Skip to content

Поддержка семантической подсветки лямбд внутри строковых литералов (sfaqer/lambdas)#3860

Draft
Copilot wants to merge 22 commits intodevelopfrom
copilot/add-semantic-highlighting-for-lambdas
Draft

Поддержка семантической подсветки лямбд внутри строковых литералов (sfaqer/lambdas)#3860
Copilot wants to merge 22 commits intodevelopfrom
copilot/add-semantic-highlighting-for-lambdas

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

Строки внутри вызовов лямбда-методов (например, Лямбда.Выражение("Параметр -> Возврат Параметр > 5")) теперь подсвечиваются как BSL-код — с выделением ключевых слов, операторов и чисел — вместо отображения одним цветом строки.

Changes

  • StringContext.LAMBDA — новый контекст строки; не объединяется с другими контекстами через combine()
  • SemanticTokensOptions.lambdaMethods — конфигурируемый список паттернов Модуль.Метод, по умолчанию ["Лямбда.Выражение"]. Переиспользует ParsedStrTemplateMethods для парсинга паттернов
  • SpecialContextVisitor — расширен третьим параметром parsedLambdaMethods; детектит лямбда-вызовы в visitGlobalMethodCall и processModuleMethodCall
  • StringSemanticTokensSupplier.processLambdaString() — извлекает содержимое строки, токенизирует через BSLLexer, маппит BSL-токены на семантические типы (Keyword, Operator, Number), заполняет промежутки как String
  • schema.json — добавлено свойство lambdaMethods в секцию semanticTokens

Example

{
  "semanticTokens": {
    "lambdaMethods": [
      "Лямбда.Выражение",
      "Lambda.Expression"
    ]
  }
}
// Содержимое строки получает подсветку: Возврат (Keyword), > (Operator), 5 (Number)
Результат = Лямбда.Выражение("Параметр -> Возврат Параметр > 5");

⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

Copilot AI and others added 2 commits March 23, 2026 08:19
Adds support for the sfaqer/lambdas library by parsing BSL code inside
string parameters of configurable lambda methods (e.g., Лямбда.Выражение).

Changes:
- Add LAMBDA context to StringContext enum
- Add lambdaMethods configuration to SemanticTokensOptions
- Extend SpecialContextVisitor to detect lambda method calls
- Add processLambdaString in StringSemanticTokensSupplier using BSL lexer
- Update JSON schema with lambdaMethods property
- Add tests for lambda semantic highlighting and configuration

Co-authored-by: nixel2007 <1132840+nixel2007@users.noreply.github.com>
Agent-Logs-Url: https://github.com/1c-syntax/bsl-language-server/sessions/bb8c052a-c688-4797-ac97-7de78ede20a0
Copilot AI changed the title [WIP] Add support for semantic highlighting of lambdas in string literals Поддержка семантической подсветки лямбд внутри строковых литералов (sfaqer/lambdas) Mar 23, 2026
Copilot AI requested a review from nixel2007 March 23, 2026 08:31
nixel2007 and others added 4 commits March 23, 2026 14:23
Integrate lambda highlighting into StringSemanticTokensSupplier using
the same architecture as queries/NStr/StrTemplate (token splitting).

Changes:
- Remove standalone LambdaStringSemanticTokensSupplier
- Detect lambdas via -> regex in any string (OS files only)
- Tokenize lambda body with BSLTokenizer (not raw BSLLexer)
- Highlight lambda parameters as Parameter type
- Highlight parentheses, commas and arrow as Operator type
- Split string tokens around lambda sub-tokens to prevent overlap

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ual DocumentContext

Instead of manually tokenizing the lambda body and mapping token types,
create a position-padded virtual DocumentContext (like QueryComputer does
for SDBL queries) and call ALL other semantic token suppliers on it.

Benefits:
- Free highlighting of nested strings, NStr, StrTemplate, queries
- Automatic support for any future supplier additions
- Removes manual token type mapping (LAMBDA_NUMBER_TYPES, etc.)

Position preservation uses the same technique as queries: pad with
empty lines and spaces so tokenizer output positions match the
original document. Double quotes are replaced preserving positions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace simple "" → "  with the alternating pattern from
QueryComputer.removeDoubleQuotes: opening "" → ' "' (space+quote),
closing "" → '" ' (quote+space). This correctly unescapes double
quotes while preserving character positions for the BSL tokenizer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…da bodies

VSCode applies TextMate string.quoted.double.bsl scope to entire string
literals, coloring gaps between semantic tokens green. Add custom 'source'
token type to the legend that VSCode doesn't recognize, causing it to
render those gaps with default foreground color instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

Test Results

1 944 files  1 944 suites   48m 19s ⏱️
1 252 tests 1 252 ✅ 0 💤 0 ❌
7 512 runs  7 512 ✅ 0 💤 0 ❌

Results for commit 3d3ec26.

♻️ This comment has been updated with latest results.

nixel2007 and others added 15 commits March 23, 2026 23:47
…ghlighting

Wrap the lambda body in a fake 'Функция _Лямбда(params) Возврат ... КонецФункции'
so the BSL parser builds proper AST nodes and SymbolsSemanticTokensSupplier
highlights parameter references in the body. Add SOURCE custom token type
to override TextMate string scope in lambda body gaps. Use UUID for
virtual document URIs to avoid collisions in parallel execution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove PROCESSING_LAMBDA ThreadLocal and the filter(s != this) exclusion.
StringSemanticTokensSupplier now processes virtual documents like any other,
enabling recursive highlighting of lambdas nested inside lambda bodies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mbda support

- Add semantic token mapping for annotation tokens in lambda parameters:
  AMPERSAND and ANNOTATION_*_SYMBOL as Decorator, STRING, DECIMAL/FLOAT,
  DATETIME, TRUE/FALSE/UNDEFINED/NULL, PLUS/MINUS, ASSIGN
- Fix nested lambda highlighting: StringSemanticTokensSupplier was missing
  from allSuppliers list due to @lazy injection not including self.
  Replaced with lazy ApplicationContext.getBeansOfType() resolution.
- Remove unused @lazy import
- Add tests for annotation params and nested lambdas
- Delete temporary TokenTest.java

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rings

- Add CustomSemanticTokenTypes.STRING_ESCAPE for escaped quote pairs
- Register stringEscape in SemanticTokensLegend
- Scan fullContent for "" pairs and add escape SubTokens
- Remove overlapping body tokens when they conflict with escape tokens
- Fix nested lambda support: use ApplicationContext.getBeansOfType()
  for lazy supplier resolution (includes StringSemanticTokensSupplier itself)
- Add tests for escape highlighting in both params and body

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add collectSpecialContextSubTokens() to scan params area (left of ->)
for %N placeholders (StrTemplate) and language keys (NStr) when the
lambda string is inside a СтрШаблон/НСтр call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Scan body (right of ->) for %N placeholders before adding virtual doc
tokens, so removeOverlappingTokens gives placeholder tokens priority
over BSL lexer's % (Operator) + 1 (Number) split.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…emoval

Body tokens from virtual document (e.g. STRINGTAIL |" ) can start
before an escape token ("") and hide it during left-to-right overlap
removal. Now removeOverlappingTokens first removes any non-escape
tokens that overlap with escape token intervals, then does the
standard sweep.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The custom SOURCE token type doesn't work in VSCode to override
TextMate string scope. Replace all SOURCE gap-filling with standard
SemanticTokenTypes.String and remove SOURCE from legend and
CustomSemanticTokenTypes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NStr strings have 'ru = ...' format and should never be detected as
lambda expressions, even if the content contains ->. Move special
context check before lambda check in processStringToken so NStr
context takes priority.

Also revert unnecessary cosmetic refactoring in SpecialContextVisitor
and add tests for NStr inside lambda and StrTemplate via variable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…clusion, fix NStr test

- Delete CustomSemanticTokenTypes.java entirely (STRING_ESCAPE doesn't work in VSCode)
- Remove collectEscapedQuoteTokens and escape-priority logic from removeOverlappingTokens
- Remove STRING_ESCAPE from SemanticTokensLegend
- Fix getAllSuppliers() to include StringSemanticTokensSupplier itself
  (ObjectProvider excludes self due to circular dependency)
- Remove STRING from mapLambdaParamTokenToSemanticType (gap-fill covers it)
- Fix testNStrInsideLambda: ru is a lambda param, not NStr key
  (findLanguageKeyPositions requires 'key = value' format)
- Update escape-related test assertions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
STRING_ESCAPE custom token type makes VSCode ignore semantic coloring
for escaped double-quotes, allowing TextMate grammar to highlight them
as constant.character.escape instead.

Restores:
- CustomSemanticTokenTypes.STRING_ESCAPE
- STRING_ESCAPE in semantic tokens legend
- collectEscapedQuoteTokens method
- Escape-priority logic in removeOverlappingTokens
- STRING mapping in lambda param token map
- Test assertions for escape tokens

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace volatile lazy init with @PostConstruct initialization
- Add @SuppressWarnings("NullAway.Init") on allSuppliers field
- Add @nullable to mapLambdaParamTokenToSemanticType return type
- Remove fully-qualified java.util.ArrayList usage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Convert mapLambdaParamTokenToSemanticType to Map lookup (S1541, S1142)
- Extract fillBodyLineContents, buildFunctionHeader, mapBodyTokensToResult
  helpers to reduce complexity (S3776, S1541)
- Convert extractLambdaFullContent, buildContentSegments, groupStringTokens
  to switch expressions (S126, S6880)
- Move static constants to class top (S1213)
- Replace magic number 2 with ESCAPE_QUOTE_LENGTH/ARROW_LENGTH (S109)
- Remove unused cleaned param from mapCleanedOffsetToOriginal (S1172)
- Merge continues in collectLambdaParamTokens (S135)
- Use var, move declarations closer to usage (S6212, S1941)
- Replace FQNs with imports (S1942)
- Suppress S6411 (Token as Map key) and S1200 (class deps) at class level
- Suppress S6126 on 3 test methods with positional string assertions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ling

Move all lambda-related constants, methods, and the ContentSegment record
from StringSemanticTokensSupplier into a dedicated LambdaStringTokenizer class.
This resolves S1200 (too many dependencies) by splitting the 991-line class
into two focused units: StringSemanticTokensSupplier (447 lines) for routing
and query/special-context handling, and LambdaStringTokenizer (612 lines)
for lambda detection and tokenization.

Also removes all @SuppressWarnings("java:S*") annotations from source
and test files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d StringSemanticTokensSupplier

LambdaStringTokenizer:
- S1213: move static method createParamTokenTypeMap() after constructor
- S2384: store defensive copy of allSuppliers via List.copyOf()
- S1151/S134/S6916: extract addToMultilineGroup() from switch case
- S864: add parentheses for operator precedence in ternary
- S6212: use var for contentOffset

StringSemanticTokensSupplier:
- S1200: remove cached ParsedStrTemplateMethods field and event listener,
  read configuration inline to reduce class dependencies from 21 to 18

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Mar 27, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants