Skip to content

Commit 922cdf4

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Add "label" mapping for semantic tokens
Fixes Dart-Code/Dart-Code#5505 Change-Id: Iad8b405442c841b215d3697d87b0203bd06c0ef2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/428360 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent e9abc78 commit 922cdf4

File tree

5 files changed

+77
-10
lines changed

5 files changed

+77
-10
lines changed

pkg/analysis_server/lib/src/computer/computer_highlights.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ class DartUnitHighlightsComputer {
132132
if (_addIdentifierRegion_importPrefix(nameToken, element)) {
133133
return;
134134
}
135-
if (_addIdentifierRegion_label(nameToken, element)) {
135+
if (_addIdentifierRegion_label(parent, nameToken, element)) {
136136
return;
137137
}
138138
if (_addIdentifierRegion_localVariable(nameToken, element)) {
@@ -395,11 +395,22 @@ class DartUnitHighlightsComputer {
395395
return false;
396396
}
397397

398-
bool _addIdentifierRegion_label(Token nameToken, Element? element) {
398+
bool _addIdentifierRegion_label(
399+
AstNode parent,
400+
Token nameToken,
401+
Element? element,
402+
) {
399403
if (element is! LabelElement) {
400404
return false;
401405
}
402-
return _addRegion_token(nameToken, HighlightRegionType.LABEL);
406+
return _addRegion_token(
407+
nameToken,
408+
HighlightRegionType.LABEL,
409+
semanticTokenModifiers:
410+
parent is! BreakStatement
411+
? {SemanticTokenModifiers.declaration}
412+
: null,
413+
);
403414
}
404415

405416
bool _addIdentifierRegion_localVariable(Token nameToken, Element? element) {

pkg/analysis_server/lib/src/lsp/constants.dart

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,13 @@ abstract final class CustomSemanticTokenModifiers {
206206
static const importPrefix = SemanticTokenModifiers('importPrefix');
207207

208208
/// A modifier applied to parameter references to indicate they are the name/label
209-
/// to allow theming them differently to the values. For example in the code
210-
/// `foo({String a}) => foo(a: a)` the a's will be differentiated as:
209+
/// to allow theming them differently to the values.
210+
///
211+
/// This is different to [CustomSemanticTokenTypes.label] which is for labels
212+
/// as used in loops/switch statements.
213+
///
214+
/// In the code `foo({String a}) => foo(a: a)` the a's will be differentiated
215+
/// as:
211216
/// - parameter.declaration
212217
/// - parameter.label
213218
/// - parameter
@@ -268,6 +273,22 @@ abstract final class CustomSemanticTokenTypes {
268273
static const annotation = SemanticTokenTypes('annotation');
269274
static const boolean = SemanticTokenTypes('boolean');
270275

276+
/// A token type for labels.
277+
///
278+
/// This is different to [CustomSemanticTokenModifiers.label] which is for
279+
/// parameter name labels.
280+
///
281+
/// 'label' is listed as a standard VS Code token type at
282+
/// https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide
283+
/// and therefore may be used by theme authors, but it's currently not defined
284+
/// by LSP (and therefore missing from the code-generated SemanticTokenTypes)
285+
/// so we have to define it here.
286+
///
287+
/// This can be removed once
288+
/// https://github.com/microsoft/language-server-protocol/issues/2137 is
289+
/// resolved.
290+
static const label = SemanticTokenTypes('label');
291+
271292
/// A placeholder token type for basic source code that is not usually colored.
272293
///
273294
/// This is used only where clients might otherwise provide their own coloring
@@ -280,7 +301,7 @@ abstract final class CustomSemanticTokenTypes {
280301

281302
/// All custom semantic token types, used to populate the LSP Legend which must
282303
/// include all used types.
283-
static const values = [annotation, boolean, source];
304+
static const values = [annotation, boolean, label, source];
284305
}
285306

286307
/// CodeActionKinds supported by the server that are not declared in the LSP spec.

pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ final highlightRegionTokenTypes = {
140140
HighlightRegionType.INSTANCE_SETTER_DECLARATION: SemanticTokenTypes.property,
141141
HighlightRegionType.INSTANCE_SETTER_REFERENCE: SemanticTokenTypes.property,
142142
HighlightRegionType.KEYWORD: SemanticTokenTypes.keyword,
143+
HighlightRegionType.LABEL: CustomSemanticTokenTypes.label,
143144
HighlightRegionType.LIBRARY_NAME: SemanticTokenTypes.namespace,
144145
HighlightRegionType.LITERAL_BOOLEAN: CustomSemanticTokenTypes.boolean,
145146
HighlightRegionType.LITERAL_DOUBLE: SemanticTokenTypes.number,

pkg/analysis_server/test/lsp/semantic_tokens_test.dart

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,40 @@ void f() async {
11991199
await _initializeAndVerifyTokens(content, expected);
12001200
}
12011201

1202+
Future<void> test_label() async {
1203+
var content = '''
1204+
void f() {
1205+
myLabel:
1206+
while (true) {
1207+
break myLabel;
1208+
}
1209+
}
1210+
''';
1211+
1212+
var expected = [
1213+
_Token('void', SemanticTokenTypes.keyword, [
1214+
CustomSemanticTokenModifiers.void_,
1215+
]),
1216+
_Token('f', SemanticTokenTypes.function, [
1217+
SemanticTokenModifiers.declaration,
1218+
SemanticTokenModifiers.static,
1219+
]),
1220+
_Token('myLabel', CustomSemanticTokenTypes.label, [
1221+
SemanticTokenModifiers.declaration,
1222+
]),
1223+
_Token('while', SemanticTokenTypes.keyword, [
1224+
CustomSemanticTokenModifiers.control,
1225+
]),
1226+
_Token('true', CustomSemanticTokenTypes.boolean),
1227+
_Token('break', SemanticTokenTypes.keyword, [
1228+
CustomSemanticTokenModifiers.control,
1229+
]),
1230+
_Token('myLabel', CustomSemanticTokenTypes.label),
1231+
];
1232+
1233+
await _initializeAndVerifyTokens(content, expected);
1234+
}
1235+
12021236
Future<void> test_lastLine_code() async {
12031237
var content = 'String? bar;';
12041238

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5483,8 +5483,8 @@ class LabelElementImpl2 extends ElementImpl2
54835483
return [firstFragment];
54845484
}
54855485

5486-
/// Return `true` if this label is associated with a `switch` member (`case
5487-
/// ` or`default`).
5486+
/// Return `true` if this label is associated with a `switch` member (`case`
5487+
/// or `default`).
54885488
bool get isOnSwitchMember => _wrappedElement.isOnSwitchMember;
54895489

54905490
@override
@@ -5531,8 +5531,8 @@ class LabelFragmentImpl extends FragmentImpl implements LabelFragment {
55315531
ExecutableFragment get enclosingFragment =>
55325532
enclosingElement3 as ExecutableFragment;
55335533

5534-
/// Return `true` if this label is associated with a `switch` member (`case
5535-
/// ` or`default`).
5534+
/// Return `true` if this label is associated with a `switch` member (`case`
5535+
/// or `default`).
55365536
bool get isOnSwitchMember => _onSwitchMember;
55375537

55385538
@override

0 commit comments

Comments
 (0)