Skip to content

Commit d21ab14

Browse files
committed
Переменные созданные при инициализации циклов
Добавлены в индекс переменные созданные при работе циклов Для... и Для Каждого... Объяевление переменной в объявлении цикла работает так же как и объявление переменной присваиванием. Тип ссылки OccurrenceType.DEFINITION, тип переменной VariableKind.DYNAMIC
1 parent e5061c3 commit d21ab14

File tree

4 files changed

+129
-19
lines changed

4 files changed

+129
-19
lines changed

src/main/java/com/github/_1c_syntax/bsl/languageserver/context/computer/VariableSymbolComputer.java

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.github._1c_syntax.bsl.parser.BSLParserRuleContext;
3636
import org.antlr.v4.runtime.Token;
3737
import org.antlr.v4.runtime.tree.ParseTree;
38+
import org.antlr.v4.runtime.tree.TerminalNode;
3839
import org.eclipse.lsp4j.Range;
3940

4041
import java.util.ArrayList;
@@ -154,27 +155,34 @@ public ParseTree visitLValue(BSLParser.LValueContext ctx) {
154155
return ctx;
155156
}
156157

157-
var variable = VariableSymbol.builder()
158-
.name(ctx.getText().intern())
159-
.owner(documentContext)
160-
.range(Ranges.create(ctx))
161-
.variableNameRange(Ranges.create(ctx))
162-
.export(false)
163-
.kind(VariableKind.DYNAMIC)
164-
.scope(currentMethod)
165-
.description(createDescription(ctx))
166-
.build();
167-
variables.add(variable);
158+
updateVariablesCache(ctx.IDENTIFIER(), createDescription(ctx));
159+
return ctx;
160+
}
168161

169-
// Если файл с ошибками разбора может возникнуть ситуация, когда по дереву мы будем находиться внутри метода,
170-
// но при определении скоупа в модуле. В таких случаях будем сохранять описание в коллекции переменных модуля.
171-
if (currentMethod == module) {
172-
moduleVariables.put(ctx.getText(), ctx.getText());
173-
} else {
174-
currentMethodVariables.put(ctx.getText(), ctx.getText());
162+
@Override
163+
public ParseTree visitForStatement(BSLParser.ForStatementContext ctx) {
164+
if (
165+
currentMethodVariables.containsKey(ctx.IDENTIFIER().getText())
166+
|| moduleVariables.containsKey(ctx.IDENTIFIER().getText())
167+
) {
168+
return super.visitForStatement(ctx);
175169
}
176170

177-
return ctx;
171+
updateVariablesCache(ctx.IDENTIFIER(), createDescription(ctx));
172+
return super.visitForStatement(ctx);
173+
}
174+
175+
@Override
176+
public ParseTree visitForEachStatement(BSLParser.ForEachStatementContext ctx) {
177+
if (
178+
currentMethodVariables.containsKey(ctx.IDENTIFIER().getText())
179+
|| moduleVariables.containsKey(ctx.IDENTIFIER().getText())
180+
) {
181+
return super.visitForEachStatement(ctx);
182+
}
183+
184+
updateVariablesCache(ctx.IDENTIFIER(), createDescription(ctx));
185+
return super.visitForEachStatement(ctx);
178186
}
179187

180188
private SourceDefinedSymbol getVariableScope(BSLParser.SubVarDeclarationContext ctx) {
@@ -231,4 +239,26 @@ private Optional<VariableDescription> createDescription(BSLParserRuleContext ctx
231239

232240
}
233241

242+
private void updateVariablesCache(TerminalNode node, Optional<VariableDescription> description) {
243+
var variable = VariableSymbol.builder()
244+
.name(node.getText().intern())
245+
.owner(documentContext)
246+
.range(Ranges.create(node))
247+
.variableNameRange(Ranges.create(node))
248+
.export(false)
249+
.kind(VariableKind.DYNAMIC)
250+
.scope(currentMethod)
251+
.description(description)
252+
.build();
253+
variables.add(variable);
254+
255+
// Если файл с ошибками разбора может возникнуть ситуация, когда по дереву мы будем находиться внутри метода,
256+
// но при определении скоупа в модуле. В таких случаях будем сохранять описание в коллекции переменных модуля.
257+
if (currentMethod == module) {
258+
moduleVariables.put(node.getText(), node.getText());
259+
} else {
260+
currentMethodVariables.put(node.getText(), node.getText());
261+
}
262+
}
263+
234264
}

src/main/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFiller.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,46 @@ public BSLParserRuleContext visitComplexIdentifier(BSLParser.ComplexIdentifierCo
261261
return super.visitComplexIdentifier(ctx);
262262
}
263263

264+
@Override
265+
public BSLParserRuleContext visitForStatement(BSLParser.ForStatementContext ctx) {
266+
if (ctx.IDENTIFIER() == null) {
267+
return super.visitForStatement(ctx);
268+
}
269+
270+
findVariableSymbol(ctx.IDENTIFIER().getText()).ifPresent(s -> {
271+
if (notVariableInitialization(ctx, s)) {
272+
addVariableUsage(
273+
s.getRootParent(SymbolKind.Method),
274+
ctx.IDENTIFIER().getText(),
275+
Ranges.create(ctx.IDENTIFIER()),
276+
false
277+
);
278+
}
279+
});
280+
281+
return super.visitForStatement(ctx);
282+
}
283+
284+
@Override
285+
public BSLParserRuleContext visitForEachStatement(BSLParser.ForEachStatementContext ctx) {
286+
if (ctx.IDENTIFIER() == null) {
287+
return super.visitForEachStatement(ctx);
288+
}
289+
290+
findVariableSymbol(ctx.IDENTIFIER().getText()).ifPresent(s -> {
291+
if (notVariableInitialization(ctx, s)) {
292+
addVariableUsage(
293+
s.getRootParent(SymbolKind.Method),
294+
ctx.IDENTIFIER().getText(),
295+
Ranges.create(ctx.IDENTIFIER()),
296+
false
297+
);
298+
}
299+
});
300+
301+
return super.visitForEachStatement(ctx);
302+
}
303+
264304
private Optional<VariableSymbol> findVariableSymbol(String variableName) {
265305
var variableSymbol = documentContext.getSymbolTree()
266306
.getVariableSymbol(variableName, currentScope);
@@ -281,6 +321,14 @@ private boolean notVariableInitialization(BSLParser.ModuleVarDeclarationContext
281321
return !Ranges.containsRange(variableSymbol.getRange(), Ranges.create(ctx));
282322
}
283323

324+
private boolean notVariableInitialization(BSLParser.ForStatementContext ctx, VariableSymbol variableSymbol) {
325+
return !Ranges.containsRange(variableSymbol.getRange(), Ranges.create(ctx.IDENTIFIER()));
326+
}
327+
328+
private boolean notVariableInitialization(BSLParser.ForEachStatementContext ctx, VariableSymbol variableSymbol) {
329+
return !Ranges.containsRange(variableSymbol.getRange(), Ranges.create(ctx.IDENTIFIER()));
330+
}
331+
284332
private void addVariableUsage(Optional<SourceDefinedSymbol> methodSymbol,
285333
String variableName,
286334
Range range,

src/test/java/com/github/_1c_syntax/bsl/languageserver/references/ReferenceIndexFillerTest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,33 @@ void testFindVariables() {
100100
.getMethodSymbol("ТретийМетод");
101101
assertThat(scopeMethod).isPresent();
102102
var references = referenceIndex.getReferencesFrom(scopeMethod.get());
103-
assertThat(references).hasSize(11);
103+
assertThat(references).hasSize(13);
104104

105105
var targetVariable = documentContext.getSymbolTree().getVariables().get(0);
106106
var usage = referenceIndex.getReferencesTo(targetVariable);
107107
assertThat(usage).hasSize(5);
108108
}
109109

110+
@Test
111+
void testFindVariablesInForStatements() {
112+
DocumentContext documentContext = TestUtils.getDocumentContextFromFile(
113+
"./src/test/resources/references/ReferenceIndexFillerVariableTest.bsl"
114+
);
115+
referenceIndexFiller.fill(documentContext);
116+
117+
var referencedForStatementsSymbol = referenceIndex.getReference(
118+
documentContext.getUri(),
119+
new Position(38, 25)
120+
);
121+
assertThat(referencedForStatementsSymbol).isPresent();
122+
123+
var referencedForEachStatementSymbol = referenceIndex.getReference(
124+
documentContext.getUri(),
125+
new Position(44, 30)
126+
);
127+
assertThat(referencedForEachStatementSymbol).isPresent();
128+
}
129+
110130
@Test
111131
void testFindVariablesRangesCallStatement() {
112132
DocumentContext documentContext = TestUtils.getDocumentContextFromFile(

src/test/resources/references/ReferenceIndexFillerVariableTest.bsl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@
3434
Модуль.Метод(Параметр3);
3535
Третья = Модуль.Метод();
3636

37+
Для Каждого ЭлементКоллекции Из Коллекция Цикл
38+
39+
Метод(ЭлементКоллекции);
40+
41+
КонецЦикла;
42+
43+
Для Счетчик = 1 По 100 Цикл
44+
45+
Коллекция.Добавить(Счетчик);
46+
47+
КонецЦикла;
48+
3749
КонецФункции
3850

3951
Метод(Модуль, Модуль2);

0 commit comments

Comments
 (0)