How to use AstNode class

Best Gherkin-php code snippet using AstNode

UriTemplateParserTest.php

Source:UriTemplateParserTest.php Github

copy

Full Screen

...11use Aphiria\Routing\UriTemplates\Lexers\Token;12use Aphiria\Routing\UriTemplates\Lexers\TokenStream;13use Aphiria\Routing\UriTemplates\Lexers\TokenType;14use Aphiria\Routing\UriTemplates\Lexers\UnexpectedTokenException;15use Aphiria\Routing\UriTemplates\Parsers\AstNode;16use Aphiria\Routing\UriTemplates\Parsers\AstNodeType;17use Aphiria\Routing\UriTemplates\Parsers\UriTemplateParser;18use PHPUnit\Framework\TestCase;19class UriTemplateParserTest extends TestCase20{21    private UriTemplateParser $parser;22    protected function setUp(): void23    {24        $this->parser = new UriTemplateParser();25    }26    public function testParsingClosingBracketWhenNotParsingOptionalRoutePartTreatsBracketAsText(): void27    {28        $tokens = new TokenStream([29            new Token(TokenType::Punctuation, '/'),30            new Token(TokenType::Punctuation, ']')31        ]);32        $pathNode = new AstNode(AstNodeType::Path);33        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));34        $pathNode->addChild(new AstNode(AstNodeType::Text, ']'));35        $expectedAst = new AstNode(AstNodeType::Root);36        $expectedAst->addChild($pathNode);37        $this->assertEquals($expectedAst, $this->parser->parse($tokens));38    }39    public function testParsingInvalidBracketInMiddleOfConstraintThrowsException(): void40    {41        $this->expectException(UnexpectedTokenException::class);42        $this->expectExceptionMessage("Expected optional path part to start with '/', got " . TokenType::Variable->name);43        $tokens = new TokenStream([44            new Token(TokenType::Punctuation, '/'),45            new Token(TokenType::Punctuation, '['),46            new Token(TokenType::Variable, 'foo'),47            new Token(TokenType::Punctuation, '('),48            new Token(TokenType::Punctuation, ']'),49        ]);50        $this->parser->parse($tokens);51    }52    public function testParsingNestedOptionalPathParts(): void53    {54        $tokens = new TokenStream([55            new Token(TokenType::Punctuation, '/'),56            new Token(TokenType::Punctuation, '['),57            new Token(TokenType::Punctuation, '/'),58            new Token(TokenType::Text, 'foo'),59            new Token(TokenType::Punctuation, '['),60            new Token(TokenType::Punctuation, '/'),61            new Token(TokenType::Text, 'bar'),62            new Token(TokenType::Punctuation, ']'),63            new Token(TokenType::Punctuation, ']')64        ]);65        $innerOptionalRoutePartNode = new AstNode(AstNodeType::OptionalRoutePart, '[');66        $innerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));67        $innerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::Text, 'bar'));68        $outerOptionalRoutePartNode = new AstNode(AstNodeType::OptionalRoutePart, '[');69        $outerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));70        $outerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::Text, 'foo'));71        $outerOptionalRoutePartNode->addChild($innerOptionalRoutePartNode);72        $pathNode = new AstNode(AstNodeType::Path, null);73        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));74        $pathNode->addChild($outerOptionalRoutePartNode);75        $expectedAst = new AstNode(AstNodeType::Root, null);76        $expectedAst->addChild($pathNode);77        $this->assertEquals($expectedAst, $this->parser->parse($tokens));78    }79    public function testParsingNestedOptionalHostPartCreatesNestedOptionalPartNodes(): void80    {81        $tokens = new TokenStream([82            new Token(TokenType::Punctuation, '['),83            new Token(TokenType::Text, 'foo'),84            new Token(TokenType::Punctuation, '.'),85            new Token(TokenType::Punctuation, '['),86            new Token(TokenType::Text, 'bar'),87            new Token(TokenType::Punctuation, '.'),88            new Token(TokenType::Punctuation, ']'),89            new Token(TokenType::Punctuation, ']'),90            new Token(TokenType::Text, 'example'),91            new Token(TokenType::Punctuation, '.'),92            new Token(TokenType::Text, 'com'),93            new Token(TokenType::Punctuation, '/'),94            new Token(TokenType::Text, 'foo')95        ]);96        $expectedAst = new AstNode(AstNodeType::Root, null);97        $hostNode = new AstNode(AstNodeType::Host, null);98        $expectedAst->addChild($hostNode);99        $innerOptionalRoutePartNode = new AstNode(AstNodeType::OptionalRoutePart, '[');100        $innerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::Text, 'bar'));101        $innerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'));102        $outerOptionalRoutePartNode = new AstNode(AstNodeType::OptionalRoutePart, '[');103        $outerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::Text, 'foo'));104        $outerOptionalRoutePartNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'));105        $outerOptionalRoutePartNode->addChild($innerOptionalRoutePartNode);106        $hostNode->addChild($outerOptionalRoutePartNode);107        $hostNode->addChild(new AstNode(AstNodeType::Text, 'example'));108        $hostNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'));109        $hostNode->addChild(new AstNode(AstNodeType::Text, 'com'));110        $pathNode = new AstNode(AstNodeType::Path, null);111        $expectedAst->addChild($pathNode);112        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));113        $pathNode->addChild(new AstNode(AstNodeType::Text, 'foo'));114        $this->assertEquals($expectedAst, $this->parser->parse($tokens));115    }116    public function testParsingNestedOptionalHostPartThatDoesEndWithPeriodThrowsException(): void117    {118        $this->expectException(UnexpectedTokenException::class);119        $this->expectExceptionMessage("Expected optional host part to end with '.'");120        $tokens = new TokenStream([121            new Token(TokenType::Punctuation, '['),122            new Token(TokenType::Text, 'foo'),123            new Token(TokenType::Punctuation, '.'),124            new Token(TokenType::Punctuation, '['),125            new Token(TokenType::Text, 'bar'),126            new Token(TokenType::Punctuation, ']'),127            new Token(TokenType::Punctuation, ']'),128            new Token(TokenType::Text, 'example'),129            new Token(TokenType::Punctuation, '.'),130            new Token(TokenType::Text, 'com'),131            new Token(TokenType::Punctuation, '/'),132            new Token(TokenType::Text, 'foo')133        ]);134        $this->parser->parse($tokens);135    }136    public function testParsingNonStandardPunctuationJustGetsTreatedAsText(): void137    {138        $tokens = new TokenStream([139            new Token(TokenType::Punctuation, '/'),140            new Token(TokenType::Punctuation, '!')141        ]);142        $pathNode = new AstNode(AstNodeType::Path);143        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));144        $pathNode->addChild(new AstNode(AstNodeType::Text, '!'));145        $expectedAst = new AstNode(AstNodeType::Root);146        $expectedAst->addChild($pathNode);147        $this->assertEquals($expectedAst, $this->parser->parse($tokens));148    }149    public function testParsingOptionalHostPartThatDoesEndWithPeriodThrowsException(): void150    {151        $this->expectException(UnexpectedTokenException::class);152        $this->expectExceptionMessage("Expected optional host part to end with '.'");153        $tokens = new TokenStream([154            new Token(TokenType::Punctuation, '['),155            new Token(TokenType::Text, 'api'),156            new Token(TokenType::Punctuation, ']'),157            new Token(TokenType::Text, 'example'),158            new Token(TokenType::Punctuation, '.'),159            new Token(TokenType::Text, 'com'),160            new Token(TokenType::Punctuation, '/'),161            new Token(TokenType::Text, 'foo')162        ]);163        $this->parser->parse($tokens);164    }165    public function testParsingOptionalPathPartCreatesCorrectNodes(): void166    {167        $tokens = new TokenStream([168            new Token(TokenType::Punctuation, '/'),169            new Token(TokenType::Text, 'foo'),170            new Token(TokenType::Punctuation, '['),171            new Token(TokenType::Punctuation, '/'),172            new Token(TokenType::Text, 'bar'),173            new Token(TokenType::Punctuation, ']')174        ]);175        $expectedAst = new AstNode(AstNodeType::Root, null);176        $pathNode = new AstNode(AstNodeType::Path, null);177        $expectedAst->addChild($pathNode);178        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));179        $pathNode->addChild(new AstNode(AstNodeType::Text, 'foo'));180        $optionalRoutePartNode = new AstNode(AstNodeType::OptionalRoutePart, '[');181        $optionalRoutePartNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));182        $optionalRoutePartNode->addChild(new AstNode(AstNodeType::Text, 'bar'));183        $pathNode->addChild($optionalRoutePartNode);184        $this->assertEquals($expectedAst, $this->parser->parse($tokens));185    }186    public function testParsingOptionalPathPartThatDoesNotBeginWithSlashThrowsException(): void187    {188        $this->expectException(UnexpectedTokenException::class);189        $this->expectExceptionMessage("Expected optional path part to start with '/', got " . TokenType::Text->name);190        $tokens = new TokenStream([191            new Token(TokenType::Punctuation, '/'),192            new Token(TokenType::Text, 'foo'),193            new Token(TokenType::Punctuation, '['),194            new Token(TokenType::Text, 'bar'),195            new Token(TokenType::Punctuation, ']')196        ]);197        $this->parser->parse($tokens);198    }199    public function testParsingTextOnlyPathCreatesSingleTextNode(): void200    {201        $tokens = new TokenStream([202            new Token(TokenType::Punctuation, '/'),203            new Token(TokenType::Text, 'foo')204        ]);205        $expectedAst = new AstNode(AstNodeType::Root, null);206        $pathNode = new AstNode(AstNodeType::Path, null);207        $expectedAst->addChild($pathNode);208        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));209        $pathNode->addChild(new AstNode(AstNodeType::Text, 'foo'));210        $this->assertEquals($expectedAst, $this->parser->parse($tokens));211    }212    public function testParsingNumberOnlyPathCreatesSingleNumber(): void213    {214        $tokens = new TokenStream([215            new Token(TokenType::Punctuation, '/'),216            new Token(TokenType::Number, 12345)217        ]);218        $expectedAst = new AstNode(AstNodeType::Root, null);219        $pathNode = new AstNode(AstNodeType::Path, null);220        $expectedAst->addChild($pathNode);221        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));222        $pathNode->addChild(new AstNode(AstNodeType::Text, 12345));223        $this->assertEquals($expectedAst, $this->parser->parse($tokens));224    }225    public function testParsingPeriodInPathCreatesTextNode(): void226    {227        $tokens = new TokenStream([228            new Token(TokenType::Text, 'example'),229            new Token(TokenType::Punctuation, '.'),230            new Token(TokenType::Text, 'com'),231            new Token(TokenType::Punctuation, '/'),232            new Token(TokenType::Text, 'foo'),233            new Token(TokenType::Punctuation, '.'),234            new Token(TokenType::Text, 'bar'),235        ]);236        $expectedAst = new AstNode(AstNodeType::Root, null);237        $hostNode = new AstNode(AstNodeType::Host, null);238        $pathNode = new AstNode(AstNodeType::Path, null);239        $expectedAst->addChild($hostNode);240        $expectedAst->addChild($pathNode);241        $hostNode->addChild(new AstNode(AstNodeType::Text, 'example'));242        $hostNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'));243        $hostNode->addChild(new AstNode(AstNodeType::Text, 'com'));244        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));245        $pathNode->addChild(new AstNode(AstNodeType::Text, 'foo'));246        $pathNode->addChild(new AstNode(AstNodeType::Text, '.'));247        $pathNode->addChild(new AstNode(AstNodeType::Text, 'bar'));248        $this->assertEquals($expectedAst, $this->parser->parse($tokens));249    }250    public function testParsingQuotedStringOnlyPathCreatesSingleString(): void251    {252        $tokens = new TokenStream([253            new Token(TokenType::Punctuation, '/'),254            new Token(TokenType::QuotedString, '"12345"')255        ]);256        $expectedAst = new AstNode(AstNodeType::Root, null);257        $pathNode = new AstNode(AstNodeType::Path, null);258        $expectedAst->addChild($pathNode);259        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));260        $pathNode->addChild(new AstNode(AstNodeType::Text, '"12345"'));261        $this->assertEquals($expectedAst, $this->parser->parse($tokens));262    }263    public function testParsingSequentialVariablesThrowsException(): void264    {265        $this->expectException(UnexpectedTokenException::class);266        $this->expectExceptionMessage('Cannot have consecutive variables without a delimiter');267        $tokens = new TokenStream([268            new Token(TokenType::Punctuation, '/'),269            new Token(TokenType::Variable, 'foo'),270            new Token(TokenType::Variable, 'foo')271        ]);272        $this->parser->parse($tokens);273    }274    public function testParsingUnclosedConstraintParenthesisThrowsException(): void275    {276        $this->expectException(UnexpectedTokenException::class);277        $this->expectExceptionMessage('Expected closing parenthesis after constraints, got ' . TokenType::Eof->name);278        $tokens = new TokenStream([279            new Token(TokenType::Punctuation, '/'),280            new Token(TokenType::Variable, 'foo'),281            new Token(TokenType::Punctuation, '('),282            new Token(TokenType::Text, 'bar'),283        ]);284        $this->parser->parse($tokens);285    }286    public function testParsingVariableInPathCreatesVariableNameNode(): void287    {288        $tokens = new TokenStream([289            new Token(TokenType::Punctuation, '/'),290            new Token(TokenType::Variable, 'foo')291        ]);292        $expectedAst = new AstNode(AstNodeType::Root, null);293        $pathNode = new AstNode(AstNodeType::Path, null);294        $expectedAst->addChild($pathNode);295        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));296        $pathNode->addChild(new AstNode(AstNodeType::Variable, 'foo'));297        $this->assertEquals($expectedAst, $this->parser->parse($tokens));298    }299    public function testParsingVariableInPathWithConstraintWithMultipleParametersCreatesCorrectNodes(): void300    {301        $tokens = new TokenStream([302            new Token(TokenType::Punctuation, '/'),303            new Token(TokenType::Variable, 'foo'),304            new Token(TokenType::Punctuation, '('),305            new Token(TokenType::Text, 'bar'),306            new Token(TokenType::Punctuation, '('),307            new Token(TokenType::QuotedString, 'baz'),308            new Token(TokenType::Punctuation, ','),309            new Token(TokenType::Text, 'blah'),310            new Token(TokenType::Punctuation, ')'),311            new Token(TokenType::Punctuation, ')')312        ]);313        $expectedAst = new AstNode(AstNodeType::Root, null);314        $pathNode = new AstNode(AstNodeType::Path, null);315        $expectedAst->addChild($pathNode);316        $variableConstraintNode = new AstNode(AstNodeType::VariableConstraint, 'bar');317        $variableConstraintNode->addChild(new AstNode(AstNodeType::VariableConstraintParameters, ['baz', 'blah']));318        $variableNode = new AstNode(AstNodeType::Variable, 'foo');319        $variableNode->addChild($variableConstraintNode);320        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));321        $pathNode->addChild($variableNode);322        $this->assertEquals($expectedAst, $this->parser->parse($tokens));323    }324    public function testParsingVariableInPathWithConstraintWithNoParametersCreatesCorrectNodes(): void325    {326        $tokens = new TokenStream([327            new Token(TokenType::Punctuation, '/'),328            new Token(TokenType::Variable, 'foo'),329            new Token(TokenType::Punctuation, '('),330            new Token(TokenType::Text, 'bar'),331            new Token(TokenType::Punctuation, ')')332        ]);333        $expectedAst = new AstNode(AstNodeType::Root, null);334        $pathNode = new AstNode(AstNodeType::Path, null);335        $expectedAst->addChild($pathNode);336        $variableConstraintNode = new AstNode(AstNodeType::VariableConstraint, 'bar');337        $variableNode = new AstNode(AstNodeType::Variable, 'foo');338        $variableNode->addChild($variableConstraintNode);339        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));340        $pathNode->addChild($variableNode);341        $this->assertEquals($expectedAst, $this->parser->parse($tokens));342    }343    public function testParsingVariableInPathWithConstraintWithSingleParameterCreatesCorrectNodes(): void344    {345        $tokens = new TokenStream([346            new Token(TokenType::Punctuation, '/'),347            new Token(TokenType::Variable, 'foo'),348            new Token(TokenType::Punctuation, '('),349            new Token(TokenType::Text, 'bar'),350            new Token(TokenType::Punctuation, '('),351            new Token(TokenType::QuotedString, 'baz'),352            new Token(TokenType::Punctuation, ')'),353            new Token(TokenType::Punctuation, ')')354        ]);355        $expectedAst = new AstNode(AstNodeType::Root, null);356        $pathNode = new AstNode(AstNodeType::Path, null);357        $expectedAst->addChild($pathNode);358        $variableConstraintNode = new AstNode(AstNodeType::VariableConstraint, 'bar');359        $variableConstraintNode->addChild(new AstNode(AstNodeType::VariableConstraintParameters, ['baz']));360        $variableNode = new AstNode(AstNodeType::Variable, 'foo');361        $variableNode->addChild($variableConstraintNode);362        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));363        $pathNode->addChild($variableNode);364        $this->assertEquals($expectedAst, $this->parser->parse($tokens));365    }366    public function testParsingVariableInPathWithConstraintButWithNoSlugThrowsException(): void367    {368        $this->expectException(UnexpectedTokenException::class);369        $this->expectExceptionMessage('Expected constraint name, got ' . TokenType::Punctuation->name);370        $tokens = new TokenStream([371            new Token(TokenType::Punctuation, '/'),372            new Token(TokenType::Variable, 'foo'),373            new Token(TokenType::Punctuation, '('),374            new Token(TokenType::Punctuation, ')')375        ]);376        $this->parser->parse($tokens);377    }378    public function testParsingVariableInPathWithConstraintWithTrailingCommaDoesNotThrowException(): void379    {380        $tokens = new TokenStream([381            new Token(TokenType::Punctuation, '/'),382            new Token(TokenType::Variable, 'foo'),383            new Token(TokenType::Punctuation, '('),384            new Token(TokenType::Text, 'bar'),385            new Token(TokenType::Punctuation, '('),386            new Token(TokenType::QuotedString, 'baz'),387            new Token(TokenType::Punctuation, ','),388            new Token(TokenType::Punctuation, ')'),389            new Token(TokenType::Punctuation, ')')390        ]);391        $expectedAst = new AstNode(AstNodeType::Root, null);392        $pathNode = new AstNode(AstNodeType::Path, null);393        $expectedAst->addChild($pathNode);394        $variableConstraintNode = new AstNode(AstNodeType::VariableConstraint, 'bar');395        $variableConstraintNode->addChild(new AstNode(AstNodeType::VariableConstraintParameters, ['baz']));396        $variableNode = new AstNode(AstNodeType::Variable, 'foo');397        $variableNode->addChild($variableConstraintNode);398        $pathNode->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));399        $pathNode->addChild($variableNode);400        $this->assertEquals($expectedAst, $this->parser->parse($tokens));401    }402}...

Full Screen

Full Screen

TrieCompilerTest.php

Source:TrieCompilerTest.php Github

copy

Full Screen

...22use Aphiria\Routing\UriTemplates\Lexers\IUriTemplateLexer;23use Aphiria\Routing\UriTemplates\Lexers\LexingException;24use Aphiria\Routing\UriTemplates\Lexers\TokenStream;25use Aphiria\Routing\UriTemplates\Lexers\UnexpectedTokenException;26use Aphiria\Routing\UriTemplates\Parsers\AstNode;27use Aphiria\Routing\UriTemplates\Parsers\AstNodeType;28use Aphiria\Routing\UriTemplates\Parsers\IUriTemplateParser;29use Aphiria\Routing\UriTemplates\UriTemplate;30use PHPUnit\Framework\MockObject\MockObject;31use PHPUnit\Framework\TestCase;32class TrieCompilerTest extends TestCase33{34    private TrieCompiler $compiler;35    private RouteVariableConstraintFactory $constraintFactory;36    private IUriTemplateParser&MockObject $parser;37    private IUriTemplateLexer&MockObject $lexer;38    private AstNode $ast;39    private RootTrieNode $expectedTrie;40    protected function setUp(): void41    {42        $this->constraintFactory = new RouteVariableConstraintFactory();43        $this->parser = $this->createMock(IUriTemplateParser::class);44        $this->lexer = $this->createMock(IUriTemplateLexer::class);45        $this->ast = new AstNode(AstNodeType::Root, null);46        $this->parser->method('parse')47            ->willReturn($this->ast);48        $this->compiler = new TrieCompiler($this->constraintFactory, $this->parser, $this->lexer);49        $this->expectedTrie = new RootTrieNode();50    }51    public function testCompilingEmptyPathPrependsWithSlash(): void52    {53        $pathAst = (new AstNode(AstNodeType::Path, null))54            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'));55        $this->ast->addChild($pathAst);56        $expectedRoute = $this->createRoute('');57        $this->expectedTrie->addChild(new LiteralTrieNode(58            '',59            [],60            $expectedRoute61        ));62        $this->lexer->expects($this->once())63            ->method('lex')64            ->with('/')65            ->willReturn(new TokenStream([]));66        $this->assertEquals(67            $this->expectedTrie,68            $this->compiler->compile($expectedRoute)69        );70    }71    public function testCompilingHostAddsTrieNodeToLastPathNodeAndOptionalNodes(): void72    {73        $hostAst = (new AstNode(AstNodeType::Host, null))74            ->addChild(new AstNode(AstNodeType::Text, 'example'))75            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'))76            ->addChild(new AstNode(AstNodeType::Text, 'com'));77        $this->ast->addChild($hostAst);78        $pathAst = (new AstNode(AstNodeType::Path, null))79            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))80            ->addChild(new AstNode(AstNodeType::Text, 'foo'))81            ->addChild(82                (new AstNode(AstNodeType::OptionalRoutePart, '['))83                    ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))84                    ->addChild(new AstNode(AstNodeType::Text, 'bar'))85            );86        $this->ast->addChild($pathAst);87        $hostTemplate = 'example.com';88        $pathTemplate = '/foo[/bar]';89        $expectedRoute = $this->createRoute($pathTemplate, $hostTemplate);90        $expectedHostTrie = new RootTrieNode([91            new LiteralTrieNode(92                'com',93                [94                    new LiteralTrieNode(95                        'example',96                        [],97                        $expectedRoute98                    )99                ]100            )101        ]);102        $this->expectedTrie->addChild(new LiteralTrieNode(103            'foo',104            [105                new LiteralTrieNode('bar', [], [], $expectedHostTrie)106            ],107            [],108            $expectedHostTrie109        ));110        $this->lexer->expects($this->once())111            ->method('lex')112            ->with($hostTemplate . $pathTemplate)113            ->willReturn(new TokenStream([]));114        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));115    }116    public function testCompilingHostWithOptionalPartAddsRouteToItAndLastNonOptionalHostPart(): void117    {118        $hostAst = (new AstNode(AstNodeType::Host, null))119            ->addChild(120                (new AstNode(AstNodeType::OptionalRoutePart, '['))121                    ->addChild(new AstNode(AstNodeType::Text, 'api'))122                    ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'))123            )124            ->addChild(new AstNode(AstNodeType::Text, 'example'))125            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '.'))126            ->addChild(new AstNode(AstNodeType::Text, 'com'));127        $this->ast->addChild($hostAst);128        $pathAst = (new AstNode(AstNodeType::Path, null))129            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))130            ->addChild(new AstNode(AstNodeType::Text, 'foo'));131        $this->ast->addChild($pathAst);132        $hostTemplate = 'example.com';133        $pathTemplate = '/foo';134        $expectedRoute = $this->createRoute($pathTemplate, $hostTemplate);135        $this->expectedTrie->addChild(new LiteralTrieNode(136            'foo',137            [],138            [],139            new RootTrieNode([140                new LiteralTrieNode(141                    'com',142                    [143                        new LiteralTrieNode(144                            'example',145                            [146                                new LiteralTrieNode(147                                    'api',148                                    [],149                                    $expectedRoute150                                )151                            ],152                            $expectedRoute153                        )154                    ]155                )156            ])157        ));158        $this->lexer->expects($this->once())159            ->method('lex')160            ->with($hostTemplate . $pathTemplate)161            ->willReturn(new TokenStream([]));162        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));163    }164    public function testCompilingInvalidVariableNodeThrowsException(): void165    {166        $this->expectException(InvalidUriTemplateException::class);167        $this->expectExceptionMessage('Unexpected node type ' . AstNodeType::Path->name);168        $variableNode = new AstNode(AstNodeType::Variable, 'foo');169        // Add an invalid child to the variable node170        $variableNode->addChild(new AstNode(AstNodeType::Path, null));171        $pathAst = (new AstNode(AstNodeType::Path, null))172            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))173            ->addChild($variableNode);174        $this->ast->addChild($pathAst);175        $pathTemplate = '/:foo';176        $expectedRoute = $this->createRoute($pathTemplate);177        $this->expectedTrie->addChild(new VariableTrieNode(178            new RouteVariable('foo'),179            [],180            $expectedRoute181        ));182        $this->lexer->expects($this->once())183            ->method('lex')184            ->with($pathTemplate)185            ->willReturn(new TokenStream([]));186        $this->compiler->compile($expectedRoute);187    }188    public function testCompilingPathVariableCreatesVariableNodeWithRouteVariable(): void189    {190        $pathAst = (new AstNode(AstNodeType::Path, null))191            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))192            ->addChild(new AstNode(AstNodeType::Variable, 'foo'));193        $this->ast->addChild($pathAst);194        $pathTemplate = '/:foo';195        $expectedRoute = $this->createRoute($pathTemplate);196        $this->expectedTrie->addChild(new VariableTrieNode(197            new RouteVariable('foo'),198            [],199            $expectedRoute200        ));201        $this->lexer->expects($this->once())202            ->method('lex')203            ->with($pathTemplate)204            ->willReturn(new TokenStream([]));205        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));206    }207    public function testCompilingPathVariableWithMultipleConstraintsAndParamsCreatesVariableNodeWithConstraints(): void208    {209        // Set up AST210        $constraint1Node = (new AstNode(AstNodeType::VariableConstraint, 'r1'))211            ->addChild(new AstNode(AstNodeType::VariableConstraintParameters, ['p1', 'p2']));212        $constraint2Node = (new AstNode(AstNodeType::VariableConstraint, 'r2'))213            ->addChild(new AstNode(AstNodeType::VariableConstraintParameters, ['p3', 'p4']));214        $variableNode = (new AstNode(AstNodeType::Variable, 'foo'))215            ->addChild($constraint1Node)216            ->addChild($constraint2Node);217        $pathAst = (new AstNode(AstNodeType::Path, null))218            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))219            ->addChild($variableNode);220        $this->ast->addChild($pathAst);221        // Set up constraint factory222        /** @var IRouteVariableConstraint&MockObject $constraint1 */223        $constraint1 = $this->createMock(IRouteVariableConstraint::class);224        /** @var IRouteVariableConstraint&MockObject $constraint2 */225        $constraint2 = $this->createMock(IRouteVariableConstraint::class);226        $this->constraintFactory->registerConstraintFactory('r1', fn (string $p1, string $p2) => $constraint1);227        $this->constraintFactory->registerConstraintFactory('r2', fn (string $p1, string $p2) => $constraint1);228        // Test compiling229        $pathTemplate = '/:foo(r1(p1,p2),r2(p3,p4))';230        $expectedRoute = $this->createRoute($pathTemplate);231        $this->expectedTrie->addChild(new VariableTrieNode(232            new RouteVariable('foo', [$constraint1, $constraint2]),233            [],234            $expectedRoute235        ));236        $this->lexer->expects($this->once())237            ->method('lex')238            ->with($pathTemplate)239            ->willReturn(new TokenStream([]));240        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));241    }242    public function testCompilingPathVariableWithNonConstraintChildThrowsException(): void243    {244        $this->expectException(InvalidUriTemplateException::class);245        $constraintNode = (new AstNode(AstNodeType::VariableConstraint, 'foo'))246            ->addChild(new AstNode(AstNodeType::Text, 'bar'));247        $pathAst = (new AstNode(AstNodeType::Path, null))248            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))249            ->addChild($constraintNode);250        $this->ast->addChild($pathAst);251        $pathTemplate = '/:foo';252        $this->lexer->expects($this->once())253            ->method('lex')254            ->with($pathTemplate)255            ->willReturn(new TokenStream([]));256        $this->compiler->compile($this->createRoute($pathTemplate));257    }258    public function testCompilingPathVariableWithConstraintsCreatesVariableNodeWithConstraints(): void259    {260        // Set up AST261        $variableNode = (new AstNode(AstNodeType::Variable, 'foo'))262            ->addChild(new AstNode(AstNodeType::VariableConstraint, 'r1'));263        $pathAst = (new AstNode(AstNodeType::Path, null))264            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))265            ->addChild($variableNode);266        $this->ast->addChild($pathAst);267        // Set up constraint factory268        /** @var IRouteVariableConstraint&MockObject $constraint */269        $constraint = $this->createMock(IRouteVariableConstraint::class);270        $this->constraintFactory->registerConstraintFactory('r1', fn () => $constraint);271        // Test compiling272        $pathTemplate = '/:foo(r1)';273        $expectedRoute = $this->createRoute($pathTemplate);274        $this->expectedTrie->addChild(new VariableTrieNode(275            new RouteVariable('foo', [$constraint]),276            [],277            $expectedRoute278        ));279        $this->lexer->expects($this->once())280            ->method('lex')281            ->with($pathTemplate)282            ->willReturn(new TokenStream([]));283        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));284    }285    public function testCompilingRequiredAndOptionalPathSegmentsCreatesNodesWithSameRoute(): void286    {287        $optionalNode = (new AstNode(AstNodeType::OptionalRoutePart))288            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))289            ->addChild(new AstNode(AstNodeType::Text, 'bar'));290        $pathAst = (new AstNode(AstNodeType::Path, null))291            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))292            ->addChild(new AstNode(AstNodeType::Text, 'foo'))293            ->addChild($optionalNode);294        $this->ast->addChild($pathAst);295        $pathTemplate = '/foo[/bar]';296        $expectedRoute = $this->createRoute($pathTemplate);297        $this->expectedTrie->addChild(new LiteralTrieNode(298            'foo',299            [300                new LiteralTrieNode(301                    'bar',302                    [],303                    $expectedRoute304                )305            ],306            $expectedRoute307        ));308        $this->lexer->expects($this->once())309            ->method('lex')310            ->with($pathTemplate)311            ->willReturn(new TokenStream([]));312        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));313    }314    public function testCompilingTextOnlyPathAstAddsRouteToNode(): void315    {316        $pathAst = (new AstNode(AstNodeType::Path, null))317            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))318            ->addChild(new AstNode(AstNodeType::Text, 'foo'));319        $this->ast->addChild($pathAst);320        $pathTemplate = '/foo';321        $expectedRoute = $this->createRoute($pathTemplate);322        $this->expectedTrie->addChild(new LiteralTrieNode(323            'foo',324            [],325            $expectedRoute326        ));327        $this->lexer->expects($this->once())328            ->method('lex')329            ->with($pathTemplate)330            ->willReturn(new TokenStream([]));331        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));332    }333    public function testCompilingVariableOnlyPathAstAddsRouteToNode(): void334    {335        $pathAst = (new AstNode(AstNodeType::Path, null))336            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))337            ->addChild(new AstNode(AstNodeType::Variable, 'foo'));338        $this->ast->addChild($pathAst);339        $pathTemplate = '/:foo';340        $expectedRoute = $this->createRoute($pathTemplate);341        $this->expectedTrie->addChild(new VariableTrieNode(342            new RouteVariable('foo'),343            [],344            $expectedRoute345        ));346        $this->lexer->expects($this->once())347            ->method('lex')348            ->with($pathTemplate)349            ->willReturn(new TokenStream([]));350        $this->assertEquals($this->expectedTrie, $this->compiler->compile($expectedRoute));351    }352    public function testConstructingCompilerWithoutConstraintsStillRegistersDefaultOnes(): void353    {354        // Set up AST355        $variableNode = (new AstNode(AstNodeType::Variable, 'foo'))356            ->addChild(new AstNode(AstNodeType::VariableConstraint, 'int'));357        $pathAst = (new AstNode(AstNodeType::Path, null))358            ->addChild(new AstNode(AstNodeType::SegmentDelimiter, '/'))359            ->addChild($variableNode);360        $this->ast->addChild($pathAst);361        // Test compiling362        $pathTemplate = '/:foo(int)';363        $expectedRoute = $this->createRoute($pathTemplate);364        $this->expectedTrie->addChild(new VariableTrieNode(365            new RouteVariable('foo', [new IntegerConstraint()]),366            [],367            $expectedRoute368        ));369        $this->lexer->expects($this->once())370            ->method('lex')371            ->with($pathTemplate)372            ->willReturn(new TokenStream([]));...

Full Screen

Full Screen

AbstractASTNode.php

Source:AbstractASTNode.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PDepend.4 *5 * PHP Version 56 *7 * Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.8 * All rights reserved.9 *10 * Redistribution and use in source and binary forms, with or without11 * modification, are permitted provided that the following conditions12 * are met:13 *14 *   * Redistributions of source code must retain the above copyright15 *     notice, this list of conditions and the following disclaimer.16 *17 *   * Redistributions in binary form must reproduce the above copyright18 *     notice, this list of conditions and the following disclaimer in19 *     the documentation and/or other materials provided with the20 *     distribution.21 *22 *   * Neither the name of Manuel Pichler nor the names of his23 *     contributors may be used to endorse or promote products derived24 *     from this software without specific prior written permission.25 *26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE30 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER34 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN36 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE37 * POSSIBILITY OF SUCH DAMAGE.38 *39 * @copyright 2008-2017 Manuel Pichler. All rights reserved.40 * @license http://www.opensource.org/licenses/bsd-license.php BSD License41 * @since 0.9.642 */43namespace PDepend\Source\AST;44/**45 * This is an abstract base implementation of the ast node interface.46 *47 * @copyright 2008-2017 Manuel Pichler. All rights reserved.48 * @license http://www.opensource.org/licenses/bsd-license.php BSD License49 * @since 0.9.650 */51abstract class AbstractASTNode implements ASTNode52{53    /**54     * Parsed child nodes of this node.55     *56     * @var \PDepend\Source\AST\ASTNode[]57     */58    protected $nodes = array();59    /**60     * The parent node of this node or <b>null</b> when this node is the root61     * of a node tree.62     *63     * @var \PDepend\Source\AST\ASTNode64     */65    protected $parent = null;66    /**67     * An optional doc comment for this node.68     *69     * @var string70     */71    protected $comment = null;72    /**73     * Metadata for this node instance, serialized in a string. This string74     * contains the start, end line, and the start, end column and the node75     * image in a colon seperated string.76     *77     * @var string78     * @since 0.10.479     */80    protected $metadata = '::::';81    /**82     * Constructs a new ast node instance.83     *84     * @param string $image The source image for this node.85     */86    public function __construct($image = null)87    {88        $this->metadata = str_repeat(':', $this->getMetadataSize() - 1);89        $this->setImage($image);90    }91    /**92     * Sets the image for this ast node.93     *94     * @param string $image95     * @return void96     */97    public function setImage($image)98    {99        $this->setMetadata(4, $image);100    }101    /**102     * Returns the source image of this ast node.103     *104     * @return string105     */106    public function getImage()107    {108        return $this->getMetadata(4);109    }110    /**111     * Returns the start line for this ast node.112     *113     * @return integer114     */115    public function getStartLine()116    {117        return $this->getMetadataInteger(0);118    }119    /**120     * Returns the start column for this ast node.121     *122     * @return integer123     */124    public function getStartColumn()125    {126        return $this->getMetadataInteger(2);127    }128    /**129     * Returns the end line for this ast node.130     *131     * @return integer132     */133    public function getEndLine()134    {135        return $this->getMetadataInteger(1);136    }137    /**138     * Returns the end column for this ast node.139     *140     * @return integer141     */142    public function getEndColumn()143    {144        return $this->getMetadataInteger(3);145    }146    /**147     * For better performance we have moved the single setter methods for the148     * node columns and lines into this configure method.149     *150     * @param integer $startLine151     * @param integer $endLine152     * @param integer $startColumn153     * @param integer $endColumn154     * @return void155     * @since 0.9.10156     */157    public function configureLinesAndColumns(158        $startLine,159        $endLine,160        $startColumn,161        $endColumn162    ) {163        $this->setMetadataInteger(0, $startLine);164        $this->setMetadataInteger(1, $endLine);165        $this->setMetadataInteger(2, $startColumn);166        $this->setMetadataInteger(3, $endColumn);167    }168    /**169     * Returns an integer value that was stored under the given index.170     *171     * @param integer $index172     * @return integer173     * @since 0.10.4174     */175    protected function getMetadataInteger($index)176    {177        return (int) $this->getMetadata($index);178    }179    /**180     * Stores an integer value under the given index in the internally used data181     * string.182     *183     * @param integer $index184     * @param integer $value185     * @return void186     * @since 0.10.4187     */188    protected function setMetadataInteger($index, $value)189    {190        $this->setMetadata($index, $value);191    }192    /**193     * Returns a boolean value that was stored under the given index.194     *195     * @param integer $index196     * @return boolean197     * @since 0.10.4198     */199    protected function getMetadataBoolean($index)200    {201        return (bool) $this->getMetadata($index);202    }203    /**204     * Stores a boolean value under the given index in the internally used data205     * string.206     *207     * @param integer $index208     * @param boolean $value209     * @return void210     * @since 0.10.4211     */212    protected function setMetadataBoolean($index, $value)213    {214        $this->setMetadata($index, $value ? 1 : 0);215    }216    /**217     * Returns the value that was stored under the given index.218     *219     * @param integer $index220     * @return mixed221     * @since 0.10.4222     */223    protected function getMetadata($index)224    {225        $metadata = explode(':', $this->metadata, $this->getMetadataSize());226        return $metadata[$index];227    }228    /**229     * Stores the given value under the given index in an internal storage230     * container.231     *232     * @param integer $index233     * @param mixed $value234     * @return void235     * @since 0.10.4236     */237    protected function setMetadata($index, $value)238    {239        $metadata         = explode(':', $this->metadata, $this->getMetadataSize());240        $metadata[$index] = $value;241        $this->metadata = join(':', $metadata);242    }243    /**244     * Returns the total number of the used property bag.245     *246     * @return integer247     * @since 0.10.4248     */249    protected function getMetadataSize()250    {251        return 5;252    }253    /**254     * Returns the node instance for the given index or throws an exception.255     *256     * @param integer $index257     * @return \PDepend\Source\AST\ASTNode258     * @throws \OutOfBoundsException When no node exists at the given index.259     */260    public function getChild($index)261    {262        if (isset($this->nodes[$index])) {263            return $this->nodes[$index];264        }265        throw new \OutOfBoundsException(266            sprintf(267                'No node found at index %d in node of type: %s',268                $index,269                get_class($this)270            )271        );272    }273    /**274     * This method returns all direct children of the actual node.275     *276     * @return \PDepend\Source\AST\ASTNode[]277     */278    public function getChildren()279    {280        return $this->nodes;281    }282    /**283     * This method will search recursive for the first child node that is an284     * instance of the given <b>$targetType</b>. The returned value will be285     * <b>null</b> if no child exists for that.286     *287     * @param string $targetType288     * @return \PDepend\Source\AST\ASTNode289     */290    public function getFirstChildOfType($targetType)291    {292        foreach ($this->nodes as $node) {293            if ($node instanceof $targetType) {294                return $node;295            }296            if (($child = $node->getFirstChildOfType($targetType)) !== null) {297                return $child;298            }299        }300        return null;301    }302    /**303     * This method will search recursive for all child nodes that are an304     * instance of the given <b>$targetType</b>. The returned value will be305     * an empty <b>array</b> if no child exists for that.306     *307     * @param string $targetType Searched class or interface type.308     * @param array  &$results   Already found node instances. This parameter309     *        is only for internal usage.310     * @return \PDepend\Source\AST\ASTNode[]311     */312    public function findChildrenOfType($targetType, array &$results = array())313    {314        foreach ($this->nodes as $node) {315            if ($node instanceof $targetType) {316                $results[] = $node;317            }318            $node->findChildrenOfType($targetType, $results);319        }320        return $results;321    }322    /**323     * This method adds a new child node at the first position of the children.324     *325     * @param \PDepend\Source\AST\ASTNode $node326     * @return void327     */328    public function prependChild(ASTNode $node)329    {330        array_unshift($this->nodes, $node);331        $node->setParent($this);332    }333    /**334     * This method adds a new child node to this node instance.335     *336     * @param \PDepend\Source\AST\ASTNode $node337     * @return void338     */339    public function addChild(ASTNode $node)340    {341        $this->nodes[] = $node;342        $node->setParent($this);343    }344    /**345     * Returns the parent node of this node or <b>null</b> when this node is346     * the root of a node tree.347     *348     * @return \PDepend\Source\AST\ASTNode349     */350    public function getParent()351    {352        return $this->parent;353    }354    /**355     * Traverses up the node tree and finds all parent nodes that are instances356     * of <b>$parentType</b>.357     *358     * @param string $parentType359     * @return \PDepend\Source\AST\ASTNode[]360     */361    public function getParentsOfType($parentType)362    {363        $parents = array();364        $parentNode = $this->parent;365        while (is_object($parentNode)) {366            if ($parentNode instanceof $parentType) {367                array_unshift($parents, $parentNode);368            }369            $parentNode = $parentNode->getParent();370        }371        return $parents;372    }373    /**374     * Sets the parent node of this node.375     *376     * @param \PDepend\Source\AST\ASTNode $node377     * @return void378     */379    public function setParent(ASTNode $node)380    {381        $this->parent = $node;382    }383    /**384     * Returns a doc comment for this node or <b>null</b> when no comment was385     * found.386     *387     * @return string388     */389    public function getComment()390    {391        return $this->comment;392    }393    /**394     * Sets the raw doc comment for this node.395     *396     * @param string $comment The doc comment block for this node.397     *398     * @return void399     */400    public function setComment($comment)401    {402        $this->comment = $comment;403    }404    /**405     * The magic sleep method will be called by PHP's runtime environment right406     * before an instance of this class gets serialized. It should return an407     * array with those property names that should be serialized for this class.408     *409     * @return array410     * @since 0.10.0411     */412    public function __sleep()413    {414        return array(415            'comment',416            'metadata',417            'nodes'418        );419    }420    /**421     * The magic wakeup method will be called by PHP's runtime environment when422     * a previously serialized object gets unserialized. This implementation of423     * the wakeup method restores the dependencies between an ast node and the424     * node's children.425     *426     * @return void427     * @since 0.10.0428     */429    public function __wakeup()430    {431        foreach ($this->nodes as $node) {432            $node->setParent($this);433        }434    }435}...

Full Screen

Full Screen

UnusedLocalVariable.php

Source:UnusedLocalVariable.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PHP Mess Detector.4 *5 * Copyright (c) Manuel Pichler <mapi@phpmd.org>.6 * All rights reserved.7 *8 * Licensed under BSD License9 * For full copyright and license information, please see the LICENSE file.10 * Redistributions of files must retain the above copyright notice.11 *12 * @author Manuel Pichler <mapi@phpmd.org>13 * @copyright Manuel Pichler. All rights reserved.14 * @license https://opensource.org/licenses/bsd-license.php BSD License15 * @link http://phpmd.org/16 */17namespace PHPMD\Rule;18use PHPMD\AbstractNode;19use PHPMD\Node\AbstractCallableNode;20use PHPMD\Node\ASTNode;21/**22 * This rule collects all local variables within a given function or method23 * that are not used by any code in the analyzed source artifact.24 */25class UnusedLocalVariable extends AbstractLocalVariable implements FunctionAware, MethodAware26{27    /**28     * Found variable images within a single method or function.29     *30     * @var array(string)31     */32    private $images = array();33    /**34     * This method checks that all local variables within the given function or35     * method are used at least one time.36     *37     * @param \PHPMD\AbstractNode $node38     * @return void39     */40    public function apply(AbstractNode $node)41    {42        $this->images = array();43        /** @var $node AbstractCallableNode */44        $this->collectVariables($node);45        $this->removeParameters($node);46        foreach ($this->images as $nodes) {47            if (count($nodes) === 1) {48                $this->doCheckNodeImage($nodes[0]);49            }50        }51    }52    /**53     * This method removes all variables from the <b>$_images</b> property that54     * are also found in the formal parameters of the given method or/and55     * function node.56     *57     * @param \PHPMD\Node\AbstractCallableNode $node58     * @return void59     */60    private function removeParameters(AbstractCallableNode $node)61    {62        // Get formal parameter container63        $parameters = $node->getFirstChildOfType('FormalParameters');64        // Now get all declarators in the formal parameters container65        $declarators = $parameters->findChildrenOfType('VariableDeclarator');66        foreach ($declarators as $declarator) {67            unset($this->images[$declarator->getImage()]);68        }69    }70    /**71     * This method collects all local variable instances from the given72     * method/function node and stores their image in the <b>$_images</b>73     * property.74     *75     *76     * @param \PHPMD\Node\AbstractCallableNode $node77     * @return void78     */79    private function collectVariables(AbstractCallableNode $node)80    {81        foreach ($node->findChildrenOfType('Variable') as $variable) {82            /** @var $variable ASTNode */83            if ($this->isLocal($variable)) {84                $this->collectVariable($variable);85            }86        }87        foreach ($node->findChildrenOfType('CompoundVariable') as $variable) {88            $this->collectCompoundVariableInString($variable);89        }90        foreach ($node->findChildrenOfType('VariableDeclarator') as $variable) {91            $this->collectVariable($variable);92        }93        foreach ($node->findChildrenOfType('FunctionPostfix') as $func) {94            if ($this->isFunctionNameEndingWith($func, 'compact')) {95                foreach ($func->findChildrenOfType('Literal') as $literal) {96                    /** @var $literal ASTNode */97                    $this->collectLiteral($literal);98                }99            }100        }101    }102    /**103     * Stores the given compound variable node in an internal list of found variables.104     *105     * @param \PHPMD\Node\ASTNode $node106     * @return void107     */108    private function collectCompoundVariableInString(ASTNode $node)109    {110        $parentNode = $node->getParent()->getNode();111        $candidateParentNodes = $node->getParentsOfType('PDepend\Source\AST\ASTString');112        if (in_array($parentNode, $candidateParentNodes)) {113            $variablePrefix = $node->getImage();114            foreach ($node->findChildrenOfType('Expression') as $child) {115                $variableName = $child->getImage();116                $variableImage = $variablePrefix . $variableName;117                $this->storeImage($variableImage, $node);118            }119        }120    }121    /**122     * Stores the given variable node in an internal list of found variables.123     *124     * @param \PHPMD\Node\ASTNode $node125     * @return void126     */127    private function collectVariable(ASTNode $node)128    {129        $imageName = $node->getImage();130        $this->storeImage($imageName, $node);131    }132    /**133     * Safely add node to $this->images.134     *135     * @param string $imageName         the name to store the node as136     * @param \PHPMD\Node\ASTNode $node the node being stored137     * @return void138     */139    private function storeImage($imageName, ASTNode $node)140    {141        if (!isset($this->images[$imageName])) {142            $this->images[$imageName] = array();143        }144        $this->images[$imageName][] = $node;145    }146    /**147     * Stores the given literal node in an internal list of found variables.148     *149     * @param \PHPMD\Node\ASTNode $node150     * @return void151     */152    private function collectLiteral(ASTNode $node)153    {154        $variable = '$' . trim($node->getImage(), '\'');155        if (!isset($this->images[$variable])) {156            $this->images[$variable] = array();157        }158        $this->images[$variable][] = $node;159    }160    /**161     * Template method that performs the real node image check.162     *163     * @param ASTNode $node164     * @return void165     */166    protected function doCheckNodeImage(ASTNode $node)167    {168        if ($this->isNameAllowedInContext($node)) {169            return;170        }171        if ($this->isUnusedForeachVariableAllowed($node)) {172            return;173        }174        $exceptions = $this->getExceptionsList();175        if (in_array(substr($node->getImage(), 1), $exceptions)) {176            return;177        }178        $this->addViolation($node, array($node->getImage()));179    }180    /**181     * Checks if a short name is acceptable in the current context. For the182     * moment these contexts are the init section of a for-loop and short183     * variable names in catch-statements.184     *185     * @param \PHPMD\AbstractNode $node186     * @return boolean187     */188    private function isNameAllowedInContext(AbstractNode $node)189    {190        return $this->isChildOf($node, 'CatchStatement');191    }192    /**193     * Checks if an unused foreach variable (key or variable) is allowed.194     *195     * If it's not a foreach variable, it returns always false.196     *197     * @param \PHPMD\Node\ASTNode $variable The variable to check.198     * @return bool True if allowed, else false.199     */200    private function isUnusedForeachVariableAllowed(ASTNode $variable)201    {202        $isForeachVariable = $this->isChildOf($variable, 'ForeachStatement');203        if (!$isForeachVariable) {204            return false;205        }206        return $this->getBooleanProperty('allow-unused-foreach-variables');207    }208    /**209     * Checks if the given node is a direct or indirect child of a node with210     * the given type.211     *212     * @param \PHPMD\AbstractNode $node213     * @param string $type214     * @return boolean215     */216    private function isChildOf(AbstractNode $node, $type)217    {218        $parent = $node->getParent();219        return $parent->isInstanceOf($type);220    }221    /**222     * Gets array of exceptions from property223     *224     * @return array225     */226    private function getExceptionsList()227    {228        try {229            $exceptions = $this->getStringProperty('exceptions');230        } catch (\OutOfBoundsException $e) {231            $exceptions = '';232        }233        return explode(',', $exceptions);234    }235}...

Full Screen

Full Screen

UnusedPrivateField.php

Source:UnusedPrivateField.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PHP Mess Detector.4 *5 * Copyright (c) Manuel Pichler <mapi@phpmd.org>.6 * All rights reserved.7 *8 * Licensed under BSD License9 * For full copyright and license information, please see the LICENSE file.10 * Redistributions of files must retain the above copyright notice.11 *12 * @author Manuel Pichler <mapi@phpmd.org>13 * @copyright Manuel Pichler. All rights reserved.14 * @license https://opensource.org/licenses/bsd-license.php BSD License15 * @link http://phpmd.org/16 */17namespace PHPMD\Rule;18use PHPMD\AbstractNode;19use PHPMD\AbstractRule;20use PHPMD\Node\ASTNode;21use PHPMD\Node\ClassNode;22/**23 * This rule collects all private fields in a class that aren't used in any24 * method of the analyzed class.25 */26class UnusedPrivateField extends AbstractRule implements ClassAware27{28    /**29     * Collected private fields/variable declarators in the currently processed30     * class.31     *32     * @var \PHPMD\Node\ASTNode[]33     */34    private $fields = array();35    /**36     * This method checks that all private class properties are at least accessed37     * by one method.38     *39     * @param \PHPMD\AbstractNode $node40     * @return void41     */42    public function apply(AbstractNode $node)43    {44        /** @var ClassNode $field */45        foreach ($this->collectUnusedPrivateFields($node) as $field) {46            $this->addViolation($field, array($field->getImage()));47        }48    }49    /**50     * This method collects all private fields that aren't used by any class51     * method.52     *53     * @param \PHPMD\Node\ClassNode $class54     * @return \PHPMD\AbstractNode[]55     */56    private function collectUnusedPrivateFields(ClassNode $class)57    {58        $this->fields = array();59        $this->collectPrivateFields($class);60        $this->removeUsedFields($class);61        return $this->fields;62    }63    /**64     * This method collects all private fields in the given class and stores65     * them in the <b>$_fields</b> property.66     *67     * @param \PHPMD\Node\ClassNode $class68     * @return void69     */70    private function collectPrivateFields(ClassNode $class)71    {72        foreach ($class->findChildrenOfType('FieldDeclaration') as $declaration) {73            /** @var ASTNode $declaration */74            if ($declaration->isPrivate()) {75                $this->collectPrivateField($declaration);76            }77        }78    }79    /**80     * This method extracts all variable declarators from the given field81     * declaration and stores them in the <b>$_fields</b> property.82     *83     * @param \PHPMD\Node\ASTNode $declaration84     * @return void85     */86    private function collectPrivateField(ASTNode $declaration)87    {88        $fields = $declaration->findChildrenOfType('VariableDeclarator');89        foreach ($fields as $field) {90            $this->fields[$field->getImage()] = $field;91        }92    }93    /**94     * This method extracts all property postfix nodes from the given class and95     * removes all fields from the <b>$_fields</b> property that are accessed by96     * one of the postfix nodes.97     *98     * @param \PHPMD\Node\ClassNode $class99     * @return void100     */101    private function removeUsedFields(ClassNode $class)102    {103        foreach ($class->findChildrenOfType('PropertyPostfix') as $postfix) {104            /** @var $postfix ASTNode */105            if ($this->isInScopeOfClass($class, $postfix)) {106                $this->removeUsedField($postfix);107            }108        }109    }110    /**111     * This method removes the field from the <b>$_fields</b> property that is112     * accessed through the given property postfix node.113     *114     * @param \PHPMD\Node\ASTNode $postfix115     * @return void116     */117    private function removeUsedField(ASTNode $postfix)118    {119        $image = '$';120        $child = $postfix->getFirstChildOfType('Identifier');121        if ($postfix->getParent()->isStatic()) {122            $image = '';123            $child = $postfix->getFirstChildOfType('Variable');124        }125        if ($this->isValidPropertyNode($child)) {126            unset($this->fields[$image . $child->getImage()]);127        }128    }129    /**130     * Checks if the given node is a valid property node.131     *132     * @param \PHPMD\Node\ASTNode $node133     * @return boolean134     * @since 0.2.6135     */136    protected function isValidPropertyNode(ASTNode $node = null)137    {138        if ($node === null) {139            return false;140        }141        $parent = $node->getParent();142        while (!$parent->isInstanceOf('PropertyPostfix')) {143            if ($parent->isInstanceOf('CompoundVariable')) {144                return false;145            }146            $parent = $parent->getParent();147            if (is_null($parent)) {148                   return false;149            }150        }151        return true;152    }153    /**154     * This method checks that the given property postfix is accessed on an155     * instance or static reference to the given class.156     *157     * @param \PHPMD\Node\ClassNode $class158     * @param \PHPMD\Node\ASTNode $postfix159     * @return boolean160     */161    protected function isInScopeOfClass(ClassNode $class, ASTNode $postfix)162    {163        $owner = $this->getOwner($postfix);164        return (165            $owner->isInstanceOf('SelfReference') ||166            $owner->isInstanceOf('StaticReference') ||167            strcasecmp($owner->getImage(), '$this') === 0 ||168            strcasecmp($owner->getImage(), $class->getImage()) === 0169        );170    }171    /**172     * Looks for owner of the given variable.173     *174     * @param \PHPMD\Node\ASTNode $postfix175     * @return \PHPMD\Node\ASTNode176     */177    protected function getOwner(ASTNode $postfix)178    {179        $owner = $postfix->getParent()->getChild(0);180        if ($owner->isInstanceOf('PropertyPostfix')) {181            $owner = $owner->getParent()->getParent()->getChild(0);182        }183        if ($owner->getParent()->isInstanceOf('ArrayIndexExpression')) {184            $owner = $owner->getParent()->getParent()->getChild(0);185        }186        return $owner;187    }188}...

Full Screen

Full Screen

AbstractLocalVariable.php

Source:AbstractLocalVariable.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PHP Mess Detector.4 *5 * Copyright (c) Manuel Pichler <mapi@phpmd.org>.6 * All rights reserved.7 *8 * Licensed under BSD License9 * For full copyright and license information, please see the LICENSE file.10 * Redistributions of files must retain the above copyright notice.11 *12 * @author Manuel Pichler <mapi@phpmd.org>13 * @copyright Manuel Pichler. All rights reserved.14 * @license https://opensource.org/licenses/bsd-license.php BSD License15 * @link http://phpmd.org/16 */17namespace PHPMD\Rule;18use PHPMD\AbstractNode;19use PHPMD\AbstractRule;20use PHPMD\Node\ASTNode;21/**22 * Base class for rules that rely on local variables.23 *24 * @since     0.2.625 */26abstract class AbstractLocalVariable extends AbstractRule27{28    /**29     * PHP super globals that are available in all php scopes, so that they30     * can never be unused local variables.31     *32     * @var array(string=>boolean)33     * @link http://php.net/manual/en/reserved.variables.php34     */35    private static $superGlobals = array(36        '$argc' => true,37        '$argv' => true,38        '$_COOKIE' => true,39        '$_ENV' => true,40        '$_FILES' => true,41        '$_GET' => true,42        '$_POST' => true,43        '$_REQUEST' => true,44        '$_SERVER' => true,45        '$_SESSION' => true,46        '$GLOBALS' => true,47        '$HTTP_RAW_POST_DATA' => true,48        '$php_errormsg' => true,49        '$http_response_header' => true,50    );51    /**52     * Tests if the given variable node represents a local variable or if it is53     * a static object property or something similar.54     *55     * @param \PHPMD\Node\ASTNode $variable The variable to check.56     * @return boolean57     */58    protected function isLocal(ASTNode $variable)59    {60        return (false === $variable->isThis()61            && $this->isNotSuperGlobal($variable)62            && $this->isRegularVariable($variable)63        );64    }65    /**66     * Tests if the given variable represents one of the PHP super globals67     * that are available in scopes.68     *69     * @param \PHPMD\AbstractNode $variable70     * @return boolean71     */72    protected function isNotSuperGlobal(AbstractNode $variable)73    {74        return !isset(self::$superGlobals[$variable->getImage()]);75    }76    /**77     * Tests if the given variable node is a regular variable an not property78     * or method postfix.79     *80     * @param \PHPMD\Node\ASTNode $variable81     * @return boolean82     */83    protected function isRegularVariable(ASTNode $variable)84    {85        $node   = $this->stripWrappedIndexExpression($variable);86        $parent = $node->getParent();87        if ($parent->isInstanceOf('PropertyPostfix')) {88            $primaryPrefix = $parent->getParent();89            if ($primaryPrefix->getParent()->isInstanceOf('MemberPrimaryPrefix')) {90                return !$primaryPrefix->getParent()->isStatic();91            }92            return ($parent->getChild(0)->getNode() !== $node->getNode()93                || !$primaryPrefix->isStatic()94            );95        }96        return true;97    }98    /**99     * Removes all index expressions that are wrapped around the given node100     * instance.101     *102     * @param \PHPMD\Node\ASTNode $node103     * @return \PHPMD\Node\ASTNode104     */105    protected function stripWrappedIndexExpression(ASTNode $node)106    {107        if (false === $this->isWrappedByIndexExpression($node)) {108            return $node;109        }110        $parent = $node->getParent();111        if ($parent->getChild(0)->getNode() === $node->getNode()) {112            return $this->stripWrappedIndexExpression($parent);113        }114        return $node;115    }116    /**117     * Tests if the given variable node os part of an index expression.118     *119     * @param \PHPMD\Node\ASTNode $node120     * @return boolean121     */122    protected function isWrappedByIndexExpression(ASTNode $node)123    {124        return ($node->getParent()->isInstanceOf('ArrayIndexExpression')125            || $node->getParent()->isInstanceOf('StringIndexExpression')126        );127    }128    /**129     * PHP is case insensitive so we should compare function names case130     * insensitive.131     *132     * @param \PHPMD\AbstractNode $node133     * @param string $name134     * @return boolean135     */136    protected function isFunctionNameEqual(AbstractNode $node, $name)137    {138        return (0 === strcasecmp(trim($node->getImage(), '\\'), $name));139    }140    /**141     * AST puts namespace prefix to global functions called from a namespace.142     * This method checks if the last part of function fully qualified name is equal to $name143     *144     * @param \PHPMD\AbstractNode $node145     * @param string $name146     * @return boolean147     */148    protected function isFunctionNameEndingWith(AbstractNode $node, $name)149    {150        $parts = explode('\\', trim($node->getImage(), '\\'));151        return (0 === strcasecmp(array_pop($parts), $name));152    }153}...

Full Screen

Full Screen

DuplicatedArrayKey.php

Source:DuplicatedArrayKey.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PHP Mess Detector.4 *5 * Copyright (c) Manuel Pichler <mapi@phpmd.org>.6 * All rights reserved.7 *8 * Licensed under BSD License9 * For full copyright and license information, please see the LICENSE file.10 * Redistributions of files must retain the above copyright notice.11 *12 * @author Manuel Pichler <mapi@phpmd.org>13 * @copyright Manuel Pichler. All rights reserved.14 * @license https://opensource.org/licenses/bsd-license.php BSD License15 * @link http://phpmd.org/16 */17namespace PHPMD\Rule\CleanCode;18use PDepend\Source\AST\AbstractASTNode;19use PDepend\Source\AST\ASTArrayElement;20use PDepend\Source\AST\ASTLiteral;21use PDepend\Source\AST\ASTNode as PDependASTNode;22use PHPMD\AbstractNode;23use PHPMD\AbstractRule;24use PHPMD\Node\ASTNode;25use PHPMD\Rule\FunctionAware;26use PHPMD\Rule\MethodAware;27/**28 * Duplicated Array Key Rule29 *30 * This rule detects duplicated array keys.31 *32 * @author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>33 * @author Kamil Szymanaski <kamil.szymanski@gmail.com>34 */35class DuplicatedArrayKey extends AbstractRule implements MethodAware, FunctionAware36{37    /**38     * Retrieves all arrays from single node and performs comparison logic on it39     *40     * @param AbstractNode $node41     * @return void42     */43    public function apply(AbstractNode $node)44    {45        foreach ($node->findChildrenOfType('Array') as $arrayNode) {46            /** @var ASTNode $arrayNode */47            $this->checkForDuplicatedArrayKeys($arrayNode);48        }49    }50    /**51     * This method checks if a given function or method contains an array literal52     * with duplicated entries for any key and emits a rule violation if so.53     *54     * @param ASTNode $node Array node.55     * @return void56     */57    private function checkForDuplicatedArrayKeys(ASTNode $node)58    {59        $keys = array();60        /** @var ASTArrayElement $arrayElement */61        foreach ($node->getChildren() as $index => $arrayElement) {62            $arrayElement = $this->normalizeKey($arrayElement, $index);63            if (null === $arrayElement) {64                // skip everything that can't be resolved easily65                continue;66            }67            $key = $arrayElement->getImage();68            if (isset($keys[$key])) {69                $this->addViolation($node, array($key, $arrayElement->getStartLine()));70                continue;71            }72            $keys[$key] = $arrayElement;73        }74    }75    /**76     * Changes key name to its string format.77     *78     * To compare keys, we have to cast them to string.79     * Non-associative keys have to use index as its key,80     * while boolean and nulls have to be casted respectively.81     * As current logic doesn't evaluate expressions nor constants,82     * statics, globals, etc. we simply skip them.83     *84     * @param AbstractASTNode $node Array key to evaluate.85     * @param int $index Fallback in case of non-associative arrays86     * @return AbstractASTNode Key name87     */88    private function normalizeKey(AbstractASTNode $node, $index)89    {90        $childCount = count($node->getChildren());91        // Skip, if there is no array key, just an array value92        if ($childCount === 1) {93            return null;94        }95        // non-associative - key name equals to its index96        if ($childCount === 0) {97            $node->setImage((string) $index);98            return $node;99        }100        101        $node = $node->getChild(0);102        if (!($node instanceof ASTLiteral)) {103            // skip expressions, method calls, globals and constants104            return null;105        }106        $node->setImage($this->castStringFromLiteral($node));107        return $node;108    }109    /**110     * Cleans string literals and casts boolean and null values as PHP engine does111     *112     * @param PDependASTNode $key113     * @return string114     */115    private function castStringFromLiteral(PDependASTNode $key)116    {117        $value = $key->getImage();118        switch ($value) {119            case 'false':120                return '0';121            case 'true':122                return '1';123            case 'null':124                return '';125            default:126                return trim($value, '\'""');127        }128    }129}...

Full Screen

Full Screen

ASTNodeTest.php

Source:ASTNodeTest.php Github

copy

Full Screen

1<?php2/**3 * This file is part of PHP Mess Detector.4 *5 * Copyright (c) 2008-2012, Manuel Pichler <mapi@phpmd.org>.6 * All rights reserved.7 *8 * Redistribution and use in source and binary forms, with or without9 * modification, are permitted provided that the following conditions10 * are met:11 *12 *   * Redistributions of source code must retain the above copyright13 *     notice, this list of conditions and the following disclaimer.14 *15 *   * Redistributions in binary form must reproduce the above copyright16 *     notice, this list of conditions and the following disclaimer in17 *     the documentation and/or other materials provided with the18 *     distribution.19 *20 *   * Neither the name of Manuel Pichler nor the names of his21 *     contributors may be used to endorse or promote products derived22 *     from this software without specific prior written permission.23 *24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE35 * POSSIBILITY OF SUCH DAMAGE.36 *37 * @author    Manuel Pichler <mapi@phpmd.org>38 * @copyright 2008-2014 Manuel Pichler. All rights reserved.39 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License40 */41namespace PHPMD\Node;42use PHPMD\AbstractTest;43/**44 * Test case for the {@link \PHPMD\Node\ASTNode} class.45 *46 * @author    Manuel Pichler <mapi@phpmd.org>47 * @copyright 2008-2014 Manuel Pichler. All rights reserved.48 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License49 *50 * @covers \PHPMD\Node\ASTNode51 * @group phpmd52 * @group phpmd::node53 * @group unittest54 */55class ASTNodeTest extends AbstractTest56{57    /**58     * testGetImageDelegatesToGetImageMethodOfWrappedNode59     *60     * @return void61     */62    public function testGetImageDelegatesToGetImageMethodOfWrappedNode()63    {64        $mock = $this->getMock('PDepend\Source\AST\ASTNode');65        $mock->expects($this->once())66            ->method('getImage');67        $node = new ASTNode($mock, __FILE__);68        $node->getImage();69    }70    /**71     * testGetNameDelegatesToGetImageMethodOfWrappedNode72     *73     * @return void74     */75    public function testGetNameDelegatesToGetImageMethodOfWrappedNode()76    {77        $mock = $this->getMock('PDepend\Source\AST\ASTNode');78        $mock->expects($this->once())79            ->method('getImage');80        $node = new ASTNode($mock, __FILE__);81        $node->getName();82    }83    /**84     * testHasSuppressWarningsAnnotationForAlwaysReturnsFalse85     *86     * @return void87     */88    public function testHasSuppressWarningsAnnotationForAlwaysReturnsFalse()89    {90        $mock = $this->getMock('PDepend\Source\AST\ASTNode');91        $node = new ASTNode($mock, __FILE__);92        $rule = $this->getMockForAbstractClass('PHPMD\\AbstractRule');93        $this->assertFalse($node->hasSuppressWarningsAnnotationFor($rule));94    }95    /**96     * testGetParentNameReturnsNull97     *98     * @return void99     */100    public function testGetParentNameReturnsNull()101    {102        $mock = $this->getMock('PDepend\Source\AST\ASTNode');103        $node = new ASTNode($mock, __FILE__);104        $this->assertNull($node->getParentName());105    }106    /**107     * testGetNamespaceNameReturnsNull108     *109     * @return void110     */111    public function testGetNamespaceNameReturnsNull()112    {113        $mock = $this->getMock('PDepend\Source\AST\ASTNode');114        $node = new ASTNode($mock, __FILE__);115        $this->assertNull($node->getNamespaceName());116    }117}...

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\Gherkin;3use Behat\Gherkin\Node\FeatureNode;4use Behat\Gherkin\Node\ScenarioNode;5use Behat\Gherkin\Node\StepNode;6use Behat\Gherkin\Node\TableNode;7use Behat\Gherkin\Node\PyStringNode;8use Behat\Gherkin\Node\BackgroundNode;9use Behat\Gherkin\Node\OutlineNode;10use Behat\Gherkin\Node\ExampleNode;11use Behat\Gherkin\Node\StepContainerInterface;12use Behat\Gherkin\Node\FeatureInterface;13use Behat\Gherkin\Node\ScenarioInterface;14use Behat\Gherkin\Node\StepInterface;15use Behat\Gherkin\Node\BackgroundInterface;16use Behat\Gherkin\Node\OutlineInterface;17use Behat\Gherkin\Node\ExampleInterface;18use Behat\Gherkin\Node\StepArgumentInterface;19use Behat\Gherkin\Node\PyStringNode;20use Behat\Gherkin\Node\TableNode;21use Behat\Gherkin\Node\AstNode;22use Behat\Gherkin\Node\BackgroundNode;23use Behat\Gherkin\Node\FeatureNode;24use Behat\Gherkin\Node\OutlineNode;25use Behat\Gherkin\Node\ScenarioNode;26use Behat\Gherkin\Node\StepNode;27use Behat\Gherkin\Node\TableNode;28use Behat\Gherkin\Node\PyStringNode;29use Behat\Gherkin\Node\StepArgumentInterface;30use Behat\Gherkin\Node\StepContainerInterface;31use Behat\Gherkin\Node\FeatureInterface;32use Behat\Gherkin\Node\ScenarioInterface;33use Behat\Gherkin\Node\StepInterface;34use Behat\Gherkin\Node\BackgroundInterface;35use Behat\Gherkin\Node\OutlineInterface;36use Behat\Gherkin\Node\ExampleInterface;

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\Node\AstNode;3use Behat\Gherkin\Node\FeatureNode;4use Behat\Gherkin\Node\ScenarioNode;5use Behat\Gherkin\Node\StepNode;6use Behat\Gherkin\Node\TableNode;7use Behat\Gherkin\Node\PyStringNode;8use Behat\Gherkin\Parser;9use Behat\Gherkin\Lexer;10use Behat\Gherkin\Filter\LineFilter;11use Behat\Gherkin\Filter\TagFilter;12use Behat\Gherkin\Filter\NameFilter;13use Behat\Gherkin\Filter\RoleFilter;14use Behat\Gherkin\Filter\FeatureFilter;15use Behat\Gherkin\Filter\ScenarioFilter;16use Behat\Gherkin\Filter\StepFilter;17use Behat\Gherkin\Filter\BackgroundFilter;18use Behat\Gherkin\Filter\OutlineFilter;19use Behat\Gherkin\Filter\ExamplesFilter;20use Behat\Gherkin\FilterFactory;21use Behat\Gherkin\Dumper\GherkinDumper;22use Behat\Gherkin\Node\NodeElement;23use Behat\Gherkin\Node\NodeElementFactory;24use Behat\Gherkin\Node\NodeBuilder;25use Behat\Gherkin\Node\NodeFactory;26use Behat\Gherkin\Node\NodeFactoryInterface;27use Behat\Gherkin\Node\NodeVisitor;28use Behat\Gherkin\Node\NodeVisitorInterface;

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\Keywords\ArrayKeywords;3use Behat\Gherkin\Keywords\KeywordsInterface;4use Behat\Gherkin\Keywords\Keywords;5use Behat\Gherkin\Keywords\KeywordsTable;6use Behat\Gherkin\Node\StepNode;7use Behat\Gherkin\Node\ScenarioNode;8use Behat\Gherkin\Node\FeatureNode;9use Behat\Gherkin\Node\BackgroundNode;10use Behat\Gherkin\Node\AstNode;11use Behat\Gherkin\Node\OutlineNode;12use Behat\Gherkin\Node\PyStringNode;13use Behat\Gherkin\Node\TableNode;14use Behat\Gherkin\Node\ExamplesNode;15use Behat\Gherkin\Node\StepContainerInterface;16use Behat\Gherkin\Node\ScenarioLikeInterface;17use Behat\Gherkin\Node\FeatureInterface;18use Behat\Gherkin\Node\StepInterface;19use Behat\Gherkin\Node\NodeInterface;20use Behat\Gherkin\Filter\NameFilter;21use Behat\Gherkin\Filter\TagFilter;22use Behat\Gherkin\Filter\LineFilter;23use Behat\Gherkin\Filter\CompositeFilter;24use Behat\Gherkin\Filter\FilterInterface;25use Behat\Gherkin\Loader\LoaderInterface;26use Behat\Gherkin\Loader\GherkinFileLoader;27use Behat\Gherkin\Loader\GherkinStringLoader;28use Behat\Gherkin\Loader\GherkinDirectoryLoader;29use Behat\Gherkin\Loader\CachedFileLoader;30use Behat\Gherkin\Loader\CachedDirectoryLoader;31use Behat\Gherkin\Loader\LoaderChain;32use Behat\Gherkin\Loader\LoaderResolver;33use Behat\Gherkin\Loader\NodeLoaderInterface;34use Behat\Gherkin\Loader\NodeGherkinFileLoader;35use Behat\Gherkin\Loader\NodeGherkinStringLoader;36use Behat\Gherkin\Loader\NodeGherkinDirectoryLoader;

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\Node\AstNode;3use Behat\Gherkin\Node\FeatureNode;4use Behat\Gherkin\Node\ScenarioNode;5use Behat\Gherkin\Node\StepNode;6use Behat\Gherkin\Node\OutlineNode;7use Behat\Gherkin\Node\BackgroundNode;8use Behat\Gherkin\Node\ExampleTableNode;9use Behat\Gherkin\Node\ExampleNode;10use Behat\Gherkin\Node\PyStringNode;11use Behat\Gherkin\Node\TableNode;12use Behat\Gherkin\Node\RowNode;13use Behat\Gherkin\Node\TagNode;14use Behat\Gherkin\Node\ArgumentInterface;15use Behat\Gherkin\Node\Argument\PyStringArgument;16use Behat\Gherkin\Node\Argument\TableArgument;

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1include_once 'vendor/autoload.php';2use Behat\Gherkin\Node\StepNode;3use Behat\Gherkin\Node\PyStringNode;4use Behat\Gherkin\Node\TableNode;5use Behat\Gherkin\Node\StepNode;6use Behat\Gherkin\Node\PyStringNode;7use Behat\Gherkin\Node\TableNode;8use Behat\Gherkin\Node\StepNode;9use Behat\Gherkin\Node\PyStringNode;10use Behat\Gherkin\Node\TableNode;11use Behat\Gherkin\Node\StepNode;12use Behat\Gherkin\Node\PyStringNode;13use Behat\Gherkin\Node\TableNode;14use Behat\Gherkin\Node\StepNode;15use Behat\Gherkin\Node\PyStringNode;16use Behat\Gherkin\Node\TableNode;17use Behat\Gherkin\Node\StepNode;18use Behat\Gherkin\Node\PyStringNode;19use Behat\Gherkin\Node\TableNode;20use Behat\Gherkin\Node\StepNode;21use Behat\Gherkin\Node\PyStringNode;22use Behat\Gherkin\Node\TableNode;23use Behat\Gherkin\Node\StepNode;24use Behat\Gherkin\Node\PyStringNode;25use Behat\Gherkin\Node\TableNode;26use Behat\Gherkin\Node\StepNode;27use Behat\Gherkin\Node\PyStringNode;28use Behat\Gherkin\Node\TableNode;29use Behat\Gherkin\Node\StepNode;

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'Gherkin/Parser.php';2require_once 'Gherkin/TokenScanner.php';3require_once 'Gherkin/TokenMatcher.php';4require_once 'Gherkin/Gherkin.php';5require_once 'Gherkin/Exception.php';6require_once 'Gherkin/Exception/ParserException.php';7require_once 'Gherkin/Exception/CompositeException.php';8require_once 'Gherkin/Exception/CompositeParserException.php';9require_once 'Gherkin/Exception/CompositeLexicalException.php';10require_once 'Gherkin/Exception/CompositeAstException.php';11require_once 'Gherkin/Exception/LexicalException.php';12require_once 'Gherkin/Exception/AstException.php';13require_once 'Gherkin/Exception/UndefinedStepException.php';14require_once 'Gherkin/Exception/RedundantStepException.php';15require_once 'Gherkin/Exception/RedundantArgument.php';16require_once 'Gherkin/Exception/UndefinedStepDefinitionException.php';17require_once 'Gherkin/Exception/UnexpectedException.php';18require_once 'Gherkin/Exception/InvalidFeatureFileException.php';19require_once 'Gherkin/Exception/NodeException.php';20require_once 'Gherkin/Exception/RedundantScenarioException.php';21require_once 'Gherkin/Exception/RedundantScenarioOutlineException.php';22require_once 'Gherkin/Exception/RedundantBackgroundException.php';23require_once 'Gherkin/Exception/RedundantExamplesException.php';24require_once 'Gherkin/Exception/RedundantExampleException.php';25require_once 'Gherkin/Exception/RedundantStepException.php';

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1$parser = new Gherkin\Parser();2$gherkin = $parser->parse(file_get_contents('features/feature.feature'));3$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();4$parser = new Behat\Gherkin\Parser();5$gherkin = $parser->parse(file_get_contents('features/feature.feature'));6$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();7$parser = new Behat\Gherkin\Parser();8$gherkin = $parser->parse(file_get_contents('features/feature.feature'));9$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();10$parser = new Behat\Gherkin\Parser();11$gherkin = $parser->parse(file_get_contents('features/feature.feature'));12$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();13$parser = new Behat\Gherkin\Parser();14$gherkin = $parser->parse(file_get_contents('features/feature.feature'));15$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();16$parser = new Behat\Gherkin\Parser();17$gherkin = $parser->parse(file_get_contents('features/feature.feature'));18$gherkin->getFeature()->getChildren()[0]->getSteps()[0]->getAstNode()->getKeyword();

Full Screen

Full Screen

AstNode

Using AI Code Generation

copy

Full Screen

1require_once 'vendor/autoload.php';2use Behat\Gherkin\Node\ScenarioNode;3$gherkin = new \Behat\Gherkin\Gherkin();4$parser = $gherkin->getParser();5$gherkin = new \Behat\Gherkin\Gherkin();6$parser = $gherkin->getParser();7$feature = $parser->parse($file);8$feature = $parser->parse($file);9$scenarios = $feature->getScenarios();10$scenarios = $feature->getScenarios();11foreach ($scenarios as $scenario) {12    $scenario->getTitle();13    $scenario->getTags();14    $scenario->getSteps();15    $scenario->getExamples();16    $scenario->getKeyword();17    $scenario->getLine();18    $scenario->getKeywordType();19}20print_r($scenarios);21require_once 'vendor/autoload.php';22use Behat\Gherkin\Node\ScenarioNode;23$gherkin = new \Behat\Gherkin\Gherkin();24$parser = $gherkin->getParser();25$gherkin = new \Behat\Gherkin\Gherkin();26$parser = $gherkin->getParser();27$feature = $parser->parse($file);28$feature = $parser->parse($file);29$scenarios = $feature->getScenarios();30$scenarios = $feature->getScenarios();31foreach ($scenarios as $scenario) {32    $scenario->getTitle();33    $scenario->getTags();34    $scenario->getSteps();35    $scenario->getExamples();36    $scenario->getKeyword();37    $scenario->getLine();38    $scenario->getKeywordType();39}40print_r($scenarios);41require_once 'vendor/autoload.php';42use Behat\Gherkin\Node\ScenarioNode;

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Gherkin-php automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Run Selenium Automation Tests on LambdaTest Cloud Grid

Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.

Test now for Free

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful