[analyzer] Add a "constructor" modifier for LSP semantic tokens
Fixes https://github.com/dart-lang/sdk/issues/45861.
Change-Id: Ib97e14d6e23dfd0c48e1ad8abb18b42a4c2f9cb1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197401
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 4afc13e..7f10b84 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -104,9 +104,13 @@
/// - parameter
static const label = SemanticTokenModifiers('label');
+ /// A modifier applied to constructors to allow colouring them differently
+ /// to class names that are not constructors.
+ static const constructor = SemanticTokenModifiers('constructor');
+
/// All custom semantic token modifiers, used to populate the LSP Legend which must
/// include all used modifiers.
- static const values = [control, label];
+ static const values = [control, label, constructor];
}
abstract class CustomSemanticTokenTypes {
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
index 66e4b26..c83e229 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -15,6 +15,7 @@
HighlightRegionType.COMMENT_DOCUMENTATION: {
SemanticTokenModifiers.documentation
},
+ HighlightRegionType.CONSTRUCTOR: {CustomSemanticTokenModifiers.constructor},
HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION: {
SemanticTokenModifiers.declaration
},
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
index 6fcc641..20d0bfc 100644
--- a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -82,6 +82,46 @@
expect(decoded, equals(expected));
}
+ Future<void> test_class_constructors() async {
+ final content = '''
+ class MyClass {
+ MyClass();
+ MyClass.named();
+ }
+
+ final a = MyClass();
+ final b = MyClass.named();
+ ''';
+
+ final expected = [
+ _Token('class', SemanticTokenTypes.keyword),
+ _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('named', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('a', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('MyClass', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('b', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('MyClass', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
+ _Token('named', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor])
+ ];
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final tokens = await getSemanticTokens(mainFileUri);
+ final decoded = decodeSemanticTokens(content, tokens);
+ expect(decoded, equals(expected));
+ }
+
Future<void> test_class_fields() async {
final content = '''
class MyClass {
@@ -119,7 +159,8 @@
_Token('final', SemanticTokenTypes.keyword),
_Token('a', SemanticTokenTypes.variable,
[SemanticTokenModifiers.declaration]),
- _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('MyClass', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
_Token('print', SemanticTokenTypes.function),
_Token('a', SemanticTokenTypes.variable),
_Token('myField', SemanticTokenTypes.property),
@@ -197,7 +238,8 @@
_Token('final', SemanticTokenTypes.keyword),
_Token('a', SemanticTokenTypes.variable,
[SemanticTokenModifiers.declaration]),
- _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('MyClass', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
_Token('print', SemanticTokenTypes.function),
_Token('a', SemanticTokenTypes.variable),
_Token('myGetter', SemanticTokenTypes.property),
@@ -255,7 +297,8 @@
_Token('final', SemanticTokenTypes.keyword),
_Token('a', SemanticTokenTypes.variable,
[SemanticTokenModifiers.declaration]),
- _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('MyClass', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
_Token('a', SemanticTokenTypes.variable),
_Token('myMethod', SemanticTokenTypes.method),
_Token('MyClass', SemanticTokenTypes.class_),
@@ -443,7 +486,8 @@
_Token('a', SemanticTokenTypes.variable,
[SemanticTokenModifiers.declaration]),
_Token('new', SemanticTokenTypes.keyword),
- _Token('Object', SemanticTokenTypes.class_),
+ _Token('Object', SemanticTokenTypes.class_,
+ [CustomSemanticTokenModifiers.constructor]),
_Token('await', SemanticTokenTypes.keyword,
[CustomSemanticTokenModifiers.control]),
_Token('null', SemanticTokenTypes.keyword),