88use Microsoft \PhpParser \Node \ArrayElement ;
99use Microsoft \PhpParser \Node \Attribute ;
1010use Microsoft \PhpParser \Node \AttributeGroup ;
11+ use Microsoft \PhpParser \Node \CaseStatementNode ;
12+ use Microsoft \PhpParser \Node \CatchClause ;
1113use Microsoft \PhpParser \Node \ClassBaseClause ;
1214use Microsoft \PhpParser \Node \ClassInterfaceClause ;
1315use Microsoft \PhpParser \Node \ClassMembersNode ;
1416use Microsoft \PhpParser \Node \ConstElement ;
17+ use Microsoft \PhpParser \Node \DelimitedList \ExpressionList ;
1518use Microsoft \PhpParser \Node \DelimitedList \MatchArmConditionList ;
1619use Microsoft \PhpParser \Node \DelimitedList \QualifiedNameList ;
1720use Microsoft \PhpParser \Node \Expression ;
1821use Microsoft \PhpParser \Node \Expression \AnonymousFunctionCreationExpression ;
1922use Microsoft \PhpParser \Node \Expression \ArgumentExpression ;
23+ use Microsoft \PhpParser \Node \Expression \CallExpression ;
24+ use Microsoft \PhpParser \Node \Expression \MemberAccessExpression ;
25+ use Microsoft \PhpParser \Node \Expression \ScopedPropertyAccessExpression ;
2026use Microsoft \PhpParser \Node \Expression \BinaryExpression ;
2127use Microsoft \PhpParser \Node \Expression \Variable ;
2228use Microsoft \PhpParser \Node \InterfaceBaseClause ;
2935use Microsoft \PhpParser \Node \StatementNode ;
3036use Microsoft \PhpParser \Node \Statement \ClassDeclaration ;
3137use Microsoft \PhpParser \Node \Statement \CompoundStatementNode ;
38+ use Microsoft \PhpParser \Node \Statement \DoStatement ;
39+ use Microsoft \PhpParser \Node \Statement \EchoStatement ;
3240use Microsoft \PhpParser \Node \Statement \EnumDeclaration ;
41+ use Microsoft \PhpParser \Node \Statement \ForStatement ;
42+ use Microsoft \PhpParser \Node \Statement \ForeachStatement ;
3343use Microsoft \PhpParser \Node \Statement \ExpressionStatement ;
3444use Microsoft \PhpParser \Node \Statement \InlineHtml ;
3545use Microsoft \PhpParser \Node \Statement \IfStatementNode ;
3646use Microsoft \PhpParser \Node \Statement \WhileStatement ;
3747use Microsoft \PhpParser \Node \Statement \InterfaceDeclaration ;
48+ use Microsoft \PhpParser \Node \Statement \NamespaceUseDeclaration ;
49+ use Microsoft \PhpParser \Node \Statement \SwitchStatementNode ;
3850use Microsoft \PhpParser \Node \Statement \TraitDeclaration ;
51+ use Microsoft \PhpParser \Node \StringLiteral ;
3952use Microsoft \PhpParser \Node \TraitUseClause ;
4053use Microsoft \PhpParser \TokenKind ;
4154use Phpactor \TextDocument \ByteOffset ;
@@ -62,7 +75,20 @@ public static function expression(?Node $node): bool
6275 return false ;
6376 }
6477
65- if ($ parent instanceof ArgumentExpression) {
78+ if (
79+ $ node instanceof Variable
80+ || $ node instanceof ExpressionStatement
81+ || $ node instanceof MemberAccessExpression
82+ || $ node instanceof ScopedPropertyAccessExpression
83+ || $ node instanceof StringLiteral
84+ ) {
85+ return false ;
86+ }
87+
88+ if (
89+ $ node instanceof CallExpression
90+ || $ parent instanceof ArgumentExpression
91+ ) {
6692 return true ;
6793 }
6894
@@ -306,6 +332,92 @@ public static function methodName(Node $node): bool
306332 return $ node ->parent ->openParen instanceof MissingToken;
307333 }
308334
335+ public static function statement (Node $ node , ByteOffset $ offset ): bool
336+ {
337+ if ($ node instanceof NamespaceUseDeclaration) {
338+ return false ;
339+ }
340+
341+ if ($ node instanceof CaseStatementNode) {
342+ return true ;
343+ }
344+
345+ if ($ node instanceof CompoundStatementNode) {
346+ if ($ node ->parent instanceof MethodDeclaration && $ node ->openBrace instanceof MissingToken) {
347+ return false ;
348+ }
349+
350+ $ lastStmt = \end ($ node ->statements );
351+ if (false === $ lastStmt || $ lastStmt ->getEndPosition () > $ offset ->toInt ()) {
352+ return true ;
353+ }
354+
355+ return !$ lastStmt instanceof EchoStatement;
356+ }
357+
358+ if ($ node instanceof Expression) {
359+ return false ;
360+ }
361+
362+ if ($ node instanceof SwitchStatementNode) {
363+ if ([] === $ node ->caseStatements ) {
364+ return false ;
365+ }
366+
367+ return $ offset ->toInt () > $ node ->caseStatements [0 ]->getStartPosition ();
368+ }
369+
370+ if (
371+ $ node ->parent && $ node ->parent ->getEndPosition () === $ offset ->toInt ()
372+ && (
373+ $ node ->parent instanceof WhileStatement
374+ || $ node ->parent instanceof DoStatement
375+ || $ node ->parent instanceof IfStatementNode
376+ || $ node ->parent instanceof CatchClause
377+ || $ node ->parent instanceof ForeachStatement
378+ || $ node ->parent instanceof SwitchStatementNode
379+ ) && $ node ->parent ->openParen instanceof MissingToken
380+ ) {
381+ return true ;
382+ }
383+
384+ if (
385+ $ node instanceof WhileStatement
386+ || $ node instanceof IfStatementNode
387+ || $ node instanceof DoStatement
388+ || $ node instanceof CatchClause
389+ || $ node instanceof ForStatement
390+ || $ node instanceof ForeachStatement
391+ || $ node instanceof EchoStatement
392+ || $ node ->parent instanceof ExpressionList
393+ || $ node ->parent instanceof WhileStatement
394+ || $ node ->parent instanceof DoStatement
395+ || $ node ->parent instanceof IfStatementNode
396+ || $ node ->parent instanceof CatchClause
397+ || $ node ->parent instanceof ForeachStatement
398+ || $ node ->parent instanceof SwitchStatementNode
399+ ) {
400+ return false ;
401+ }
402+
403+ return $ node ->parent instanceof CaseStatementNode
404+ || $ node ->parent instanceof SourceFileNode
405+ || $ node ->parent instanceof CompoundStatementNode
406+ || $ node ->parent ?->parent instanceof CaseStatementNode
407+ || $ node ->parent ?->parent instanceof CompoundStatementNode;
408+ }
409+
410+ public static function loopOrSwitch (Node $ node ): bool
411+ {
412+ return $ node ->getFirstAncestor (
413+ DoStatement::class,
414+ ForStatement::class,
415+ ForeachStatement::class,
416+ SwitchStatementNode::class,
417+ WhileStatement::class,
418+ ) instanceof Node;
419+ }
420+
309421 public static function declaration (Node $ node , ByteOffset $ offset ): bool
310422 {
311423 if (!$ node ->parent ) {
0 commit comments