Skip to content

Commit 2c2eb6e

Browse files
committed
sq fixes
1 parent f00e40f commit 2c2eb6e

File tree

5 files changed

+118
-117
lines changed

5 files changed

+118
-117
lines changed

src/main/java/com/github/_1c_syntax/bsl/languageserver/aop/EventPublisherAspect.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.aspectj.lang.annotation.Aspect;
3838
import org.eclipse.lsp4j.InitializeParams;
3939
import org.eclipse.lsp4j.services.LanguageServer;
40-
import org.jspecify.annotations.Nullable;
4140
import org.springframework.context.ApplicationEvent;
4241
import org.springframework.context.ApplicationEventPublisher;
4342
import org.springframework.context.ApplicationEventPublisherAware;

src/main/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProvider.java

Lines changed: 67 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ public class SemanticTokensProvider {
136136
BSLLexer.ANNOTATION_CUSTOM_SYMBOL
137137
);
138138

139+
private static final Set<Integer> SPEC_LITERALS = Set.of(
140+
BSLLexer.UNDEFINED,
141+
BSLLexer.TRUE,
142+
BSLLexer.FALSE,
143+
BSLLexer.NULL
144+
);
145+
139146
private static final String[] NO_MODIFIERS = new String[0];
140147
private static final String[] DOC_ONLY = new String[]{SemanticTokenModifiers.Documentation};
141148

@@ -333,26 +340,33 @@ private void addAnnotationsFromAst(List<TokenEntry> entries, ParseTree parseTree
333340
}
334341

335342
private void addPreprocessorFromAst(List<TokenEntry> entries, ParseTree parseTree) {
336-
// 1) Regions as Namespace: handle all regionStart and regionEnd nodes explicitly
337-
for (var regionStart : Trees.<RegionStartContext>findAllRuleNodes(parseTree, BSLParser.RULE_regionStart)) {
338-
// Namespace only for '#'+keyword part to avoid overlap with region name token
339-
var preprocessor = Trees.<PreprocessorContext>getAncestorByRuleIndex(regionStart, BSLParser.RULE_preprocessor);
340-
if (preprocessor != null && regionStart.PREPROC_REGION() != null) {
341-
addRange(entries,
342-
Ranges.create(preprocessor.getStart(), regionStart.PREPROC_REGION().getSymbol()),
343-
SemanticTokenTypes.Namespace);
344-
} else {
345-
addNamespaceForPreprocessorNode(entries, regionStart);
343+
addRegionsNamespaces(entries, parseTree);
344+
addDirectives(entries, parseTree);
345+
addOtherPreprocs(entries, parseTree);
346+
}
347+
348+
// 2) Other preprocessor directives: Macro for each HASH and PREPROC_* token,
349+
// excluding region start/end (handled as Namespace)
350+
private void addOtherPreprocs(List<TokenEntry> entries, ParseTree parseTree) {
351+
for (var preprocessor : Trees.<PreprocessorContext>findAllRuleNodes(parseTree, BSLParser.RULE_preprocessor)) {
352+
boolean containsRegion = (preprocessor.regionStart() != null) || (preprocessor.regionEnd() != null);
353+
if (containsRegion) {
354+
continue; // region handled as Namespace above
346355
}
347-
// region name highlighted as Variable (consistent with #Использовать <libName>)
348-
if (regionStart.regionName() != null) {
349-
addRange(entries, Ranges.create(regionStart.regionName()), SemanticTokenTypes.Variable);
356+
357+
for (Token token : Trees.getTokens(preprocessor)) {
358+
if (token.getChannel() != Token.DEFAULT_CHANNEL) {
359+
continue;
360+
}
361+
String symbolicName = BSLLexer.VOCABULARY.getSymbolicName(token.getType());
362+
if (token.getType() == BSLLexer.HASH || (symbolicName != null && symbolicName.startsWith("PREPROC_"))) {
363+
addRange(entries, Ranges.create(token), SemanticTokenTypes.Macro);
364+
}
350365
}
351366
}
352-
for (var regionEnd : Trees.<RegionEndContext>findAllRuleNodes(parseTree, BSLParser.RULE_regionEnd)) {
353-
addNamespaceForPreprocessorNode(entries, regionEnd);
354-
}
367+
}
355368

369+
private void addDirectives(List<TokenEntry> entries, ParseTree parseTree) {
356370
// 1.1) Use directives as Namespace: #Использовать ... (moduleAnnotations scope)
357371
for (var use : Trees.<UseContext>findAllRuleNodes(parseTree, BSLParser.RULE_use)) {
358372
addNamespaceForUse(entries, use);
@@ -369,25 +383,28 @@ private void addPreprocessorFromAst(List<TokenEntry> entries, ParseTree parseTre
369383
addRange(entries, Ranges.create(nativeKw), SemanticTokenTypes.Macro);
370384
}
371385
}
386+
}
372387

373-
// 2) Other preprocessor directives: Macro for each HASH and PREPROC_* token,
374-
// excluding region start/end (handled as Namespace)
375-
for (var preprocessor : Trees.<PreprocessorContext>findAllRuleNodes(parseTree, BSLParser.RULE_preprocessor)) {
376-
boolean containsRegion = (preprocessor.regionStart() != null) || (preprocessor.regionEnd() != null);
377-
if (containsRegion) {
378-
continue; // region handled as Namespace above
388+
// 1) Regions as Namespace: handle all regionStart and regionEnd nodes explicitly
389+
private void addRegionsNamespaces(List<TokenEntry> entries, ParseTree parseTree) {
390+
for (var regionStart : Trees.<RegionStartContext>findAllRuleNodes(parseTree, BSLParser.RULE_regionStart)) {
391+
// Namespace only for '#'+keyword part to avoid overlap with region name token
392+
var preprocessor = Trees.<PreprocessorContext>getAncestorByRuleIndex(regionStart, BSLParser.RULE_preprocessor);
393+
if (preprocessor != null && regionStart.PREPROC_REGION() != null) {
394+
addRange(entries,
395+
Ranges.create(preprocessor.getStart(), regionStart.PREPROC_REGION().getSymbol()),
396+
SemanticTokenTypes.Namespace);
397+
} else {
398+
addNamespaceForPreprocessorNode(entries, regionStart);
379399
}
380-
381-
for (Token token : Trees.getTokens(preprocessor)) {
382-
if (token.getChannel() != Token.DEFAULT_CHANNEL) {
383-
continue;
384-
}
385-
String symbolicName = BSLLexer.VOCABULARY.getSymbolicName(token.getType());
386-
if (token.getType() == BSLLexer.HASH || (symbolicName != null && symbolicName.startsWith("PREPROC_"))) {
387-
addRange(entries, Ranges.create(token), SemanticTokenTypes.Macro);
388-
}
400+
// region name highlighted as Variable (consistent with #Использовать <libName>)
401+
if (regionStart.regionName() != null) {
402+
addRange(entries, Ranges.create(regionStart.regionName()), SemanticTokenTypes.Variable);
389403
}
390404
}
405+
for (var regionEnd : Trees.<RegionEndContext>findAllRuleNodes(parseTree, BSLParser.RULE_regionEnd)) {
406+
addNamespaceForPreprocessorNode(entries, regionEnd);
407+
}
391408
}
392409

393410
private void addNamespaceForPreprocessorNode(List<TokenEntry> entries, ParserRuleContext preprocessorChildNode) {
@@ -404,8 +421,8 @@ private void addNamespaceForPreprocessorNode(List<TokenEntry> entries, ParserRul
404421
}
405422

406423
private void addNamespaceForUse(List<TokenEntry> entries, UseContext useCtx) {
407-
TerminalNode hashNode = useCtx.HASH();
408-
TerminalNode useNode = useCtx.PREPROC_USE_KEYWORD();
424+
var hashNode = useCtx.HASH();
425+
var useNode = useCtx.PREPROC_USE_KEYWORD();
409426

410427
if (hashNode != null && useNode != null) {
411428
addRange(entries, Ranges.create(hashNode, useNode), SemanticTokenTypes.Namespace);
@@ -510,49 +527,26 @@ private void addLexicalTokens(List<Token> tokens, List<TokenEntry> entries) {
510527
for (Token token : tokens) {
511528
var tokenType = token.getType();
512529
var tokenText = Objects.toString(token.getText(), "");
513-
if (tokenText.isEmpty()) {
514-
continue;
515-
}
516-
517-
// strings
518-
if (STRING_TYPES.contains(tokenType)) {
519-
addRange(entries, Ranges.create(token), SemanticTokenTypes.String);
520-
continue;
521-
}
522-
523-
// date literals in single quotes
524-
if (tokenType == BSLLexer.DATETIME) {
525-
addRange(entries, Ranges.create(token), SemanticTokenTypes.String);
526-
continue;
527-
}
528-
529-
// numbers
530-
if (NUMBER_TYPES.contains(tokenType)) {
531-
addRange(entries, Ranges.create(token), SemanticTokenTypes.Number);
532-
continue;
533-
}
534-
535-
// operators and punctuators
536-
if (OPERATOR_TYPES.contains(tokenType)) {
537-
addRange(entries, Ranges.create(token), SemanticTokenTypes.Operator);
538-
continue;
530+
if (!tokenText.isEmpty()) {
531+
selectAndAddSemanticToken(entries, token, tokenType);
539532
}
533+
}
534+
}
540535

536+
private void selectAndAddSemanticToken(List<TokenEntry> entries, Token token, int tokenType) {
537+
if (STRING_TYPES.contains(tokenType)) { // strings
538+
addRange(entries, Ranges.create(token), SemanticTokenTypes.String);
539+
} else if (tokenType == BSLLexer.DATETIME) { // date literals in single quotes
540+
addRange(entries, Ranges.create(token), SemanticTokenTypes.String);
541+
} else if (NUMBER_TYPES.contains(tokenType)) { // numbers
542+
addRange(entries, Ranges.create(token), SemanticTokenTypes.Number);
543+
} else if (OPERATOR_TYPES.contains(tokenType)) { // operators and punctuators
544+
addRange(entries, Ranges.create(token), SemanticTokenTypes.Operator);
545+
} else if (tokenType == BSLLexer.AMPERSAND || ANNOTATION_TOKENS.contains(tokenType)) {
541546
// Skip '&' and all ANNOTATION_* symbol tokens here to avoid duplicate Decorator emission (handled via AST)
542-
if (tokenType == BSLLexer.AMPERSAND || ANNOTATION_TOKENS.contains(tokenType)) {
543-
continue;
544-
}
545-
546-
// specific literals as keywords: undefined/boolean/null
547-
if (tokenType == BSLLexer.UNDEFINED
548-
|| tokenType == BSLLexer.TRUE
549-
|| tokenType == BSLLexer.FALSE
550-
|| tokenType == BSLLexer.NULL) {
551-
addRange(entries, Ranges.create(token), SemanticTokenTypes.Keyword);
552-
continue;
553-
}
554-
555-
// keywords (by symbolic name suffix), skip PREPROC_* (handled via AST)
547+
} else if (SPEC_LITERALS.contains(tokenType)) { // specific literals as keywords: undefined/boolean/null
548+
addRange(entries, Ranges.create(token), SemanticTokenTypes.Keyword);
549+
} else { // keywords (by symbolic name suffix), skip PREPROC_* (handled via AST)
556550
String symbolicName = BSLLexer.VOCABULARY.getSymbolicName(tokenType);
557551
if (symbolicName != null && symbolicName.endsWith("_KEYWORD") && !symbolicName.startsWith("PREPROC_")) {
558552
addRange(entries, Ranges.create(token), SemanticTokenTypes.Keyword);

src/test/java/com/github/_1c_syntax/bsl/languageserver/infrastructure/CachePathProviderTest.java

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ void getCachePath_shouldContainHashSubdirectory(@TempDir Path tempDir) {
9090
// then
9191
// Get the last component (hash)
9292
var hashComponent = cachePath.getFileName().toString();
93-
93+
9494
// MD5 hash in hex is 32 characters
95-
assertThat(hashComponent).hasSize(32);
96-
assertThat(hashComponent).matches("[0-9a-f]{32}");
95+
assertThat(hashComponent)
96+
.hasSize(32)
97+
.matches("[0-9a-f]{32}");
9798
}
9899

99100
@Test
@@ -122,9 +123,9 @@ void getCachePath_shouldProduceExpectedStructure(@TempDir Path tempDir) {
122123

123124
// then
124125
// Check that the path structure ends with: .bsl-language-server/cache/{hash}
125-
assertThat(cachePath.getParent().getParent().getFileName().toString()).isEqualTo(".bsl-language-server");
126-
assertThat(cachePath.getParent().getFileName().toString()).isEqualTo("cache");
127-
126+
assertThat(cachePath.getParent().getParent().getFileName()).hasToString(".bsl-language-server");
127+
assertThat(cachePath.getParent().getFileName()).hasToString("cache");
128+
128129
// Verify the path starts with basePath
129130
assertThat(cachePath.toString()).startsWith(basePath);
130131
}
@@ -140,7 +141,7 @@ void getCachePath_shouldUseFullPathWhenProvided(@TempDir Path tempDir) {
140141
var cachePath = cachePathProvider.getCachePath(basePath, fullPath);
141142

142143
// then
143-
assertThat(cachePath.toString()).isEqualTo(fullPath);
144+
assertThat(cachePath).hasToString(fullPath);
144145
assertThat(cachePath.toString()).doesNotContain(".bsl-language-server");
145146
}
146147

@@ -155,7 +156,7 @@ void getCachePath_shouldIgnoreBasePathWhenFullPathProvided(@TempDir Path tempDir
155156
var cachePath = cachePathProvider.getCachePath(basePath, fullPath);
156157

157158
// then
158-
assertThat(cachePath.toString()).isEqualTo(fullPath);
159+
assertThat(cachePath).hasToString(fullPath);
159160
assertThat(cachePath.toString()).doesNotContain(basePath);
160161
}
161162

@@ -185,9 +186,10 @@ void getCachePath_withRealSystemProperties() {
185186

186187
// then
187188
assertThat(cachePath).isNotNull();
188-
assertThat(cachePath.toString()).startsWith(basePath);
189-
assertThat(cachePath.toString()).contains(".bsl-language-server");
190-
assertThat(cachePath.toString()).contains("cache");
189+
assertThat(cachePath.toString())
190+
.startsWith(basePath)
191+
.contains(".bsl-language-server")
192+
.contains("cache");
191193
}
192194

193195
@Test
@@ -216,8 +218,9 @@ void getCachePath_withInstanceNumberZero_shouldNotAddSuffix(@TempDir Path tempDi
216218

217219
// then
218220
var fileName = cachePath.getFileName().toString();
219-
assertThat(fileName).doesNotContain("@");
220-
assertThat(fileName).hasSize(32); // MD5 hash length
221+
assertThat(fileName)
222+
.doesNotContain("@")
223+
.hasSize(32); // MD5 hash length
221224
}
222225

223226
@Test
@@ -232,8 +235,9 @@ void getCachePath_instanceNumberedPaths_shouldBeDifferent(@TempDir Path tempDir)
232235
var cachePath2 = cachePathProvider.getCachePath(basePath, fullPath, 2);
233236

234237
// then
235-
assertThat(cachePath0).isNotEqualTo(cachePath1);
236-
assertThat(cachePath0).isNotEqualTo(cachePath2);
238+
assertThat(cachePath0)
239+
.isNotEqualTo(cachePath1)
240+
.isNotEqualTo(cachePath2);
237241
assertThat(cachePath1).isNotEqualTo(cachePath2);
238242
}
239243

@@ -250,8 +254,9 @@ void getCachePath_withInstanceNumber_shouldShareParentDirectory(@TempDir Path te
250254

251255
// then
252256
// All instances should have the same parent (cache directory)
253-
assertThat(cachePath0.getParent()).isEqualTo(cachePath1.getParent());
254-
assertThat(cachePath0.getParent()).isEqualTo(cachePath2.getParent());
257+
assertThat(cachePath0.getParent())
258+
.isEqualTo(cachePath1.getParent())
259+
.isEqualTo(cachePath2.getParent());
255260
}
256261

257262
@Test
@@ -267,8 +272,9 @@ void getCachePath_withInstanceNumber_shouldIgnoreWhenFullPathProvided(@TempDir P
267272

268273
// then
269274
// When fullPath is provided, instance number should be ignored
270-
assertThat(cachePath0).isEqualTo(customPath);
275+
assertThat(cachePath0)
276+
.isEqualTo(customPath)
277+
.isEqualTo(cachePath1);
271278
assertThat(cachePath1).isEqualTo(customPath);
272-
assertThat(cachePath0).isEqualTo(cachePath1);
273279
}
274280
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ void testCommonModuleVariableReassignment() throws IOException {
370370
.filter(ref -> ref.getUri().equals(documentContext.getUri()))
371371
.toList();
372372
// Не должно быть ссылок, так как вызов после переназначения на Неопределено
373-
assertThat(referencesToFuncFromTest).hasSize(0);
373+
assertThat(referencesToFuncFromTest).isEmpty();
374374
}
375375

376376
@Test
@@ -452,7 +452,7 @@ void testCommonModuleVariableIsolationBetweenMethods() throws IOException {
452452
var referencesToFuncFromTest = referencesToFunc.stream()
453453
.filter(ref -> ref.getUri().equals(documentContext.getUri()))
454454
.toList();
455-
assertThat(referencesToFuncFromTest).hasSize(0);
455+
assertThat(referencesToFuncFromTest).isEmpty();
456456
}
457457

458458
@Test

0 commit comments

Comments
 (0)