Implement some general tests for the parser code

remotes/local/master
Hugo Thunnissen 3 years ago
parent f7c2a49b25
commit f7d88a90f4

@ -23,3 +23,13 @@ Example config:
(add-hook 'php-mode-hook #'my-php-personal-hook)
```
## Development
### Running tests
Tests are implemented using `ert`. You can run them in batch mode with the following
command:
```bash
emacs -batch -l ert -l ./phpinspect.el -l ./test/phpinspect-test.el -f ert-run-tests-batch-and-exit
```

@ -706,6 +706,12 @@ the properties of the class"
(goto-char (buffer-end 1))
(insert (concat (apply 'format args) "\n")))))
(defun phpinspect-parse-file (file)
(with-temp-buffer
(insert-file-contents-literally file)
(phpinspect-parse-current-buffer)))
(defun phpinspect-parse-current-buffer ()
(phpinspect-parse-buffer-until-point
(current-buffer)
@ -1507,6 +1513,9 @@ namespace if not provided"
(phpinspect--get-project-root)
class-fqn))
(defun phpinspect-index-file (file-name)
(phpinspect--index-tokens (phpinspect-parse-file file-name)))
(defun phpinspect-get-or-create-cached-project-class (project-root class-fqn)
(let ((existing-index (phpinspect-get-cached-project-class
project-root
@ -1524,9 +1533,7 @@ namespace if not provided"
(if visited-buffer
(setq new-index (with-current-buffer visited-buffer
(phpinspect--index-current-buffer)))
(setq new-index (with-temp-buffer
(insert-file-contents-literally class-file)
(phpinspect--index-current-buffer))))
(setq new-index (phpinspect-index-file class-file)))
(phpinspect--log "New index: %s" new-index)
(dolist (class (alist-get 'classes new-index))
(when class
@ -2136,7 +2143,8 @@ level of START-FILE in stead of `default-directory`."
;; Use statements
;;;###autoload
(defun phpinspect-fix-uses-interactive () "Add missing use statements to a php file"
(defun phpinspect-fix-uses-interactive ()
"Add missing use statements to the currently visited PHP file."
(interactive)
(save-buffer)
(let* ((project-root (phpinspect--get-project-root))

@ -0,0 +1 @@
(:root (:block (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "domain/manage.html.twig") (:comma ",") (:array (:string "domain") (:fat-arrow "=>") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "name")) (:comma ",") (:string "users") (:fat-arrow "=>") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findBy")) (:list (:array (:string "domain") (:fat-arrow "=>") (:variable "name")))))) (:terminator ";")))

@ -0,0 +1,8 @@
{
return new Response(
$this->twig->render('domain/manage.html.twig', [
'domain' => $this->repo->find($name),
'users' => $this->user_repo->findBy(['domain' => $name])
])
);
}

@ -0,0 +1 @@
(:root (:function (:declaration (:word "function") (:word "MergeTwoArraysAndSomeOtherStuff") (:list (:word "array") (:variable "array1") (:comma ",") (:variable "untyped_variable")) (:word "Response")) (:block (:variable "merged") (:assignment "=") (:word "array_merge") (:list (:variable "array_1") (:comma ",") (:variable "untyped_variable")) (:terminator ";") (:variable "mapped") (:assignment "=") (:word "arrap_map") (:list (:function (:declaration (:word "function") (:list (:variable "item"))) (:block (:word "return") (:variable "item") (:terminator ";"))) (:comma ",") (:variable "merged")) (:terminator ";") (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";"))) (:function (:declaration (:word "function") (:word "BeTheSecondFunctionInTheFile") (:list)) (:block (:word "return") (:array (:string "Very Impressive Result") (:fat-arrow "=>") (:variable "result")) (:terminator ";"))))

@ -0,0 +1,25 @@
<?php
function MergeTwoArraysAndSomeOtherStuff(array $array1, $untyped_variable): Response
{
$merged = array_merge($array_1, $untyped_variable);
$mapped = arrap_map(
function ($item) {
return $item;
},
$merged
);
$user = $this->user_repo->findOne($req->get('user'));
return new Response(
$this->twig->render('address/create.html.twig', [
'user' => $user,
])
);
}
function BeTheSecondFunctionInTheFile() {
return [ "Very Impressive Result" => $result ];
}

@ -0,0 +1 @@
(:root (:word "declare") (:list (:word "strict_types") (:assignment "=")) (:terminator ";") (:namespace (:word "App\\Controller") (:terminator ";") (:use (:word "Symfony\\Component\\HttpFoundation\\Response") (:terminator ";")) (:use (:word "App\\Entity\\Address") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\RedirectResponse") (:terminator ";")) (:use (:word "App\\Repository\\AddressRepository") (:terminator ";")) (:use (:word "App\\Repository\\UserRepository") (:terminator ";")) (:use (:word "Doctrine\\ORM\\EntityManagerInterface") (:terminator ";")) (:use (:word "Twig\\Environment") (:terminator ";")) (:use (:word "Symfony\\Component\\HttpFoundation\\Request") (:terminator ";")) (:use (:word "Symfony\\Component\\Routing\\Annotation\\Route") (:terminator ";")) (:class (:declaration (:word "class") (:word "AddressController")) (:block (:const (:word "A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE") (:assignment "=") (:string "a value") (:terminator ";")) (:public (:const (:word "ARRAY_CONSTANT") (:assignment "=") (:array (:string "key") (:fat-arrow "=>") (:string "value") (:comma ",") (:string "key") (:fat-arrow "=>")) (:terminator ";"))) (:private (:variable "repo") (:terminator ";")) (:private (:variable "user_repo") (:terminator ";")) (:private (:variable "twig") (:terminator ";")) (:private (:variable "em") (:terminator ";")) (:public (:function (:declaration (:word "function") (:word "__construct") (:list (:word "AddressRepository") (:variable "repo") (:comma ",") (:word "UserRepository") (:variable "user_repo") (:comma ",") (:word "Environment") (:variable "twig") (:comma ",") (:word "EntityManagerInterface") (:variable "em"))) (:block (:variable "this") (:object-attrib (:word "repo")) (:assignment "=") (:variable "repo") (:terminator ";") (:variable "this") (:object-attrib (:word "user_repo")) (:assignment "=") (:variable "user_repo") (:terminator ";") (:variable "this") (:object-attrib (:word "twig")) (:assignment "=") (:variable "twig") (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:assignment "=") (:variable "em") (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressPage") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "addAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:variable "address_string") (:assignment "=") (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address")) (:terminator ";") (:variable "address") (:assignment "=") (:word "new") (:word "Address") (:list (:variable "user") (:comma ",") (:variable "address_string")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "persist")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "user") (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";")))) (:doc-block (:annotation "Route")) (:public (:function (:declaration (:word "function") (:word "deleteAddressAction") (:list (:word "Request") (:variable "req")) (:word "Response")) (:block (:variable "address") (:assignment "=") (:variable "this") (:object-attrib (:word "repo")) (:object-attrib (:word "find")) (:list (:variable "req") (:object-attrib (:word "request")) (:object-attrib (:word "get")) (:list (:string "address"))) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "remove")) (:list (:variable "address")) (:terminator ";") (:variable "this") (:object-attrib (:word "em")) (:object-attrib (:word "flush")) (:list) (:terminator ";") (:word "return") (:word "new") (:word "RedirectResponse") (:list (:string "/user/") (:variable "address") (:object-attrib (:word "getUser")) (:list) (:object-attrib (:word "getLoginName")) (:list) (:string "/manage")) (:terminator ";"))))))))

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use App\Entity\Address;
use Symfony\Component\HttpFoundation\RedirectResponse;
use App\Repository\AddressRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Twig\Environment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class AddressController
{
const A_CONSTANT_FOR_THE_SAKE_OF_HAVING_ONE = 'a value';
public const ARRAY_CONSTANT = [
'key' => 'value',
'key' => 0
];
private $repo;
private $user_repo;
private $twig;
private $em;
public function __construct(
AddressRepository $repo,
UserRepository $user_repo,
Environment $twig,
EntityManagerInterface $em
) {
$this->repo = $repo;
$this->user_repo = $user_repo;
$this->twig = $twig;
$this->em = $em;
}
/**
* @Route("/address/add", methods={"GET"})
*/
public function addAddressPage(Request $req): Response
{
$user = $this->user_repo->findOne($req->get('user'));
return new Response(
$this->twig->render('address/create.html.twig', [
'user' => $user,
])
);
}
/**
* @Route("/address/add", methods={"POST"})
*/
public function addAddressAction(Request $req): Response
{
$user = $this->user_repo->findOne($req->request->get('user'));
$address_string = $req->request->get('address');
$address = new Address($user, $address_string);
$this->em->persist($address);
$this->em->flush();
return new RedirectResponse('/user/' . $user->getLoginName() . '/manage');
}
/**
* @Route("/address/delete", methods={"POST"})
*/
public function deleteAddressAction(Request $req): Response
{
$address = $this->repo->find($req->request->get('address'));
$this->em->remove($address);
$this->em->flush();
return new RedirectResponse('/user/' . $address->getUser()->getLoginName() . '/manage');
}
}

@ -0,0 +1 @@
(:root (:namespace (:word "App\\Functions") (:terminator ";") (:function (:declaration (:word "function") (:word "MergeTwoArraysAndSomeOtherStuff") (:list (:word "array") (:variable "array1") (:comma ",") (:variable "untyped_variable")) (:word "Response")) (:block (:variable "merged") (:assignment "=") (:word "array_merge") (:list (:variable "array_1") (:comma ",") (:variable "untyped_variable")) (:terminator ";") (:variable "mapped") (:assignment "=") (:word "arrap_map") (:list (:function (:declaration (:word "function") (:list (:variable "item"))) (:block (:word "return") (:variable "item") (:terminator ";"))) (:comma ",") (:variable "merged")) (:terminator ";") (:variable "user") (:assignment "=") (:variable "this") (:object-attrib (:word "user_repo")) (:object-attrib (:word "findOne")) (:list (:variable "req") (:object-attrib (:word "get")) (:list (:string "user"))) (:terminator ";") (:word "return") (:word "new") (:word "Response") (:list (:variable "this") (:object-attrib (:word "twig")) (:object-attrib (:word "render")) (:list (:string "address/create.html.twig") (:comma ",") (:array (:string "user") (:fat-arrow "=>") (:variable "user") (:comma ",")))) (:terminator ";"))) (:function (:declaration (:word "function") (:word "BeTheSecondFunctionInTheFile") (:list)) (:block (:word "return") (:array (:string "Very Impressive Result") (:fat-arrow "=>") (:variable "result")) (:terminator ";")))))

@ -0,0 +1,27 @@
<?php
namespace App\Functions;
function MergeTwoArraysAndSomeOtherStuff(array $array1, $untyped_variable): Response
{
$merged = array_merge($array_1, $untyped_variable);
$mapped = arrap_map(
function ($item) {
return $item;
},
$merged
);
$user = $this->user_repo->findOne($req->get('user'));
return new Response(
$this->twig->render('address/create.html.twig', [
'user' => $user,
])
);
}
function BeTheSecondFunctionInTheFile() {
return [ "Very Impressive Result" => $result ];
}

@ -0,0 +1,71 @@
;;; phpinspect-test.el --- Unit tests for phpinslect.el -*- lexical-binding: t; -*-
;; Copyright (C) 2021 Free Software Foundation, Inc.
;; Author: Hugo Thunnissen <devel@hugot.nl>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'ert)
(require 'phpinspect)
(defvar phpinspect-test-php-file-directory
(concat
(file-name-directory
(or load-file-name
buffer-file-name))
"/fixtures")
"Directory with syntax trees of example PHP files.")
(defun phpinspect-test-read-fixture-tree (name)
(with-temp-buffer
(insert-file-contents-literally (concat phpinspect-test-php-file-directory "/" name ".el"))
(read (current-buffer))))
(defun phpinspect-test-parse-fixture-code (name)
(phpinspect-parse-file
(concat phpinspect-test-php-file-directory "/" name ".php")))
(ert-deftest phpinspect-parse-namespaced-class ()
"Test phpinspect-parse on a namespaced class"
(should
(equal (phpinspect-test-read-fixture-tree "NamespacedClass")
(phpinspect-test-parse-fixture-code "NamespacedClass"))))
(ert-deftest phpinspect-parse-block ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-tree "Block")
(phpinspect-test-parse-fixture-code "Block"))))
(ert-deftest phpinspect-parse-functions ()
"Test phpinspect-parse for php functions"
(should
(equal (phpinspect-test-read-fixture-tree "Functions")
(phpinspect-test-parse-fixture-code "Functions"))))
(ert-deftest phpinspect-parse-namespaced-functions ()
"Test phpinspect-parse for php blocks"
(should
(equal (phpinspect-test-read-fixture-tree "NamespacedFunctions")
(phpinspect-test-parse-fixture-code "NamespacedFunctions"))))
(provide 'phpinspect-test)
;;; phpinspect-test.el ends here

@ -0,0 +1,13 @@
(require 'phpinspect)
(let ((here (file-name-directory
(or load-file-name
buffer-file-name))))
(dolist (file (directory-files (concat here "/../fixtures" ) t "\\.php$"))
(with-temp-buffer
(insert-file-contents-literally file)
(let ((result (phpinspect-parse-current-buffer)))
(with-temp-buffer
(insert (prin1-to-string result))
(write-file (concat (string-remove-suffix ".php" file) ".el")))))))
Loading…
Cancel
Save