diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..35ab0d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Third party +/composer.lock +/phpunit.xml +/vendor +/.couscous +/.puli diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c955756 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: php + +sudo: false + +cache: + directories: + - $HOME/.composer/cache + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +matrix: +# include: +# - php: 5.3.3 +# env: COMPOSER_FLAGS="--prefer-lowest" + allow_failures: + - php: hhvm + - php: 7.0 + +before_script: + - curl http://cs.sensiolabs.org/get/php-cs-fixer.phar -o php-cs-fixer.phar + - composer selfupdate + - composer update $COMPOSER_FLAGS + +script: + - echo '[phpspec] Running specification tests'; ./vendor/bin/phpspec run -n -f dot + - output=$(php -n php-cs-fixer.phar fix -v --dry-run --config=sf23 .); if [[ $(grep -o F <<< $output | wc -l) -gt 3 ]]; then while read -r line; do echo -e "\e[00;31m$line\e[00m"; done <<< "$output"; false; fi; diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cc04eca --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# CHANGELOG + +## 1.0.0: Import + +* imported constraints from [memio/validator](http://github.com/memio/validator) v1.0.0-rc1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..12a85c3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,63 @@ +# How to contribute + +Everybody should be able to help. Here's how you can make this project more +awesome: + +1. [Fork it](https://github.com/memio/linter/fork_select) +2. improve it +3. submit a [pull request](https://help.github.com/articles/creating-a-pull-request) + +Your work will then be reviewed as soon as possible (suggestions about some +changes, improvements or alternatives may be given). + +Here's some tips to make you the best contributor ever: + +* [Standard code](#standard-code) +* [Specifications](#specifications) +* [Keeping your fork up-to-date](#keeping-your-fork-up-to-date) + +## Standard code + +Use [PHP CS fixer](http://cs.sensiolabs.org/) to make your code compliant with +Memio Linter's coding standards: + + ./vendor/bin/php-cs-fixer fix --config=sf23 . + +## Specifications + +Memio Linter drives its development using [phpspec](http://www.phpspec.net/): + + # Generate the specification class: + phpspec describe 'Memio\Validator\MyNewClass' + + # Customize the specification class: + $EDITOR spec/Memio/Linter/MyNewClass.php + + # Generate the specified class: + phpspec run + + # Customize the class: + $EDITOR src/Memio/Linter/MyNewClass.php + + phpspec run # Should be green! + +## Keeping your fork up-to-date + +To keep your fork up-to-date, you should track the upstream (original) one +using the following command: + + git remote add upstream https://github.com/memio/linter.git + +Then get the upstream changes: + + git checkout master + git pull --rebase origin master + git pull --rebase upstream master + git checkout + git rebase master + +Finally, publish your changes: + + git push -f origin + +Your pull request will be automatically updated. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba0bc4d --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Loïc Chardonnet + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8fc85be --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +# Memio's Linter [![Travis CI](https://travis-ci.org/memio/linter.png)](https://travis-ci.org/memio/linter) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/e5794d5b-5305-4569-bc9b-caeecf9ae982/mini.png)](https://insight.sensiolabs.com/projects/e5794d5b-5305-4569-bc9b-caeecf9ae982) + +A set of [Memio constraints](http://github.com/memio/validator) that check +[Memio models](http://github.com/memio/model) for syntax errors and the likes. + +> **Note**: This package is part of [Memio](http://memio.github.io/memio), a highly opinionated PHP code generator. +> Have a look at [the main repository](http://github.com/memio/memio). + +## Installation + +Install it using [Composer](https://getcomposer.org/download): + + composer require memio/linter:~1.0 + +## Example + +Usually we'd have to install [Memio](http://github.com/memio/memio) and use its +`Build::linter()` method to get a linter validator. + +The atlernative would be to build manually the validator as follow: + +```php +add(new ArgumentCannotBeScalar()); + +$collectionValidator = new CollectionValidator(); +$collectionValidator->add(new CollectionCannotHaveNameDuplicates()); + +$methodValidator = new MethodValidator($argumentValidator, $collectionValidator); +$methodValidator->add(new MethodCannotBeAbstractAndHaveBody()); +$methodValidator->add(new MethodCannotBeBothAbstractAndFinal()); +$methodValidator->add(new MethodCannotBeBothAbstractAndPrivate()); +$methodValidator->add(new MethodCannotBeBothAbstractAndStatic()); + +$contractValidator = new ContractValidator($collectionValidator, $methodValidator); +$contractValidator->add(new ContractMethodsCanOnlyBePublic()); +$contractValidator->add(new ContractMethodsCannotBeFinal()); +$contractValidator->add(new ContractMethodsCannotBeStatic()); +$contractValidator->add(new ContractMethodsCannotHaveBody()); + +$objectValidator = new ObjectValidator($collectionValidator, $methodValidator); +$objectValidator->add(new ConcreteObjectMethodsCannotBeAbstract()); +$objectValidator->add(new ObjectArgumentCanOnlyDefaultToNull()); + +$fileValidator = new FileValidator($contractValidator, $objectValidator); + +$linter = new Validator(); +$linter->add($argumentValidator); +$linter->add($collectionValidator); +$linter->add($methodValidator); +$linter->add($contractValidator); +$linter->add($objectValidator); +$linter->add($fileValidator); + +$linter->validator($anyModels); +``` + +Have a look at [the main respository](http://github.com/memio/memio) to discover the full power of Medio. + +## Want to know more? + +Memio uses [phpspec](http://phpspec.net/), which means the tests also provide the documentation. +Not convinced? Then clone this repository and run the following commands: + + composer install + ./vendor/bin/phpspec run -n -f pretty + +You can see the current and past versions using one of the following: + +* the `git tag` command +* the [releases page on Github](https://github.com/memio/memio/releases) +* the file listing the [changes between versions](CHANGELOG.md) + +And finally some meta documentation: + +* [copyright and MIT license](LICENSE) +* [versioning and branching models](VERSIONING.md) +* [contribution instructions](CONTRIBUTING.md) diff --git a/VERSIONING.md b/VERSIONING.md new file mode 100644 index 0000000..9e005bd --- /dev/null +++ b/VERSIONING.md @@ -0,0 +1,27 @@ +# Versioning and branching models + +This file explains the versioning and branching models of this project. + +## Versioning + +The versioning is inspired by [Semantic Versioning](http://semver.org/): + +> Given a version number MAJOR.MINOR.PATCH, increment the: +> +> 1. MAJOR version when you make incompatible API changes +> 2. MINOR version when you add functionality in a backwards-compatible manner +> 3. PATCH version when you make backwards-compatible bug fixes + +### Public API + +Classes and methods marked with the `@api` tag are considered to be the public +API of this project. + +## Branching Model + +The branching is inspired by [@jbenet](https://github.com/jbenet) +[simple git branching model](https://gist.github.com/jbenet/ee6c9ac48068889b0912): + +> 1. `master` must always be deployable. +> 2. **all changes** are made through feature branches (pull-request + merge) +> 3. rebase to avoid/resolve conflicts; merge in to `master` diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3d111a3 --- /dev/null +++ b/composer.json @@ -0,0 +1,29 @@ +{ + "name": "memio/linter", + "license": "MIT", + "type": "library", + "description": "Memio's linter, a set of constraint that check models for syntax errors", + "keywords": ["generator", "PHP", "code"], + "homepage": "http://memio.github.io/memio", + "authors": [ + { + "name": "Loïc Chardonnet", + "email": "loic.chardonnet@gmail.com", + "homepage": "http://gnugat.github.io", + "role": "Developer" + } + ], + "autoload": { "psr-4": { + "Memio\\Linter\\": "src/Memio/Linter" + }}, + "require": { + "php": ">=5.3.3", + "memio/model": "~1.0", + "memio/validator": "~1.0" + }, + "require-dev": { + "ciaranmcnulty/phpspec-typehintedmethods": "~1.1", + "fabpot/php-cs-fixer": "~1.6", + "phpspec/phpspec": "~2.2" + } +} diff --git a/phpspec.yml b/phpspec.yml new file mode 100644 index 0000000..c1c2a05 --- /dev/null +++ b/phpspec.yml @@ -0,0 +1,2 @@ +extensions: + - Cjm\PhpSpec\Extension\TypeHintedMethodsExtension diff --git a/spec/Memio/Linter/CollectionCannotHaveNameDuplicatesSpec.php b/spec/Memio/Linter/CollectionCannotHaveNameDuplicatesSpec.php new file mode 100644 index 0000000..50abd5a --- /dev/null +++ b/spec/Memio/Linter/CollectionCannotHaveNameDuplicatesSpec.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Argument; +use Memio\Model\Constant; +use Memio\Model\Method; +use Memio\Model\Property; +use PhpSpec\ObjectBehavior; + +class CollectionCannotHaveNameDuplicatesSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_unique_names(Argument $argument1, Argument $argument2) + { + $argument1->getName()->willReturn('myArgument1'); + $argument2->getName()->willReturn('myArgument2'); + + $this->validate(array($argument1, $argument2))->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_name_duplicates(Argument $argument1, Argument $argument2) + { + $argument1->getName()->willReturn('myArgument'); + $argument2->getName()->willReturn('myArgument'); + + $this->validate(array($argument1, $argument2))->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ConcreteObjectMethodsCannotBeAbstractSpec.php b/spec/Memio/Linter/ConcreteObjectMethodsCannotBeAbstractSpec.php new file mode 100644 index 0000000..e5d6df4 --- /dev/null +++ b/spec/Memio/Linter/ConcreteObjectMethodsCannotBeAbstractSpec.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Object; +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class ConcreteObjectMethodsCannotBeAbstractSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_concrete_object_and_concrete_methods(Object $object, Method $method) + { + $object->getName()->willReturn('ConcreteClass'); + $object->isAbstract()->willReturn(false); + $object->allMethods()->willReturn(array($method)); + $method->isAbstract()->willReturn(false); + + $this->validate($object)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_abstract_objects(Object $object) + { + $object->isAbstract()->willReturn(true); + + $this->validate($object)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_concrete_object_and_abstract_methods(Object $object, Method $method) + { + $object->getName()->willReturn('ConcreteClass'); + $object->isAbstract()->willReturn(false); + $object->allMethods()->willReturn(array($method)); + $method->isAbstract()->willReturn(true); + $method->getName()->willReturn('abstractClass'); + + $this->validate($object)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ContractMethodsCanOnlyBePublicSpec.php b/spec/Memio/Linter/ContractMethodsCanOnlyBePublicSpec.php new file mode 100644 index 0000000..24a4f46 --- /dev/null +++ b/spec/Memio/Linter/ContractMethodsCanOnlyBePublicSpec.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Contract; +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class ContractMethodsCanOnlyBePublicSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_public_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getVisibility()->willReturn('public'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_no_visibility_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getVisibility()->willReturn(''); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_private_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getVisibility()->willReturn('private'); + $method->getName()->willReturn('handle'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } + + function it_is_not_fine_with_protected_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getVisibility()->willReturn('protected'); + $method->getName()->willReturn('handle'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ContractMethodsCannotBeFinalSpec.php b/spec/Memio/Linter/ContractMethodsCannotBeFinalSpec.php new file mode 100644 index 0000000..e9484aa --- /dev/null +++ b/spec/Memio/Linter/ContractMethodsCannotBeFinalSpec.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Contract; +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class ContractMethodsCannotBeFinalSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_simple_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->isFinal()->willReturn(false); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_protected_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->isFinal()->willReturn(true); + $method->getName()->willReturn('handle'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ContractMethodsCannotBeStaticSpec.php b/spec/Memio/Linter/ContractMethodsCannotBeStaticSpec.php new file mode 100644 index 0000000..82f1558 --- /dev/null +++ b/spec/Memio/Linter/ContractMethodsCannotBeStaticSpec.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Contract; +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class ContractMethodsCannotBeStaticSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_non_static_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->isStatic()->willReturn(false); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_static_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->isStatic()->willReturn(true); + $method->getName()->willReturn('handle'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ContractMethodsCannotHaveBodySpec.php b/spec/Memio/Linter/ContractMethodsCannotHaveBodySpec.php new file mode 100644 index 0000000..87c5203 --- /dev/null +++ b/spec/Memio/Linter/ContractMethodsCannotHaveBodySpec.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Contract; +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class ContractMethodsCannotHaveBodySpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_pure_virtual_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getBody()->willReturn(null); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_none_pure_virtual_methods(Contract $contract, Method $method) + { + $contract->getName()->willReturn('HttpKernelInterface'); + $contract->allMethods()->willReturn(array($method)); + $method->getBody()->willReturn('echo "Nobody expects the spanish inquisition";'); + $method->getName()->willReturn('handle'); + + $this->validate($contract)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/MethodCannotBeAbstractAndHaveBodySpec.php b/spec/Memio/Linter/MethodCannotBeAbstractAndHaveBodySpec.php new file mode 100644 index 0000000..44337ef --- /dev/null +++ b/spec/Memio/Linter/MethodCannotBeAbstractAndHaveBodySpec.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class MethodCannotBeAbstractAndHaveBodySpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_simple_methods(Method $method) + { + $method->isAbstract()->willReturn(false); + $method->getBody()->willReturn(''); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_abstract_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->getBody()->willReturn(null); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_abstract_methods_with_body(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->getBody()->willReturn(''); + $method->getName()->willReturn('__construct'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/MethodCannotBeBothAbstractAndFinalSpec.php b/spec/Memio/Linter/MethodCannotBeBothAbstractAndFinalSpec.php new file mode 100644 index 0000000..9600076 --- /dev/null +++ b/spec/Memio/Linter/MethodCannotBeBothAbstractAndFinalSpec.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class MethodCannotBeBothAbstractAndFinalSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_simple_methods(Method $method) + { + $method->isAbstract()->willReturn(false); + $method->isFinal()->willReturn(false); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_abstract_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->isFinal()->willReturn(false); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_final_methods(Method $method) + { + $method->isAbstract()->willReturn(false); + $method->isFinal()->willReturn(true); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_abstract_and_final_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->isFinal()->willReturn(true); + $method->getName()->willReturn('__construct'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/MethodCannotBeBothAbstractAndPrivateSpec.php b/spec/Memio/Linter/MethodCannotBeBothAbstractAndPrivateSpec.php new file mode 100644 index 0000000..2d4a417 --- /dev/null +++ b/spec/Memio/Linter/MethodCannotBeBothAbstractAndPrivateSpec.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class MethodCannotBeBothAbstractAndPrivateSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_abstract_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->getVisibility()->willReturn('public'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_private_methods(Method $method) + { + $method->isAbstract()->willReturn(false); + $method->getVisibility()->willReturn('private'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_abstract_and_private_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->getVisibility()->willReturn('private'); + $method->getName()->willReturn('__construct'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/MethodCannotBeBothAbstractAndStaticSpec.php b/spec/Memio/Linter/MethodCannotBeBothAbstractAndStaticSpec.php new file mode 100644 index 0000000..fbe61da --- /dev/null +++ b/spec/Memio/Linter/MethodCannotBeBothAbstractAndStaticSpec.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Method; +use PhpSpec\ObjectBehavior; + +class MethodCannotBeBothAbstractAndStaticSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_non_static_abstract_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->isStatic()->willReturn(false); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_abstract_and_static_methods(Method $method) + { + $method->isAbstract()->willReturn(true); + $method->isStatic()->willReturn(true); + $method->getName()->willReturn('__construct'); + + $this->validate($method)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/spec/Memio/Linter/ObjectArgumentCanOnlyDefaultToNullSpec.php b/spec/Memio/Linter/ObjectArgumentCanOnlyDefaultToNullSpec.php new file mode 100644 index 0000000..2d57acc --- /dev/null +++ b/spec/Memio/Linter/ObjectArgumentCanOnlyDefaultToNullSpec.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\Memio\Linter; + +use Memio\Model\Argument; +use Memio\Model\Constant; +use Memio\Model\Method; +use Memio\Model\Property; +use PhpSpec\ObjectBehavior; + +class ObjectArgumentCanOnlyDefaultToNullSpec extends ObjectBehavior +{ + function it_is_a_constraint() + { + $this->shouldImplement('Memio\Validator\Constraint'); + } + + function it_is_fine_with_scalar_arguments(Argument $argument) + { + $argument->getType()->willReturn('string'); + $argument->getDefaultValue()->willReturn(null); + + $this->validate($argument)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_object_argument_without_default_value(Argument $argument) + { + $argument->getType()->willReturn('DateTime'); + $argument->getDefaultValue()->willReturn(null); + + $this->validate($argument)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_fine_with_object_argument_defaulting_to_null(Argument $argument) + { + $argument->getType()->willReturn('DateTime'); + $argument->getDefaultValue()->willReturn('null'); + + $this->validate($argument)->shouldHaveType('Memio\Validator\Violation\NoneViolation'); + } + + function it_is_not_fine_with_object_argument_not_defaulting_to_null(Argument $argument) + { + $argument->getType()->willReturn('DateTime'); + $argument->getDefaultValue()->willReturn('""'); + $argument->getName()->willReturn('objectArgument'); + + $this->validate($argument)->shouldHaveType('Memio\Validator\Violation\SomeViolation'); + } +} diff --git a/src/Memio/Linter/CollectionCannotHaveNameDuplicates.php b/src/Memio/Linter/CollectionCannotHaveNameDuplicates.php new file mode 100644 index 0000000..f4041c6 --- /dev/null +++ b/src/Memio/Linter/CollectionCannotHaveNameDuplicates.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Model\FullyQualifiedName; +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class CollectionCannotHaveNameDuplicates implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $firstElement = current($model); + $fqcn = get_class($firstElement); + $modelType = FullyQualifiedName::make($fqcn)->getName(); + $nameCount = array(); + foreach ($model as $element) { + $name = $element->getName(); + $nameCount[$name] = isset($nameCount[$name]) ? $nameCount[$name] + 1 : 1; + } + $messages = array(); + foreach ($nameCount as $name => $count) { + if ($count > 1) { + $messages[] = sprintf('Collection "%s" cannot have name "%s" duplicates (%s occurences)', $modelType, $name, $count); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/ConcreteObjectMethodsCannotBeAbstract.php b/src/Memio/Linter/ConcreteObjectMethodsCannotBeAbstract.php new file mode 100644 index 0000000..cd5a542 --- /dev/null +++ b/src/Memio/Linter/ConcreteObjectMethodsCannotBeAbstract.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ConcreteObjectMethodsCannotBeAbstract implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + if ($model->isAbstract()) { + return new NoneViolation(); + } + $objectName = $model->getName(); + $messages = array(); + foreach ($model->allMethods() as $method) { + if ($method->isAbstract()) { + $messages[] = sprintf('Concrete Object "%s" Method "%s" cannot be abstract', $objectName, $method->getName()); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/ContractMethodsCanOnlyBePublic.php b/src/Memio/Linter/ContractMethodsCanOnlyBePublic.php new file mode 100644 index 0000000..7c5b344 --- /dev/null +++ b/src/Memio/Linter/ContractMethodsCanOnlyBePublic.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ContractMethodsCanOnlyBePublic implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $contractName = $model->getName(); + $messages = array(); + foreach ($model->allMethods() as $method) { + $visibility = $method->getVisibility(); + if ('' !== $visibility && 'public' !== $visibility) { + $messages[] = sprintf('Contract "%s" Method "%s" can only be public', $contractName, $method->getName()); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/ContractMethodsCannotBeFinal.php b/src/Memio/Linter/ContractMethodsCannotBeFinal.php new file mode 100644 index 0000000..3fe5d57 --- /dev/null +++ b/src/Memio/Linter/ContractMethodsCannotBeFinal.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ContractMethodsCannotBeFinal implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $contractName = $model->getName(); + $messages = array(); + foreach ($model->allMethods() as $method) { + if ($method->isFinal()) { + $messages[] = sprintf('Contract "%s" Method "%s" cannot be final', $contractName, $method->getName()); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/ContractMethodsCannotBeStatic.php b/src/Memio/Linter/ContractMethodsCannotBeStatic.php new file mode 100644 index 0000000..9de47a8 --- /dev/null +++ b/src/Memio/Linter/ContractMethodsCannotBeStatic.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ContractMethodsCannotBeStatic implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $contractName = $model->getName(); + $messages = array(); + foreach ($model->allMethods() as $method) { + if ($method->isStatic()) { + $messages[] = sprintf('Contract "%s" Method "%s" cannot be static', $contractName, $method->getName()); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/ContractMethodsCannotHaveBody.php b/src/Memio/Linter/ContractMethodsCannotHaveBody.php new file mode 100644 index 0000000..c303236 --- /dev/null +++ b/src/Memio/Linter/ContractMethodsCannotHaveBody.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ContractMethodsCannotHaveBody implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $contractName = $model->getName(); + $messages = array(); + foreach ($model->allMethods() as $method) { + if (null !== $method->getBody()) { + $messages[] = sprintf('Contract "%s" Method "%s" cannot have a body', $contractName, $method->getName()); + } + } + + return (empty($messages) ? new NoneViolation() : new SomeViolation(implode("\n", $messages))); + } +} diff --git a/src/Memio/Linter/MethodCannotBeAbstractAndHaveBody.php b/src/Memio/Linter/MethodCannotBeAbstractAndHaveBody.php new file mode 100644 index 0000000..85004ea --- /dev/null +++ b/src/Memio/Linter/MethodCannotBeAbstractAndHaveBody.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class MethodCannotBeAbstractAndHaveBody implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + if ($model->isAbstract() && null !== $model->getBody()) { + return new SomeViolation(sprintf('Method "%s" cannot be abstract and have a body', $model->getName())); + } + + return new NoneViolation(); + } +} diff --git a/src/Memio/Linter/MethodCannotBeBothAbstractAndFinal.php b/src/Memio/Linter/MethodCannotBeBothAbstractAndFinal.php new file mode 100644 index 0000000..1c2bc61 --- /dev/null +++ b/src/Memio/Linter/MethodCannotBeBothAbstractAndFinal.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class MethodCannotBeBothAbstractAndFinal implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + if ($model->isAbstract() && $model->isFinal()) { + return new SomeViolation(sprintf('Method "%s" cannot be both abstract and final', $model->getName())); + } + + return new NoneViolation(); + } +} diff --git a/src/Memio/Linter/MethodCannotBeBothAbstractAndPrivate.php b/src/Memio/Linter/MethodCannotBeBothAbstractAndPrivate.php new file mode 100644 index 0000000..e882711 --- /dev/null +++ b/src/Memio/Linter/MethodCannotBeBothAbstractAndPrivate.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class MethodCannotBeBothAbstractAndPrivate implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + if ($model->isAbstract() && 'private' === $model->getVisibility()) { + return new SomeViolation(sprintf('Method "%s" cannot be both abstract and private', $model->getName())); + } + + return new NoneViolation(); + } +} diff --git a/src/Memio/Linter/MethodCannotBeBothAbstractAndStatic.php b/src/Memio/Linter/MethodCannotBeBothAbstractAndStatic.php new file mode 100644 index 0000000..4d47af2 --- /dev/null +++ b/src/Memio/Linter/MethodCannotBeBothAbstractAndStatic.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class MethodCannotBeBothAbstractAndStatic implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + if ($model->isAbstract() && $model->isStatic()) { + return new SomeViolation(sprintf('Method "%s" cannot be both abstract and static', $model->getName())); + } + + return new NoneViolation(); + } +} diff --git a/src/Memio/Linter/ObjectArgumentCanOnlyDefaultToNull.php b/src/Memio/Linter/ObjectArgumentCanOnlyDefaultToNull.php new file mode 100644 index 0000000..d6dba4e --- /dev/null +++ b/src/Memio/Linter/ObjectArgumentCanOnlyDefaultToNull.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Memio\Linter; + +use Memio\Model\Type; +use Memio\Validator\Constraint; +use Memio\Validator\Violation\NoneViolation; +use Memio\Validator\Violation\SomeViolation; + +class ObjectArgumentCanOnlyDefaultToNull implements Constraint +{ + /** + * {@inheritDoc} + */ + public function validate($model) + { + $type = new Type($model->getType()); + $defaultValue = $model->getDefaultValue(); + if (!$type->isObject() || null === $defaultValue || 'null' === $defaultValue) { + return new NoneViolation(); + } + + return new SomeViolation(sprintf('Object Argument "%s" can only default to null', $model->getName())); + } +}