2222package com .github ._1c_syntax .bsl .languageserver .context .computer ;
2323
2424import com .github ._1c_syntax .bsl .languageserver .context .DocumentContext ;
25+ import com .github ._1c_syntax .bsl .languageserver .context .symbol .MethodSymbol ;
26+ import com .github ._1c_syntax .bsl .languageserver .context .symbol .ModuleSymbol ;
27+ import com .github ._1c_syntax .bsl .languageserver .context .symbol .SourceDefinedSymbol ;
2528import com .github ._1c_syntax .bsl .languageserver .context .symbol .VariableSymbol ;
2629import com .github ._1c_syntax .bsl .languageserver .context .symbol .variable .VariableDescription ;
2730import com .github ._1c_syntax .bsl .languageserver .context .symbol .variable .VariableKind ;
3235import com .github ._1c_syntax .bsl .parser .BSLParserRuleContext ;
3336import org .antlr .v4 .runtime .Token ;
3437import org .antlr .v4 .runtime .tree .ParseTree ;
38+ import org .eclipse .lsp4j .Range ;
3539
3640import java .util .ArrayList ;
41+ import java .util .Collections ;
3742import java .util .HashSet ;
3843import java .util .List ;
44+ import java .util .Map ;
3945import java .util .Optional ;
4046import java .util .Set ;
47+ import java .util .TreeMap ;
48+ import java .util .function .Function ;
49+
50+ import static java .util .stream .Collectors .groupingBy ;
51+ import static java .util .stream .Collectors .toMap ;
4152
4253public class VariableSymbolComputer extends BSLParserBaseVisitor <ParseTree > implements Computer <List <VariableSymbol >> {
4354
4455 private final DocumentContext documentContext ;
56+ private final ModuleSymbol module ;
57+ private final Map <Range , SourceDefinedSymbol > methods ;
4558 private final Set <VariableSymbol > variables = new HashSet <>();
59+ private final Map <String , String > currentMethodVariables = new TreeMap <>(String .CASE_INSENSITIVE_ORDER );
60+ private final Map <String , String > moduleVariables = new TreeMap <>(String .CASE_INSENSITIVE_ORDER );
61+
62+ private SourceDefinedSymbol currentMethod ;
4663
47- public VariableSymbolComputer (DocumentContext documentContext ) {
64+ public VariableSymbolComputer (DocumentContext documentContext , ModuleSymbol module , List < MethodSymbol > methods ) {
4865 this .documentContext = documentContext ;
66+ this .module = module ;
67+ this .methods = methods .stream ().collect (toMap (MethodSymbol ::getSubNameRange , Function .identity ()));
68+ this .currentMethod = module ;
4969 }
5070
5171 @ Override
5272 public List <VariableSymbol > compute () {
5373 variables .clear ();
74+ moduleVariables .clear ();
5475 visitFile (documentContext .getAst ());
5576 return new ArrayList <>(variables );
5677 }
5778
5879 @ Override
5980 public ParseTree visitModuleVarDeclaration (BSLParser .ModuleVarDeclarationContext ctx ) {
60- var symbol = createVariableSymbol (ctx , ctx .var_name (), ctx .EXPORT_KEYWORD () != null , VariableKind .MODULE );
81+ var symbol = VariableSymbol .builder ()
82+ .name (ctx .var_name ().getText ())
83+ .owner (documentContext )
84+ .range (Ranges .create (ctx ))
85+ .variableNameRange (Ranges .create (ctx .var_name ()))
86+ .export (ctx .EXPORT_KEYWORD () != null )
87+ .kind (VariableKind .MODULE )
88+ .description (createDescription (ctx ))
89+ .scope (module )
90+ .build ();
6191 variables .add (symbol );
62-
92+ moduleVariables . put ( ctx . var_name (). getText (), ctx . var_name (). getText ());
6393 return ctx ;
6494 }
6595
96+ @ Override
97+ public ParseTree visitSub (BSLParser .SubContext ctx ) {
98+ this .currentMethod = getVariableScope (ctx );
99+ ParseTree tree = super .visitSub (ctx );
100+ currentMethodVariables .clear ();
101+ this .currentMethod = module ;
102+ return tree ;
103+ }
104+
66105 @ Override
67106 public ParseTree visitSubVarDeclaration (BSLParser .SubVarDeclarationContext ctx ) {
68- var symbol = createVariableSymbol (ctx , ctx .var_name (), false , VariableKind .LOCAL );
107+ var symbol = VariableSymbol .builder ()
108+ .name (ctx .var_name ().getText ())
109+ .owner (documentContext )
110+ .range (Ranges .create (ctx ))
111+ .variableNameRange (Ranges .create (ctx .var_name ()))
112+ .export (false )
113+ .kind (VariableKind .LOCAL )
114+ .description (createDescription (ctx ))
115+ .scope (getVariableScope (ctx ))
116+ .build ();
69117 variables .add (symbol );
118+ currentMethodVariables .put (ctx .var_name ().getText (), ctx .var_name ().getText ());
119+ return ctx ;
120+ }
70121
122+ @ Override
123+ public ParseTree visitParam (BSLParser .ParamContext ctx ) {
124+ if (ctx .IDENTIFIER () == null ) {
125+ return ctx ;
126+ }
127+
128+ var variable = VariableSymbol .builder ()
129+ .name (ctx .IDENTIFIER ().getText ())
130+ .scope (currentMethod )
131+ .owner (documentContext )
132+ .range (Ranges .create (ctx ))
133+ .variableNameRange (Ranges .create (ctx .IDENTIFIER ()))
134+ .export (false )
135+ .kind (VariableKind .PARAMETER )
136+ .description (Optional .empty ())
137+ .build ();
138+ variables .add (variable );
139+
140+ currentMethodVariables .put (ctx .IDENTIFIER ().getText (), ctx .IDENTIFIER ().getText ());
71141 return ctx ;
72142 }
73143
74- private VariableSymbol createVariableSymbol (
75- BSLParserRuleContext ctx ,
76- BSLParser .Var_nameContext varName ,
77- boolean export ,
78- VariableKind kind
79- ) {
80- return VariableSymbol .builder ()
81- .name (varName .getText ())
144+ @ Override
145+ public ParseTree visitLValue (BSLParser .LValueContext ctx ) {
146+ if (
147+ ctx .getChildCount () > 1
148+ || currentMethodVariables .containsKey (ctx .getText ())
149+ || moduleVariables .containsKey (ctx .getText ())
150+ ) {
151+ return ctx ;
152+ }
153+
154+ var variable = VariableSymbol .builder ()
155+ .name (ctx .getText ())
82156 .owner (documentContext )
83157 .range (Ranges .create (ctx ))
84- .variableNameRange (Ranges .create (varName ))
85- .export (export )
86- .kind (kind )
158+ .variableNameRange (Ranges .create (ctx ))
159+ .export (false )
160+ .kind (VariableKind .DYNAMIC )
161+ .scope (currentMethod )
87162 .description (createDescription (ctx ))
88163 .build ();
164+ variables .add (variable );
165+
166+ currentMethodVariables .put (ctx .getText (), ctx .getText ());
167+ return ctx ;
168+ }
169+
170+ private SourceDefinedSymbol getVariableScope (BSLParser .SubVarDeclarationContext ctx ) {
171+ var sub = (BSLParser .SubContext ) Trees .getRootParent (ctx , BSLParser .RULE_sub );
172+ if (sub == null ) {
173+ return module ;
174+ }
175+
176+ return getVariableScope (sub );
177+ }
178+
179+ private SourceDefinedSymbol getVariableScope (BSLParser .SubContext ctx ) {
180+ BSLParserRuleContext subNameNode ;
181+ if (Trees .nodeContainsErrors (ctx )) {
182+ return module ;
183+ } else if (ctx .function () != null ) {
184+ subNameNode = ctx .function ().funcDeclaration ().subName ();
185+ } else {
186+ subNameNode = ctx .procedure ().procDeclaration ().subName ();
187+ }
188+
189+ return methods .getOrDefault (Ranges .create (subNameNode ), module );
190+ }
191+
192+ private Optional <VariableDescription > createDescription (BSLParser .LValueContext ctx ) {
193+ var trailingComments = Trees .getTrailingComment (documentContext .getTokens (), ctx .getStop ());
194+
195+ if (trailingComments .isEmpty ()) {
196+ return Optional .empty ();
197+ }
198+
199+ return Optional .of (
200+ new VariableDescription (Collections .emptyList (), trailingComments )
201+ );
89202 }
90203
91204 private Optional <VariableDescription > createDescription (BSLParserRuleContext ctx ) {
@@ -108,5 +221,4 @@ private Optional<VariableDescription> createDescription(BSLParserRuleContext ctx
108221
109222 }
110223
111-
112- }
224+ }
0 commit comments