11package org .kdb .inside .brains .psi .mixin ;
22
33import com .intellij .lang .ASTNode ;
4- import com .intellij .psi .PsiElement ;
5- import com .intellij .psi .PsiRecursiveElementWalkingVisitor ;
4+ import com .intellij .psi .* ;
5+ import com .intellij .psi .templateLanguages . OuterLanguageElement ;
66import icons .KdbIcons ;
77import org .jetbrains .annotations .NotNull ;
88import org .jetbrains .annotations .Nullable ;
99import org .kdb .inside .brains .psi .*;
1010import org .kdb .inside .brains .psi .impl .QExpressionImpl ;
1111
1212import javax .swing .*;
13+ import java .util .List ;
1314
1415public abstract class QLambdaMixin extends QExpressionImpl implements QLambda {
1516 public QLambdaMixin (ASTNode node ) {
@@ -48,29 +49,77 @@ public boolean isImplicitDeclaration(@NotNull QVariable variable) {
4849 return null ;
4950 }
5051
52+ final QExpressions expressions = getExpressions ();
53+ if (expressions == null ) {
54+ return null ;
55+ }
56+
57+ final List <QExpression > list = expressions .getExpressionList ();
58+ if (list .isEmpty ()) {
59+ return null ;
60+ }
61+
5162 final String name = variable .getName ();
52- final QVarDeclaration [] res = new QVarDeclaration [1 ];
53- acceptChildren (new PsiRecursiveElementWalkingVisitor () {
54- @ Override
55- public void visitElement (@ NotNull PsiElement element ) {
56- // we don't search inside others lambda, query, table or dict
57- if (QPsiUtil .isLocalContextElement (element )) {
58- return ;
59- }
6063
61- // no reason to search after the definition.// In a lambda it can't be below.
62- if (element .equals (variable )) {
63- stopWalking ();
64- } else if (element instanceof QVarDeclaration d ) {
65- if (name .equals (d .getName ()) && !QPsiUtil .isGlobalDeclaration (d )) {
66- res [0 ] = d ;
67- stopWalking ();
64+ final SearchResult result = new SearchResult ();
65+ for (QExpression expression : list ) {
66+ // We iterate over each expression and takes the right as the best because Q is right-to-left language
67+ expression .accept (new PsiRecursiveElementWalkingVisitor () {
68+ @ Override
69+ public void visitElement (@ NotNull PsiElement element ) {
70+ // we don't search inside others lambda, query, table or dict
71+ if (isContextualElement (element )) {
72+ return ;
6873 }
69- } else {
70- super .visitElement (element );
74+
75+ // no reason to search after the definition.// In a lambda it can't be below.
76+ if (element .equals (variable )) {
77+ result .containsVariable = true ;
78+ } else if (element instanceof QVarDeclaration d ) {
79+ if (name .equals (d .getName ()) && !QPsiUtil .isGlobalDeclaration (d )) {
80+ result .declaration = d ;
81+ }
82+ } else {
83+ super .visitElement (element );
84+ }
85+ }
86+
87+ @ Override
88+ public void visitComment (@ NotNull PsiComment ignore ) {
89+ }
90+
91+ @ Override
92+ public void visitPlainText (@ NotNull PsiPlainText ignore ) {
7193 }
94+
95+ @ Override
96+ public void visitWhiteSpace (@ NotNull PsiWhiteSpace ignore ) {
97+ }
98+
99+ @ Override
100+ public void visitErrorElement (@ NotNull PsiErrorElement ignore ) {
101+ }
102+
103+ @ Override
104+ public void visitOuterLanguageElement (@ NotNull OuterLanguageElement ignore ) {
105+ }
106+ });
107+
108+ // if the declaration found - grate;
109+ // if the expression contains the original variable and no declaration in the expression, we stop anyway.
110+ if (result .declaration != null || result .containsVariable ) {
111+ return result .declaration ;
72112 }
73- });
74- return res [0 ];
113+ }
114+ return null ;
115+ }
116+
117+ private boolean isContextualElement (@ NotNull PsiElement element ) {
118+ return element instanceof QLambdaExpr || element instanceof QQueryExpr || element instanceof QTableExpr || element instanceof QDictExpr ;
119+ }
120+
121+ private static class SearchResult {
122+ boolean containsVariable ;
123+ QVarDeclaration declaration ;
75124 }
76125}
0 commit comments