Version 2.15.0-101.0.dev
Merge commit '30abce99f3b779d843e9caebd1896099ea515507' into 'dev'
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 4fa2db3..4271825 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -682,11 +682,7 @@
// TODO(scheglov) The `ConstructorName` in a tear-off always has a name,
// but this is not expressed via types.
computer._addRegion_node(
- constructorName.name!,
- HighlightRegionType.CONSTRUCTOR_TEAR_OFF,
- semanticTokenType: SemanticTokenTypes.method,
- semanticTokenModifiers: {CustomSemanticTokenModifiers.constructor},
- );
+ constructorName.name!, HighlightRegionType.CONSTRUCTOR_TEAR_OFF);
}
@override
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 4d44191..1758d41 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -4,17 +4,17 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/src/lsp/constants.dart';
-import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
-final highlightRegionMapper = RegionTypeMapper();
-
/// A mapping from [HighlightRegionType] to a set of [SemanticTokenModifiers].
final highlightRegionTokenModifiers =
<HighlightRegionType, Set<SemanticTokenModifiers>>{
HighlightRegionType.COMMENT_DOCUMENTATION: {
SemanticTokenModifiers.documentation
},
+ HighlightRegionType.CONSTRUCTOR_TEAR_OFF: {
+ CustomSemanticTokenModifiers.constructor
+ },
HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION: {
SemanticTokenModifiers.declaration
},
@@ -56,6 +56,7 @@
SemanticTokenModifiers.static,
},
HighlightRegionType.STATIC_METHOD_REFERENCE: {SemanticTokenModifiers.static},
+ HighlightRegionType.STATIC_METHOD_TEAR_OFF: {SemanticTokenModifiers.static},
HighlightRegionType.STATIC_SETTER_DECLARATION: {
SemanticTokenModifiers.declaration,
SemanticTokenModifiers.static,
@@ -87,6 +88,7 @@
HighlightRegionType.COMMENT_BLOCK: SemanticTokenTypes.comment,
HighlightRegionType.COMMENT_DOCUMENTATION: SemanticTokenTypes.comment,
HighlightRegionType.COMMENT_END_OF_LINE: SemanticTokenTypes.comment,
+ HighlightRegionType.CONSTRUCTOR_TEAR_OFF: SemanticTokenTypes.method,
HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION:
SemanticTokenTypes.variable,
HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_REFERENCE:
@@ -104,6 +106,7 @@
HighlightRegionType.INSTANCE_GETTER_REFERENCE: SemanticTokenTypes.property,
HighlightRegionType.INSTANCE_METHOD_DECLARATION: SemanticTokenTypes.method,
HighlightRegionType.INSTANCE_METHOD_REFERENCE: SemanticTokenTypes.method,
+ HighlightRegionType.INSTANCE_METHOD_TEAR_OFF: SemanticTokenTypes.method,
HighlightRegionType.INSTANCE_SETTER_DECLARATION: SemanticTokenTypes.property,
HighlightRegionType.INSTANCE_SETTER_REFERENCE: SemanticTokenTypes.property,
HighlightRegionType.KEYWORD: SemanticTokenTypes.keyword,
@@ -114,6 +117,7 @@
HighlightRegionType.LITERAL_STRING: SemanticTokenTypes.string,
HighlightRegionType.LOCAL_FUNCTION_DECLARATION: SemanticTokenTypes.function,
HighlightRegionType.LOCAL_FUNCTION_REFERENCE: SemanticTokenTypes.function,
+ HighlightRegionType.LOCAL_FUNCTION_TEAR_OFF: SemanticTokenTypes.function,
HighlightRegionType.LOCAL_VARIABLE_DECLARATION: SemanticTokenTypes.variable,
HighlightRegionType.LOCAL_VARIABLE_REFERENCE: SemanticTokenTypes.variable,
HighlightRegionType.PARAMETER_DECLARATION: SemanticTokenTypes.parameter,
@@ -123,11 +127,13 @@
HighlightRegionType.STATIC_GETTER_REFERENCE: SemanticTokenTypes.property,
HighlightRegionType.STATIC_METHOD_DECLARATION: SemanticTokenTypes.method,
HighlightRegionType.STATIC_METHOD_REFERENCE: SemanticTokenTypes.method,
+ HighlightRegionType.STATIC_METHOD_TEAR_OFF: SemanticTokenTypes.method,
HighlightRegionType.STATIC_SETTER_DECLARATION: SemanticTokenTypes.property,
HighlightRegionType.STATIC_SETTER_REFERENCE: SemanticTokenTypes.property,
HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION:
SemanticTokenTypes.function,
HighlightRegionType.TOP_LEVEL_FUNCTION_REFERENCE: SemanticTokenTypes.function,
+ HighlightRegionType.TOP_LEVEL_FUNCTION_TEAR_OFF: SemanticTokenTypes.function,
HighlightRegionType.TOP_LEVEL_GETTER_DECLARATION: SemanticTokenTypes.property,
HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE: SemanticTokenTypes.property,
HighlightRegionType.TOP_LEVEL_SETTER_DECLARATION: SemanticTokenTypes.property,
@@ -142,37 +148,3 @@
CustomSemanticTokenTypes.source,
HighlightRegionType.VALID_STRING_ESCAPE: SemanticTokenTypes.string,
};
-
-/// A helper for converting from Server highlight regions to LSP semantic tokens.
-class RegionTypeMapper {
- /// A map to get the [SemanticTokenTypes] index directly from a [HighlightRegionType].
- final Map<HighlightRegionType, int> _tokenTypeIndexForHighlightRegion = {};
-
- /// A map to get the [SemanticTokenModifiers] bitmask directly from a [HighlightRegionType].
- final Map<HighlightRegionType, int> _tokenModifierBitmaskForHighlightRegion =
- {};
-
- RegionTypeMapper() {
- // Build mappings that go directly from [HighlightRegionType] to index/bitmask
- // for faster lookups.
- for (final regionType in highlightRegionTokenTypes.keys) {
- _tokenTypeIndexForHighlightRegion[regionType] = semanticTokenLegend
- .indexForType(highlightRegionTokenTypes[regionType]!);
- }
-
- for (final regionType in highlightRegionTokenTypes.keys) {
- _tokenModifierBitmaskForHighlightRegion[regionType] = semanticTokenLegend
- .bitmaskForModifiers(highlightRegionTokenModifiers[regionType]);
- }
- }
-
- /// Gets the [SemanticTokenModifiers] bitmask for a [HighlightRegionType]. Returns
- /// null if the region type has not been mapped.
- int bitmaskForModifier(HighlightRegionType type) =>
- _tokenModifierBitmaskForHighlightRegion[type]!;
-
- /// Gets the [SemanticTokenTypes] index for a [HighlightRegionType]. Returns
- /// null if the region type has not been mapped.
- int indexForToken(HighlightRegionType type) =>
- _tokenTypeIndexForHighlightRegion[type]!;
-}
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
index 1b5d9a5..de5f35a 100644
--- a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -93,6 +93,7 @@
final a = MyClass();
final b = MyClass.named();
final c = MyClass.factory();
+ final d = MyClass.named;
''';
final expected = [
@@ -126,7 +127,13 @@
_Token('MyClass', SemanticTokenTypes.class_,
[CustomSemanticTokenModifiers.constructor]),
_Token('factory', SemanticTokenTypes.method,
- [CustomSemanticTokenModifiers.constructor])
+ [CustomSemanticTokenModifiers.constructor]),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('d', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('named', SemanticTokenTypes.method,
+ [CustomSemanticTokenModifiers.constructor]),
];
await initialize();
@@ -287,6 +294,8 @@
final a = MyClass();
a.myMethod();
MyClass.myStaticMethod();
+ final b = a.myMethod;
+ final c = MyClass.myStaticMethod;
}
''';
@@ -321,6 +330,17 @@
_Token('MyClass', SemanticTokenTypes.class_),
_Token('myStaticMethod', SemanticTokenTypes.method,
[SemanticTokenModifiers.static]),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('b', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('a', SemanticTokenTypes.variable),
+ _Token('myMethod', SemanticTokenTypes.method),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('c', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('MyClass', SemanticTokenTypes.class_),
+ _Token('myStaticMethod', SemanticTokenTypes.method,
+ [SemanticTokenModifiers.static]),
];
await initialize();
@@ -612,6 +632,38 @@
expect(decoded, equals(expected));
}
+ Future<void> test_local() async {
+ final content = '''
+ main() {
+ func(String a) => print(a);
+ final funcTearOff = func;
+ }
+ ''';
+
+ final expected = [
+ _Token('main', SemanticTokenTypes.function,
+ [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+ _Token('func', SemanticTokenTypes.function,
+ [SemanticTokenModifiers.declaration]),
+ _Token('String', SemanticTokenTypes.class_),
+ _Token('a', SemanticTokenTypes.parameter,
+ [SemanticTokenModifiers.declaration]),
+ _Token('print', SemanticTokenTypes.function),
+ _Token('a', SemanticTokenTypes.parameter),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('funcTearOff', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('func', SemanticTokenTypes.function),
+ ];
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final tokens = await getSemanticTokens(mainFileUri);
+ final decoded = decodeSemanticTokens(content, tokens);
+ expect(decoded, equals(expected));
+ }
+
Future<void> test_manyBools_bug() async {
// Similar to test_manyImports_sortBug, this code triggered inconsistent tokens
// for "false" because tokens were sorted incorrectly (because both boolean and
@@ -990,6 +1042,8 @@
/// abc docs
bool get abc => true;
+
+ final funcTearOff = func;
''';
final expected = [
@@ -1019,6 +1073,10 @@
_Token('abc', SemanticTokenTypes.property,
[SemanticTokenModifiers.declaration]),
_Token('true', CustomSemanticTokenTypes.boolean),
+ _Token('final', SemanticTokenTypes.keyword),
+ _Token('funcTearOff', SemanticTokenTypes.variable,
+ [SemanticTokenModifiers.declaration]),
+ _Token('func', SemanticTokenTypes.function),
];
await initialize();
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 4db5773..aabb65f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -387,7 +387,8 @@
);
if (methodElement == null) {
- // TODO(srawlins): Can we get here?
+ // The target is known, but the method is not; [UNDEFINED_GETTER] is
+ // reported elsewhere.
node.staticType = DynamicTypeImpl.instance;
return;
} else {
@@ -395,7 +396,7 @@
return;
}
} else {
- // TODO(srawlins): Can we get here?
+ // The prefix is unknown; [UNDEFINED_IDENTIFIER] is reported elsewhere.
node.staticType = DynamicTypeImpl.instance;
return;
}
@@ -440,7 +441,7 @@
void _resolveReceiverPrefix(
FunctionReferenceImpl node,
PrefixElement prefixElement,
- PrefixedIdentifier prefix,
+ PrefixedIdentifierImpl prefix,
Element element,
) {
if (element is MultiplyDefinedElement) {
@@ -477,10 +478,19 @@
name: element.name,
);
return;
+ } else if (element is ExtensionElement) {
+ prefix.identifier.staticElement = element;
+ prefix.identifier.staticType = DynamicTypeImpl.instance;
+ prefix.staticType = DynamicTypeImpl.instance;
+ _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+ return;
}
- // TODO(srawlins): Report undefined prefixed identifier.
-
+ assert(
+ false,
+ 'Member of prefixed element, $prefixElement, is not a class, mixin, '
+ 'type alias, or executable element: $element (${element.runtimeType})',
+ );
node.staticType = DynamicTypeImpl.instance;
}
@@ -590,6 +600,11 @@
function.staticType = element.type;
_resolve(node: node, rawType: element.type);
return;
+ } else if (element is ExtensionElement) {
+ function.staticElement = element;
+ function.staticType = DynamicTypeImpl.instance;
+ _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+ return;
} else {
_resolveDisallowedExpression(node, DynamicTypeImpl.instance);
return;
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index b0d0ce9..1f36c75 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -19,7 +19,7 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(AssignabilityTest);
+ defineReflectiveTests(AssignabilityWithoutNullSafetyTest);
defineReflectiveTests(TryPromoteToTest);
});
}
@@ -87,7 +87,8 @@
}
@reflectiveTest
-class AssignabilityTest extends AbstractTypeSystemWithoutNullSafetyTest {
+class AssignabilityWithoutNullSafetyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest {
void test_isAssignableTo_bottom_isBottom() {
var A = class_(name: 'A');
List<DartType> interassignable = <DartType>[
@@ -435,7 +436,7 @@
}
@reflectiveTest
-class TryPromoteToTest extends AbstractTypeSystemWithoutNullSafetyTest {
+class TryPromoteToTest extends AbstractTypeSystemTest {
void notPromotes(DartType from, DartType to) {
var result = typeSystem.tryPromoteToType(to, from);
expect(result, isNull);
diff --git a/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
index cf35b13..a6ab0bc 100644
--- a/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
+++ b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
@@ -15,38 +15,13 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ClassHierarchyLegacyTest);
- defineReflectiveTests(ClassHierarchyNullSafetyTest);
+ defineReflectiveTests(ClassHierarchyTest);
+ defineReflectiveTests(ClassHierarchyWithoutNullSafetyTest);
});
}
@reflectiveTest
-class ClassHierarchyLegacyTest extends AbstractTypeSystemWithoutNullSafetyTest
- with _AbstractClassHierarchyMixin {
- @override
- void setUp() {
- super.setUp();
- _createSharedElements();
- }
-
- test_invalid() {
- _checkA(
- typeArguments: [intNone, doubleNone],
- interfaces: ['A<int*>'],
- errors: ['A<int*> vs. A<double*>'],
- );
- }
-
- test_valid() {
- _checkA(
- typeArguments: [intNone, intQuestion],
- interfaces: ['A<int*>'],
- );
- }
-}
-
-@reflectiveTest
-class ClassHierarchyNullSafetyTest extends AbstractTypeSystemTest
+class ClassHierarchyTest extends AbstractTypeSystemTest
with _AbstractClassHierarchyMixin {
@override
void setUp() {
@@ -84,6 +59,32 @@
}
}
+@reflectiveTest
+class ClassHierarchyWithoutNullSafetyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest
+ with _AbstractClassHierarchyMixin {
+ @override
+ void setUp() {
+ super.setUp();
+ _createSharedElements();
+ }
+
+ test_invalid() {
+ _checkA(
+ typeArguments: [intNone, doubleNone],
+ interfaces: ['A<int*>'],
+ errors: ['A<int*> vs. A<double*>'],
+ );
+ }
+
+ test_valid() {
+ _checkA(
+ typeArguments: [intNone, intQuestion],
+ interfaces: ['A<int*>'],
+ );
+ }
+}
+
mixin _AbstractClassHierarchyMixin on ElementsTypesMixin {
late ClassElementImpl A;
diff --git a/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
index 9c1f2df..1e0d20f 100644
--- a/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
@@ -11,138 +11,13 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(GreatestClosureLegacyTest);
- defineReflectiveTests(GreatestClosureNullSafetyTest);
+ defineReflectiveTests(GreatestClosureTest);
+ defineReflectiveTests(GreatestClosureWithoutNullSafetyTest);
});
}
@reflectiveTest
-class GreatestClosureLegacyTest
- extends AbstractTypeSystemWithoutNullSafetyTest {
- late final TypeParameterElement T;
- late final TypeParameterType T_none;
- late final TypeParameterType T_question;
- late final TypeParameterType T_star;
-
- @override
- void setUp() {
- super.setUp();
-
- T = typeParameter('T');
- T_none = typeParameterTypeNone(T);
- T_question = typeParameterTypeQuestion(T);
- T_star = typeParameterTypeStar(T);
- }
-
- test_contravariant() {
- _check(
- functionTypeStar(returnType: voidNone, parameters: [
- requiredParameter(type: T_star),
- ]),
- greatest: 'void Function(Null*)*',
- least: 'void Function(dynamic)*',
- );
-
- _check(
- functionTypeStar(
- returnType: functionTypeStar(
- returnType: voidNone,
- parameters: [
- requiredParameter(type: T_star),
- ],
- ),
- ),
- greatest: 'void Function(Null*)* Function()*',
- least: 'void Function(dynamic)* Function()*',
- );
- }
-
- test_covariant() {
- _check(T_star, greatest: 'dynamic', least: 'Null*');
-
- _check(
- listStar(T_star),
- greatest: 'List<dynamic>*',
- least: 'List<Null*>*',
- );
-
- _check(
- functionTypeStar(returnType: voidNone, parameters: [
- requiredParameter(
- type: functionTypeStar(returnType: intStar, parameters: [
- requiredParameter(type: T_star),
- ]),
- ),
- ]),
- greatest: 'void Function(int* Function(dynamic)*)*',
- least: 'void Function(int* Function(Null*)*)*',
- );
- }
-
- test_function() {
- // void Function<U extends T>()
- _check(
- functionTypeStar(
- typeFormals: [
- typeParameter('U', bound: T_star),
- ],
- returnType: voidNone,
- ),
- greatest: 'Function*',
- least: 'Null*',
- );
- }
-
- test_unrelated() {
- _check1(intStar, 'int*');
- _check1(listStar(intStar), 'List<int*>*');
-
- _check1(objectStar, 'Object*');
- _check1(neverStar, 'Never*');
- _check1(nullStar, 'Null*');
-
- _check1(dynamicNone, 'dynamic');
-
- _check1(
- functionTypeStar(returnType: stringStar, parameters: [
- requiredParameter(type: intStar),
- ]),
- 'String* Function(int*)*',
- );
-
- _check1(
- typeParameterTypeStar(
- typeParameter('U'),
- ),
- 'U*',
- );
- }
-
- void _check(
- DartType type, {
- required String greatest,
- required String least,
- }) {
- var greatestResult = typeSystem.greatestClosure(type, [T]);
- expect(
- greatestResult.getDisplayString(withNullability: true),
- greatest,
- );
-
- var leastResult = typeSystem.leastClosure(type, [T]);
- expect(
- leastResult.getDisplayString(withNullability: true),
- least,
- );
- }
-
- void _check1(DartType type, String expected) {
- _check(type, greatest: expected, least: expected);
- }
-}
-
-@reflectiveTest
-class GreatestClosureNullSafetyTest extends AbstractTypeSystemTest {
+class GreatestClosureTest extends AbstractTypeSystemTest {
late final TypeParameterElement T;
late final TypeParameterType T_none;
late final TypeParameterType T_question;
@@ -273,3 +148,128 @@
_check(type, greatest: expected, least: expected);
}
}
+
+@reflectiveTest
+class GreatestClosureWithoutNullSafetyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest {
+ late final TypeParameterElement T;
+ late final TypeParameterType T_none;
+ late final TypeParameterType T_question;
+ late final TypeParameterType T_star;
+
+ @override
+ void setUp() {
+ super.setUp();
+
+ T = typeParameter('T');
+ T_none = typeParameterTypeNone(T);
+ T_question = typeParameterTypeQuestion(T);
+ T_star = typeParameterTypeStar(T);
+ }
+
+ test_contravariant() {
+ _check(
+ functionTypeStar(returnType: voidNone, parameters: [
+ requiredParameter(type: T_star),
+ ]),
+ greatest: 'void Function(Null*)*',
+ least: 'void Function(dynamic)*',
+ );
+
+ _check(
+ functionTypeStar(
+ returnType: functionTypeStar(
+ returnType: voidNone,
+ parameters: [
+ requiredParameter(type: T_star),
+ ],
+ ),
+ ),
+ greatest: 'void Function(Null*)* Function()*',
+ least: 'void Function(dynamic)* Function()*',
+ );
+ }
+
+ test_covariant() {
+ _check(T_star, greatest: 'dynamic', least: 'Null*');
+
+ _check(
+ listStar(T_star),
+ greatest: 'List<dynamic>*',
+ least: 'List<Null*>*',
+ );
+
+ _check(
+ functionTypeStar(returnType: voidNone, parameters: [
+ requiredParameter(
+ type: functionTypeStar(returnType: intStar, parameters: [
+ requiredParameter(type: T_star),
+ ]),
+ ),
+ ]),
+ greatest: 'void Function(int* Function(dynamic)*)*',
+ least: 'void Function(int* Function(Null*)*)*',
+ );
+ }
+
+ test_function() {
+ // void Function<U extends T>()
+ _check(
+ functionTypeStar(
+ typeFormals: [
+ typeParameter('U', bound: T_star),
+ ],
+ returnType: voidNone,
+ ),
+ greatest: 'Function*',
+ least: 'Null*',
+ );
+ }
+
+ test_unrelated() {
+ _check1(intStar, 'int*');
+ _check1(listStar(intStar), 'List<int*>*');
+
+ _check1(objectStar, 'Object*');
+ _check1(neverStar, 'Never*');
+ _check1(nullStar, 'Null*');
+
+ _check1(dynamicNone, 'dynamic');
+
+ _check1(
+ functionTypeStar(returnType: stringStar, parameters: [
+ requiredParameter(type: intStar),
+ ]),
+ 'String* Function(int*)*',
+ );
+
+ _check1(
+ typeParameterTypeStar(
+ typeParameter('U'),
+ ),
+ 'U*',
+ );
+ }
+
+ void _check(
+ DartType type, {
+ required String greatest,
+ required String least,
+ }) {
+ var greatestResult = typeSystem.greatestClosure(type, [T]);
+ expect(
+ greatestResult.getDisplayString(withNullability: true),
+ greatest,
+ );
+
+ var leastResult = typeSystem.leastClosure(type, [T]);
+ expect(
+ leastResult.getDisplayString(withNullability: true),
+ least,
+ );
+ }
+
+ void _check1(DartType type, String expected) {
+ _check(type, greatest: expected, least: expected);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index 83fc399..c5e85ce 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -21,7 +21,7 @@
}
@reflectiveTest
-class PathToObjectTest extends AbstractTypeSystemWithoutNullSafetyTest {
+class PathToObjectTest extends AbstractTypeSystemTest {
@override
final TestTypeProvider typeProvider = TestTypeProvider();
@@ -351,7 +351,7 @@
}
@reflectiveTest
-class SuperinterfaceSetTest extends AbstractTypeSystemWithoutNullSafetyTest {
+class SuperinterfaceSetTest extends AbstractTypeSystemTest {
@override
final TestTypeProvider typeProvider = TestTypeProvider();
diff --git a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
index ffdc9cc..af99f15 100644
--- a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
+++ b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
@@ -12,73 +12,13 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ReplaceTopBottomLegacyTest);
- defineReflectiveTests(ReplaceTopBottomNullSafetyTest);
+ defineReflectiveTests(ReplaceTopBottomTest);
+ defineReflectiveTests(ReplaceTopBottomWithoutNullSafetyTest);
});
}
@reflectiveTest
-class ReplaceTopBottomLegacyTest
- extends AbstractTypeSystemWithoutNullSafetyTest {
- test_contravariant_bottom() {
- // Not contravariant.
- _check(nullStar, 'Null*');
-
- _check(
- functionTypeStar(returnType: intStar, parameters: [
- requiredParameter(type: nullStar),
- ]),
- 'int* Function(dynamic)*',
- );
- }
-
- test_covariant_top() {
- _check(objectStar, 'Null*');
- _check(dynamicNone, 'Null*');
- _check(voidNone, 'Null*');
-
- _check(listStar(objectStar), 'List<Null*>*');
- _check(listStar(dynamicNone), 'List<Null*>*');
- _check(listStar(voidNone), 'List<Null*>*');
-
- _check(futureOrStar(objectStar), 'Null*');
- _check(futureOrStar(dynamicNone), 'Null*');
- _check(futureOrStar(voidNone), 'Null*');
- _check(futureOrStar(futureOrStar(voidNone)), 'Null*');
-
- _check(
- functionTypeStar(returnType: intStar, parameters: [
- requiredParameter(
- type: functionTypeStar(returnType: intStar, parameters: [
- requiredParameter(type: objectStar),
- ]),
- ),
- ]),
- 'int* Function(int* Function(Null*)*)*',
- typeStr: 'int* Function(int* Function(Object*)*)*',
- );
-
- _check(intStar, 'int*');
- _check(listStar(intStar), 'List<int*>*');
- }
-
- void _check(DartType type, String expectedStr, {String? typeStr}) {
- if (typeStr != null) {
- expect(_typeString(type), typeStr);
- }
-
- var result = typeSystem.replaceTopAndBottom(type);
- var resultStr = _typeString(result);
- expect(resultStr, expectedStr);
- }
-
- String _typeString(DartType type) {
- return type.getDisplayString(withNullability: true);
- }
-}
-
-@reflectiveTest
-class ReplaceTopBottomNullSafetyTest extends AbstractTypeSystemTest {
+class ReplaceTopBottomTest extends AbstractTypeSystemTest {
test_contravariant_bottom() {
// Not contravariant.
_check(neverNone, 'Never');
@@ -174,3 +114,63 @@
return type.getDisplayString(withNullability: true);
}
}
+
+@reflectiveTest
+class ReplaceTopBottomWithoutNullSafetyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest {
+ test_contravariant_bottom() {
+ // Not contravariant.
+ _check(nullStar, 'Null*');
+
+ _check(
+ functionTypeStar(returnType: intStar, parameters: [
+ requiredParameter(type: nullStar),
+ ]),
+ 'int* Function(dynamic)*',
+ );
+ }
+
+ test_covariant_top() {
+ _check(objectStar, 'Null*');
+ _check(dynamicNone, 'Null*');
+ _check(voidNone, 'Null*');
+
+ _check(listStar(objectStar), 'List<Null*>*');
+ _check(listStar(dynamicNone), 'List<Null*>*');
+ _check(listStar(voidNone), 'List<Null*>*');
+
+ _check(futureOrStar(objectStar), 'Null*');
+ _check(futureOrStar(dynamicNone), 'Null*');
+ _check(futureOrStar(voidNone), 'Null*');
+ _check(futureOrStar(futureOrStar(voidNone)), 'Null*');
+
+ _check(
+ functionTypeStar(returnType: intStar, parameters: [
+ requiredParameter(
+ type: functionTypeStar(returnType: intStar, parameters: [
+ requiredParameter(type: objectStar),
+ ]),
+ ),
+ ]),
+ 'int* Function(int* Function(Null*)*)*',
+ typeStr: 'int* Function(int* Function(Object*)*)*',
+ );
+
+ _check(intStar, 'int*');
+ _check(listStar(intStar), 'List<int*>*');
+ }
+
+ void _check(DartType type, String expectedStr, {String? typeStr}) {
+ if (typeStr != null) {
+ expect(_typeString(type), typeStr);
+ }
+
+ var result = typeSystem.replaceTopAndBottom(type);
+ var resultStr = _typeString(result);
+ expect(resultStr, expectedStr);
+ }
+
+ String _typeString(DartType type) {
+ return type.getDisplayString(withNullability: true);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index f695287..aa9f1fe 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -109,6 +109,50 @@
findNode.functionReference('foo<int>;'), null, 'dynamic');
}
+ test_extension() async {
+ await assertErrorsInCode('''
+extension E<T> on String {}
+
+void foo() {
+ E<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 44, 1),
+ ]);
+
+ var reference = findNode.functionReference('E<int>;');
+ assertFunctionReference(
+ reference,
+ findElement.extension_('E'),
+ 'dynamic',
+ );
+ }
+
+ test_extension_prefixed() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+extension E<T> on String {}
+''');
+ await assertErrorsInCode('''
+import 'a.dart' as a;
+
+void foo() {
+ a.E<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 38, 3),
+ ]);
+
+ assertImportPrefix(findNode.simple('a.E'), findElement.prefix('a'));
+ var reference = findNode.functionReference('E<int>;');
+ assertFunctionReference(
+ reference,
+ findElement.importFind('package:test/a.dart').extension_('E'),
+ 'dynamic',
+ );
+ }
+
test_extensionGetter_extensionOverride() async {
await assertErrorsInCode('''
class A {}
diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc
index cadb164..66bd3bd 100644
--- a/runtime/vm/compiler/backend/type_propagator_test.cc
+++ b/runtime/vm/compiler/backend/type_propagator_test.cc
@@ -552,7 +552,7 @@
const char* kScript = R"(
const y = 0xDEADBEEF;
- final int x = 0xFEEDFEED;
+ final int x = int.parse('0xFEEDFEED');
void main(List<String> args) {
print(x);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7464bef..03d5a27 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2776,6 +2776,10 @@
Class::Handle(field.Owner()).Name() == Symbols::ClassID().ptr());
return Constant(Instance::ZoneHandle(
Z, Instance::RawCast(field.StaticConstFieldValue())));
+ } else if (field.is_final() && field.has_trivial_initializer()) {
+ // Final fields with trivial initializers are effectively constant.
+ return Constant(Instance::ZoneHandle(
+ Z, Instance::RawCast(field.StaticConstFieldValue())));
} else {
const Class& owner = Class::Handle(Z, field.Owner());
const String& getter_name = H.DartGetterName(target);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
index f280b55..6bb19fa 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -340,4 +340,44 @@
// clang-format on
}
+ISOLATE_UNIT_TEST_CASE(
+ StreamingFlowGraphBuilder_StaticGetFinalFieldWithTrivialInitializer) {
+ const char* kScript = R"(
+ final int x = 0xFEEDFEED;
+ test() {
+ return x;
+ }
+ )";
+
+ const auto& root_library = Library::Handle(LoadTestScript(kScript));
+ const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+ Invoke(root_library, "test");
+
+ TestPipeline pipeline(function, CompilerPass::kJIT);
+ FlowGraph* flow_graph = pipeline.RunPasses({
+ CompilerPass::kComputeSSA,
+ });
+
+ auto entry = flow_graph->graph_entry()->normal_entry();
+ EXPECT(entry != nullptr);
+
+ ReturnInstr* return_instr = nullptr;
+
+ ILMatcher cursor(flow_graph, entry);
+ RELEASE_ASSERT(cursor.TryMatch({
+ kMatchAndMoveFunctionEntry,
+ kMatchAndMoveCheckStackOverflow,
+ kMoveDebugStepChecks,
+ {kMatchReturn, &return_instr},
+ }));
+
+ EXPECT(return_instr != nullptr);
+ ConstantInstr* const_value =
+ return_instr->value()->definition()->AsConstant();
+ EXPECT(const_value != nullptr);
+ EXPECT(const_value->value().IsInteger());
+ EXPECT_EQ(0xFEEDFEED, Integer::Cast(const_value->value()).AsInt64Value());
+}
+
} // namespace dart
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index f018ad4..6efc565 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -881,7 +881,8 @@
SimpleExpressionConverter converter(&H, &helper_);
const bool has_simple_initializer =
converter.IsSimple(helper_.ReaderOffset() + 1);
- if (!has_simple_initializer || !converter.SimpleValue().IsNull()) {
+ if (!has_simple_initializer ||
+ (!field.is_static() && !converter.SimpleValue().IsNull())) {
field.set_has_nontrivial_initializer(true);
}
return;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7a9fc6e..249c950 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11172,7 +11172,8 @@
}
ObjectPtr Field::StaticConstFieldValue() const {
- ASSERT(is_static() && is_const());
+ ASSERT(is_static() &&
+ (is_const() || (is_final() && has_trivial_initializer())));
auto thread = Thread::Current();
auto zone = thread->zone();
@@ -11183,7 +11184,11 @@
auto& value = Object::Handle(
zone, initial_field_table->At(field_id(), /*concurrent_use=*/true));
if (value.ptr() == Object::sentinel().ptr()) {
+ // Fields with trivial initializers get their initial value
+ // eagerly when they are registered.
+ ASSERT(is_const());
ASSERT(has_initializer());
+ ASSERT(has_nontrivial_initializer());
value = EvaluateInitializer();
if (!value.IsError()) {
ASSERT(value.IsNull() || value.IsInstance());
diff --git a/tools/VERSION b/tools/VERSION
index a417d59..c2f4478 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 100
+PRERELEASE 101
PRERELEASE_PATCH 0
\ No newline at end of file