Repository navigation
feat(ide): директивы компиляции и ключевые слова объявления различимы в семантической подсветке - #429
Open
flamber-dev wants to merge 1 commit into
Conversation
… own semantic tokens Compilation directives (&AtClient, &AtServer, ...) were emitted as `decorator`, the same type as extension annotations (&Before, &After, &Around, &ChangeAndValidate), and declaration keywords (Procedure, Function, EndProcedure, EndFunction, Var, Val, Export, Async) were plain `keyword` like control-flow keywords, so a theme could not tell them apart. Directives now map to the standard LSP token type `modifier` (appended to the legend at index 16; existing indices unchanged), and declaration keywords keep the `keyword` type but carry the standard `declaration` modifier, so clients that ignore modifiers see no change. The kind classification lives in `SyntaxKind::is_compilation_directive` / `is_declaration_keyword`. Token-stream snapshots change only in those two classifications; offsets and token texts are identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Проблема
Семантическая подсветка отдаёт клиенту один и тот же тип токена для разных по смыслу конструкций, поэтому тема не может
раскрасить их по-разному:
директива компиляции (
&НаКлиенте,&НаСервере,&НаСервереБезКонтекста, …) и аннотация расширения(
&Перед("..."),&После("..."),&Вместо("..."),&ИзменениеИКонтроль("...")) - обеdecorator. Директивазадаёт контекст исполнения метода, аннотация расширения - перехват чужого метода; на методе расширения они стоят
рядом и сливаются:
ключевые слова объявления (
Процедура,Функция,КонецПроцедуры,КонецФункции,Перем,Знач,Экспорт,Асинх) и управляющие (Если,Цикл,Возврат, …) - всеkeywordбез модификаторов. Привычная по Конфигураторуи по TextMate-грамматикам схема, где объявления окрашены иначе, чем управление, в семантической подсветке
недостижима: семантический токен перекрывает цвет грамматики.
Инструкции препроцессора (
#Если,#Область, …) уже отдаются какmacroи в этом PR не меняются.Что меняется
develop&НаКлиенте,&НаСервере,&НаСервереБезКонтекста,&НаКлиентеНаСервере,&НаКлиентеНаСервереБезКонтекста(и&AtClient, …)decoratormodifier&Перед,&После,&Вместо,&ИзменениеИКонтроль(и&Before, …), пользовательские аннотацииdecoratordecoratorПроцедура,Функция,КонецПроцедуры,КонецФункции,Перем,Знач,Экспорт,Асинх(иProcedure, …)keywordkeyword+ модификаторdeclarationЕсли,Тогда,Цикл,Возврат,Новый,Ждать, …keywordkeyword#Если,#КонецЕсли,#Область,#КонецОбласти,#Вставка, …macromacro#Область Имя)Оба новых признака - стандартные имена LSP 3.17 (
SemanticTokenTypes.modifier,SemanticTokenModifiers.declaration), собственных типов не добавлено. Поэтому клиент не требует настройки:modifier: VS Code сопоставляет этот тип TextMate-областиstorage.modifier, и любая тема, раскрашивающаяstorage.modifier, раскрашивает директиву без доработок; раньше директива получала цветdecorator(
entity.name.decorator, а в темах без него - цвет функции). Аннотации расширений остаютсяdecorator, так что наметоде расширения две строки теперь различимы в штатной теме.
keyword+declaration: тип прежний, поэтому в штатных темах ключевые слова выглядят как раньше; клиенты,не читающие модификаторы, видят ровно то же, что на
develop. Отличить объявления можно правилом пользователяили темы, например в VS Code:
Отдельный тип (
storageи т.п.) здесь сознательно не вводится: нестандартный тип клиент безsemanticTokenScopesне знает и оставляет такой токен без семантического цвета, то есть объявления в штатной теме потеряли бы цвет
ключевого слова и остались бы на цвете TextMate-грамматики, если она вообще подключена.
Легенда
semantic_tokens_legend(): вtoken_typesдобавлен в конецmodifier(индекс 16); прежние индексы 0-15 несдвинулись. Модификатор
declarationв легенде уже был (бит 3) - сейчас им помечаются объявления переменных ипараметров, теперь и ключевые слова объявления. Клиент получает легенду при инициализации, так что совместимость
обратная: старый клиент с новой легендой работает, ничего не переназначено.
Код
crates/syntax/src/syntax_kind.rs:SyntaxKind::is_compilation_directive()(подмножествоis_annotation) иSyntaxKind::is_declaration_keyword()(подмножествоis_keyword) - классификация видов лексем живёт рядом сis_keyword/is_annotation/is_preprocessor.crates/ide/src/syntax_highlighting.rs: новыйHlTag::CompilerDirective(as_str() == "modifier");highlight_tokenпроверяет директиву раньше общей ветки аннотаций и ставитHlMod::DECLARATIONключевым словамобъявления.
crates/bsl-analyzer/src/lsp/to_proto.rs:SemanticTokenType::MODIFIERв легенде,HlTag::CompilerDirective => 16.crates/ide/src/syntax_highlighting/token_stream_tests.rs: снапшоты обновлены (см. ниже).Доказательство
Два новых интеграционных файла, чтобы их можно было прогнать на
developбез правки (они сравнивают строки типа имодификаторов, которые видит тема, а не варианты
HlTag, поэтому компилируются и наdevelop):crates/ide/tests/highlight_directives_and_declarations.rs(уровеньide::highlight):compilation_directives_are_modifiers_not_decorators- пять директив, русское написание →modifier;compilation_directives_english_are_modifiers- те же пять, английское написание;extension_annotations_stay_decorators-&Перед/&После/&Вместо/&ИзменениеИКонтрольи&Before/&After/&Around/&ChangeAndValidateостаютсяdecorator(контроль);directive_and_annotation_on_one_method_get_different_types-&НаСервере+&После("...")на одном методе;preprocessor_instructions_stay_macros_and_region_names_stay_untagged-#Если/#КонецЕсли/#Область/#КонецОбластии английские формы остаются
macro, а имя области, совпадающее с именем процедуры, по-прежнему без токена(контроль: регресс fix(ide): имя в директиве #Область не подсвечивается как вызов метода #318 не допущен);
declaration_keywords_carry_the_declaration_modifier-Перем,Экспорт,Асинх,Процедура,Знач,КонецПроцедуры,Функция,КонецФункции-keyword+declaration;Если,Тогда,Возврат,КонецЕсли,Пока,Цикл,КонецЦикла,Новый,Ждать-keywordбез него;declaration_keywords_english_carry_the_declaration_modifier- то же для английских слов.crates/bsl-analyzer/tests/semantic_tokens_directives_and_declarations.rs(уровень LSP: токены кодируютсяsemantic_tokensи декодируются черезsemantic_tokens_legend()так, как это делает клиент):legend_advertises_the_modifier_token_type- в легенде есть типmodifierи модификаторdeclaration;client_decodes_directives_annotations_and_declaration_keywords-&НаСервере→modifier,&После→decorator,Процедура/Знач/Экспорт/КонецПроцедуры→keyword+declaration,Если/Тогда/Возврат/КонецЕсли→keywordбез него.На
develop(4467ba9), только тесты:На ветке:
Изменённые снапшоты
token_stream_tests.rsзакрепляет класс каждого токена, поэтому в нём меняются ровно две вещи - ключевые словаобъявления получили
[DECLARATION],&НаСервересталCompilerDirective. Диапазоны и тексты токенов не сдвинулись нив одной строке. Два из четырёх тестов файла помечены
corpus_contract; их снапшоты обновлены и проверены прогоном с--cfg corpus_contractна закреплённом корпусе (SHA-2563c759994…cacce):Полные прогоны
cargo test -p ide -p syntax --no-fail-fastиcargo test -p bsl-analyzer --no-fail-fastнаdevelopи на ветке (Windows): списки упавшихсовпадают, кроме новых тестов, которые на
developпадают, а на ветке проходят.Упавшие на обеих сторонах одинаково (фон Windows и тесты отмены по времени, к подсветке отношения не имеют):
-p ide/-p syntax: 9 тестов -graph::tests::method_graph_id_file_fallback_normalization,graph::tests::method_graph_id_matches_encoder_and_round_trips_for_path_fallback,name_lookup::tests::the_address_phases_observe_a_cancelled_requestи 6 тестовinfer_three_level(
a_self_qualified_call_*,manager_typed_local_is_not_reported_as_self_qualified_access,self_qualified_call_in_{constant,report}_manager_still_checks_the_method). Наdevelopк ним добавляются 5 новыхтестов из
highlight_directives_and_declarations.-p bsl-analyzer: 45 общих тестов на обеих сторонах (CLI, журнал и базовые линии на путях Windows,bench::*,mcp_install::*,server::tests::g1_*). Наdevelopк ним добавляются 2 новых тестаsemantic_tokens_directives_and_declarations. Ещё два теста live-VFS(
g1_live_vfs_pending_write_cancels_real_definition_then_fresh_request_succeeds,g1_propagated_without_new_revision_is_refused_controller_control) в одном полном прогоне упали только на ветке. Этотесты отмены по времени: при трёх повторах
cargo test -p bsl-analyzer --lib g1_на каждой стороне набор упавшихg1_*меняется от прогона к прогону, иg1_propagated_without_new_revision_is_refused_controller_controlпадает и наdevelop(второй повтор).cargo fmt --all -- --check- чисто.cargo clippy -p syntax -p ide -p bsl-analyzer --all-targets(без-D warnings:под Windows он останавливается на чужих предупреждениях) - набор предупреждений совпадает с
develop(на обеих сторонах только 2 предупреждения вmcp-server, в затронутых крейтах - ни одного).Вне рамок
#Областьпротив#Если) - они ужеmacro, а имяобласти намеренно остаётся без токена (fix(ide): имя в директиве #Область не подсвечивается как вызов метода #318).
controlFlowу rust-analyzer) - нестандартное имя, и для задачи«отделить объявления» достаточно одного стандартного модификатора.
Асинхпо-прежнему без модификатораasync;Новый,Выполнить,ДобавитьОбработчик/УдалитьОбработчикилитералы
Истина/Ложь/Неопределено/NULLостаются обычнымиkeyword.semanticTokenScopes) - в этом репозитории клиента VS Code нет, астандартные имена в нём и не нуждаются.