Version 3.0.0-5.0.dev
Merge 49f9a85be2cd10ef4a1d65eacf7de21ee1aeb390 into dev
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 25bb36f..eca97b1 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -49,11 +49,9 @@
/// Return a list of the experiments that are to be enabled for tests in this
/// class, an empty list if there are no experiments that should be enabled.
List<String> get experiments => [
- EnableString.enhanced_enums,
EnableString.macros,
- EnableString.named_arguments_anywhere,
+ EnableString.patterns,
EnableString.records,
- EnableString.super_parameters,
];
String get latestLanguageVersion =>
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 0d839ec..865de54 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -2400,14 +2400,40 @@
assertSuggestKeywords([Keyword.CASE, Keyword.DEFAULT]);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_switch_statement_case_break_insideClass() async {
- addTestSource('class A{foo() {switch(1) {case 1: b^}}}');
+ addTestSource('''
+class A{foo() {switch(1) {case 1: b^}}}
+''');
await computeSuggestions();
assertSuggestKeywords(statementStartInSwitchCaseInClass);
}
+ Future<void>
+ test_switch_statement_case_break_insideClass_language219() async {
+ addTestSource('''
+// @dart=2.19
+class A{foo() {switch(1) {case 1: b^}}}
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(statementStartInSwitchCaseInClass);
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_switch_statement_case_break_outsideClass() async {
- addTestSource('foo() {switch(1) {case 1: b^}}');
+ addTestSource('''
+foo() {switch(1) {case 1: b^}}
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(statementStartInSwitchCaseOutsideClass);
+ }
+
+ Future<void>
+ test_switch_statement_case_break_outsideClass_language219() async {
+ addTestSource('''
+// @dart=2.19
+foo() {switch(1) {case 1: b^}}
+''');
await computeSuggestions();
assertSuggestKeywords(statementStartInSwitchCaseOutsideClass);
}
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index e866095..9d313d7 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -2394,6 +2394,7 @@
assertSuggestEnumConst('F.four');
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_enum_filter_switchCase() async {
addTestSource('''
enum E { one, two }
@@ -2416,6 +2417,29 @@
assertNotSuggested('F.four');
}
+ Future<void> test_enum_filter_switchCase_language219() async {
+ addTestSource('''
+// @dart=2.19
+enum E { one, two }
+enum F { three, four }
+
+void f(E e) {
+ switch (e) {
+ case ^
+ }
+}
+''');
+ await computeSuggestions();
+
+ assertSuggestEnum('E');
+ assertSuggestEnumConst('E.one');
+ assertSuggestEnumConst('E.two');
+
+ assertSuggestEnum('F');
+ assertNotSuggested('F.three');
+ assertNotSuggested('F.four');
+ }
+
Future<void> test_enum_filter_variableDeclaration() async {
addTestSource('''
enum E { one, two }
@@ -5825,9 +5849,27 @@
assertNotSuggested('String');
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_SwitchStatement_case_var() async {
// SwitchStatement Block BlockFunctionBody MethodDeclaration
- addTestSource('g(int x) {var t; switch(x) {case 0: var bar; b^}}');
+ addTestSource('''
+g(int x) {var t; switch(x) {case 0: var bar; b^}}
+''');
+ await computeSuggestions();
+
+ assertSuggestFunction('g', 'dynamic');
+ assertSuggestLocalVariable('t', 'dynamic');
+ assertSuggestParameter('x', 'int');
+ assertSuggestLocalVariable('bar', 'dynamic');
+ assertNotSuggested('String');
+ }
+
+ Future<void> test_SwitchStatement_case_var_language219() async {
+ // SwitchStatement Block BlockFunctionBody MethodDeclaration
+ addTestSource('''
+// @dart=2.19
+g(int x) {var t; switch(x) {case 0: var bar; b^}}
+''');
await computeSuggestions();
assertSuggestFunction('g', 'dynamic');
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index d63bf90..2018ec9 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1373,7 +1373,7 @@
_assertHasChange('Add a semicolon and newline', '''
class Thing extends Object {
int foo() => 1;
-
+ ////
}
''');
}
@@ -1455,7 +1455,7 @@
'''
void f() {
int g();
-
+ ////
}
''',
(s) => _afterLast(s, '();\n '));
@@ -1557,6 +1557,7 @@
@reflectiveTest
class _SwitchCompletionTest extends StatementCompletionTest {
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_caseNoColon() async {
await _prepareCompletion(
'label',
@@ -1580,6 +1581,31 @@
(s) => _after(s, 'label: '));
}
+ Future<void> test_caseNoColon_language219() async {
+ await _prepareCompletion(
+ 'label',
+ '''
+// @dart=2.19
+void f(x) {
+ switch (x) {
+ case label
+ }
+}
+''',
+ atEnd: true);
+ _assertHasChange(
+ 'Complete switch-statement',
+ '''
+// @dart=2.19
+void f(x) {
+ switch (x) {
+ case label: ////
+ }
+}
+''',
+ (s) => _after(s, 'label: '));
+ }
+
Future<void> test_defaultNoColon() async {
await _prepareCompletion(
'default',
diff --git a/pkg/analysis_server/test/services/refactoring/legacy/inline_local_test.dart b/pkg/analysis_server/test/services/refactoring/legacy/inline_local_test.dart
index 174be56..4d56095 100644
--- a/pkg/analysis_server/test/services/refactoring/legacy/inline_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/legacy/inline_local_test.dart
@@ -154,6 +154,7 @@
''');
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_OK_inSwitchCase() async {
await indexTestUnit('''
void f(int p) {
@@ -178,6 +179,32 @@
''');
}
+ Future<void> test_OK_inSwitchCase_language219() async {
+ await indexTestUnit('''
+// @dart=2.19
+void f(int p) {
+ switch (p) {
+ case 0:
+ int test = 42;
+ print(test);
+ break;
+ }
+}
+''');
+ _createRefactoring('test =');
+ // validate change
+ return assertSuccessfulRefactoring('''
+// @dart=2.19
+void f(int p) {
+ switch (p) {
+ case 0:
+ print(42);
+ break;
+ }
+}
+''');
+ }
+
Future<void> test_OK_intoStringInterpolation_binaryExpression() async {
await indexTestUnit(r'''
void f() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_case_clauses_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_case_clauses_test.dart
index 68c19bc..b229797 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_case_clauses_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_case_clauses_test.dart
@@ -256,6 +256,7 @@
await assertNoFix(errorFilter: _filter);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_notEmpty() async {
await resolveTestCode('''
enum E {a, b, c}
@@ -283,6 +284,35 @@
''');
}
+ Future<void> test_notEmpty_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+enum E {a, b, c}
+void f(E e) {
+ switch (e) {
+ case E.a:
+ break;
+ }
+}
+''');
+ await assertHasFixWithFilter('''
+// @dart=2.19
+enum E {a, b, c}
+void f(E e) {
+ switch (e) {
+ case E.a:
+ break;
+ case E.b:
+ // TODO: Handle this case.
+ break;
+ case E.c:
+ // TODO: Handle this case.
+ break;
+ }
+}
+''');
+ }
+
Future<void> test_static() async {
await resolveTestCode('''
enum E {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
index 67f4e6c..1e407b8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_enum_like_case_clauses_test.dart
@@ -116,6 +116,7 @@
''');
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_notEmpty() async {
await resolveTestCode('''
void f(E e) {
@@ -155,4 +156,46 @@
}
''');
}
+
+ Future<void> test_notEmpty_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void f(E e) {
+ switch (e) {
+ case E.a:
+ break;
+ case E.b:
+ break;
+ }
+}
+class E {
+ static const E a = E._(0);
+ static const E b = E._(1);
+ static const E c = E._(2);
+ final int x;
+ const E._(this.x);
+}
+''');
+ await assertHasFix('''
+// @dart=2.19
+void f(E e) {
+ switch (e) {
+ case E.a:
+ break;
+ case E.b:
+ break;
+ case E.c:
+ // TODO: Handle this case.
+ break;
+ }
+}
+class E {
+ static const E a = E._(0);
+ static const E b = E._(1);
+ static const E c = E._(2);
+ final int x;
+ const E._(this.x);
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_switch_case_break_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_switch_case_break_test.dart
index 90a5543..116dfe6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_switch_case_break_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_switch_case_break_test.dart
@@ -21,6 +21,7 @@
@override
FixKind get kind => DartFixKind.ADD_SWITCH_CASE_BREAK_MULTI;
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_singleFile() async {
await resolveTestCode('''
void f(int i) {
@@ -50,6 +51,38 @@
}
''');
}
+
+ Future<void> test_singleFile_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void f(int i) {
+ switch(i) {
+ case 0:
+ i++;
+ case 1:
+ i++;
+ case 2:
+ i++;
+ }
+}
+''');
+ await assertHasFixAllFix(
+ CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY, '''
+// @dart=2.19
+void f(int i) {
+ switch(i) {
+ case 0:
+ i++;
+ break;
+ case 1:
+ i++;
+ break;
+ case 2:
+ i++;
+ }
+}
+''');
+ }
}
@reflectiveTest
@@ -57,6 +90,7 @@
@override
FixKind get kind => DartFixKind.ADD_SWITCH_CASE_BREAK;
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_indentation() async {
await resolveTestCode('''
void f(int i) {
@@ -80,4 +114,30 @@
}
''');
}
+
+ Future<void> test_indentation_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void f(int i) {
+ switch(i) {
+ case 0:
+ i++;
+ case 1:
+ i++;
+ }
+}
+''');
+ await assertHasFix('''
+// @dart=2.19
+void f(int i) {
+ switch(i) {
+ case 0:
+ i++;
+ break;
+ case 1:
+ i++;
+ }
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_duplicate_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_duplicate_case_test.dart
index 1938e20..afba699 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_duplicate_case_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_duplicate_case_test.dart
@@ -61,6 +61,7 @@
@override
String get lintCode => LintNames.no_duplicate_case_values;
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_fallThroughFromPrevious() async {
await resolveTestCode('''
void switchInt() {
@@ -95,6 +96,43 @@
''');
}
+ Future<void> test_fallThroughFromPrevious_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void switchInt() {
+ switch (2) {
+ case 1:
+ print('a');
+ break;
+ case 2:
+ case 3:
+ case 2:
+ print('b');
+ break;
+ default:
+ print('?');
+ }
+}
+''');
+ await assertHasFix('''
+// @dart=2.19
+void switchInt() {
+ switch (2) {
+ case 1:
+ print('a');
+ break;
+ case 2:
+ case 3:
+ print('b');
+ break;
+ default:
+ print('?');
+ }
+}
+''');
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_removeIntCase() async {
await resolveTestCode('''
void switchInt() {
@@ -123,6 +161,37 @@
''');
}
+ Future<void> test_removeIntCase_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void switchInt() {
+ switch (2) {
+ case 1:
+ print('a');
+ break;
+ case 2:
+ case 2:
+ default:
+ print('?');
+ }
+}
+''');
+ await assertHasFix('''
+// @dart=2.19
+void switchInt() {
+ switch (2) {
+ case 1:
+ print('a');
+ break;
+ case 2:
+ default:
+ print('?');
+ }
+}
+''');
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/49759')
Future<void> test_removeStringCase() async {
await resolveTestCode('''
void switchString() {
@@ -158,4 +227,42 @@
}
''');
}
+
+ Future<void> test_removeStringCase_language219() async {
+ await resolveTestCode('''
+// @dart=2.19
+void switchString() {
+ String v = 'a';
+ switch (v) {
+ case 'a':
+ print('a');
+ break;
+ case 'b':
+ print('b');
+ break;
+ case 'a':
+ print('a');
+ break;
+ default:
+ print('?');
+ }
+}
+''');
+ await assertHasFix('''
+// @dart=2.19
+void switchString() {
+ String v = 'a';
+ switch (v) {
+ case 'a':
+ print('a');
+ break;
+ case 'b':
+ print('b');
+ break;
+ default:
+ print('?');
+ }
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/refactoring/move_top_level_to_file_test.dart b/pkg/analysis_server/test/src/services/refactoring/move_top_level_to_file_test.dart
index 4f43443..11e2c33 100644
--- a/pkg/analysis_server/test/src/services/refactoring/move_top_level_to_file_test.dart
+++ b/pkg/analysis_server/test/src/services/refactoring/move_top_level_to_file_test.dart
@@ -539,7 +539,7 @@
// apply the changes.
expect(content[expectedNewFilePath], newFileContent);
if (modifiedOtherFileContent != null) {
- expect(content[otherFilePath!], modifiedOtherFileContent);
+ expect(content[convertPath(otherFilePath!)], modifiedOtherFileContent);
}
}
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 7a3f388..6d325b8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -2804,9 +2804,10 @@
/// This class is used as a marker of constant context for initializers
/// of constant fields and top-level variables read from summaries.
class ConstantContextForExpressionImpl extends AstNodeImpl {
+ final Element variable;
final ExpressionImpl expression;
- ConstantContextForExpressionImpl(this.expression) {
+ ConstantContextForExpressionImpl(this.variable, this.expression) {
_becomeParentOf(expression);
}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 3f8aa9b..3ce5953 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1605,30 +1605,6 @@
}
}
-/// A recursive AST visitor that is used to run over [Expression]s to determine
-/// whether the expression is composed by at least one deferred
-/// [PrefixedIdentifier].
-///
-/// See [PrefixedIdentifier.isDeferred].
-class DeferredLibraryReferenceDetector extends RecursiveAstVisitor<void> {
- /// A flag indicating whether an identifier from a deferred library has been
- /// found.
- bool _result = false;
-
- /// Return `true` if the visitor found a [PrefixedIdentifier] that returned
- /// `true` to the [PrefixedIdentifier.isDeferred] query.
- bool get result => _result;
-
- @override
- void visitPrefixedIdentifier(PrefixedIdentifier node) {
- if (!_result) {
- if (node.isDeferred) {
- _result = true;
- }
- }
- }
-}
-
/// Class capable of handling exceptions generated during linting.
///
/// Clients may not extend, implement or mix-in this class.
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index b600714..e955a7d 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -11,11 +11,9 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/potentially_constant.dart';
import 'package:analyzer/src/dart/constant/value.dart';
@@ -318,10 +316,6 @@
} else {
_reportErrors(result.errors, null);
}
- _reportErrorIfFromDeferredLibrary(
- initializer,
- CompileTimeErrorCode
- .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY);
}
}
@@ -399,26 +393,6 @@
return false;
}
- /// Given some computed [Expression], this method generates the passed
- /// [ErrorCode] on the node if its' value consists of information from a
- /// deferred library.
- ///
- /// @param expression the expression to be tested for a deferred library
- /// reference
- /// @param errorCode the error code to be used if the expression is or
- /// consists of a reference to a deferred library
- void _reportErrorIfFromDeferredLibrary(
- Expression expression, ErrorCode errorCode,
- [List<Object>? arguments, List<DiagnosticMessage>? messages]) {
- DeferredLibraryReferenceDetector referenceDetector =
- DeferredLibraryReferenceDetector();
- expression.accept(referenceDetector);
- if (referenceDetector.result) {
- _errorReporter.reportErrorForNode(
- errorCode, expression, arguments, messages);
- }
- }
-
/// Report any errors in the given list. Except for special cases, use the
/// given error code rather than the one reported in the error.
///
@@ -447,7 +421,47 @@
identical(dataErrorCode,
CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH) ||
identical(
- dataErrorCode, CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH)) {
+ dataErrorCode, CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY) ||
+ identical(dataErrorCode,
+ CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY) ||
+ identical(dataErrorCode,
+ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY) ||
+ identical(
+ dataErrorCode,
+ CompileTimeErrorCode
+ .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY)) {
_errorReporter.reportError(data);
} else if (errorCode != null) {
_errorReporter.reportError(
@@ -515,12 +529,6 @@
argument is NamedExpression ? argument.expression : argument;
_validate(
realArgument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
- if (realArgument is PrefixedIdentifier && realArgument.isDeferred) {
- _reportErrorIfFromDeferredLibrary(
- realArgument,
- CompileTimeErrorCode
- .INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY);
- }
}
}
@@ -566,12 +574,6 @@
} else {
result = _validate(
defaultValue, CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE);
- if (result != null) {
- _reportErrorIfFromDeferredLibrary(
- defaultValue,
- CompileTimeErrorCode
- .NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY);
- }
}
VariableElementImpl element =
parameter.declaredElement as VariableElementImpl;
@@ -641,12 +643,6 @@
continue;
}
- _reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode
- .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
- );
-
var expressionValueType = _typeSystem.toLegacyTypeIfOptOut(
expressionValue.type,
);
@@ -692,12 +688,6 @@
continue;
}
- _reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode
- .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
- );
-
var expressionType = expressionValue.type;
if (_implementsEqualsWhenNotAllowed(expressionType)) {
@@ -732,8 +722,6 @@
var value = verifier._validate(element, errorCode);
if (value == null) return false;
- _validateExpressionFromDeferredLibrary(element);
-
final listElementType = this.listElementType;
if (listElementType != null) {
return _validateListExpression(listElementType, element, value);
@@ -755,9 +743,6 @@
// The errors have already been reported.
if (conditionBool == null) return false;
- verifier._reportErrorIfFromDeferredLibrary(element.condition,
- CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY);
-
var thenValid = true;
var elseValid = true;
var thenElement = element.thenElement;
@@ -781,9 +766,6 @@
var value = verifier._validate(element.expression, errorCode);
if (value == null) return false;
- verifier._reportErrorIfFromDeferredLibrary(element.expression,
- CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY);
-
if (listElementType != null || setConfig != null) {
return _validateListOrSetSpread(element, value);
}
@@ -837,20 +819,6 @@
return false;
}
- void _validateExpressionFromDeferredLibrary(Expression expression) {
- if (listElementType != null) {
- verifier._reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
- );
- } else if (setConfig != null) {
- verifier._reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY,
- );
- }
- }
-
bool _validateListExpression(
DartType listElementType, Expression expression, DartObjectImpl value) {
if (!verifier._runtimeTypeMatch(value, listElementType)) {
@@ -862,11 +830,6 @@
return false;
}
- verifier._reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
- );
-
return true;
}
@@ -954,11 +917,6 @@
);
}
- verifier._reportErrorIfFromDeferredLibrary(
- keyExpression,
- CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
- );
-
var existingKey = config.uniqueKeys[keyValue];
if (existingKey != null) {
config.duplicateKeys[keyExpression] = existingKey;
@@ -975,11 +933,6 @@
[valueValue.type, config.valueType],
);
}
-
- verifier._reportErrorIfFromDeferredLibrary(
- valueExpression,
- CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
- );
}
return true;
@@ -1039,11 +992,6 @@
return false;
}
- verifier._reportErrorIfFromDeferredLibrary(
- expression,
- CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY,
- );
-
var existingValue = config.uniqueValues[value];
if (existingValue != null) {
config.duplicateElements[expression] = existingValue;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index e33f9ef..f094afd 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -971,6 +971,12 @@
}
}
// importPrefix.CONST
+ if (prefixElement is PrefixElement) {
+ if (node.isDeferred) {
+ _reportFromDeferredLibrary(node);
+ return null;
+ }
+ }
if (prefixElement is! PrefixElement && prefixElement is! ExtensionElement) {
var prefixResult = prefixNode.accept(this);
if (prefixResult == null) {
@@ -1480,6 +1486,53 @@
identifier.staticElement?.enclosingElement is! ExtensionElement;
}
+ void _reportFromDeferredLibrary(PrefixedIdentifier node) {
+ var errorCode = () {
+ AstNode? previous;
+ for (AstNode? current = node; current != null;) {
+ if (current is Annotation) {
+ return CompileTimeErrorCode
+ .INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY;
+ } else if (current is ConstantContextForExpressionImpl) {
+ return CompileTimeErrorCode
+ .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY;
+ } else if (current is DefaultFormalParameter) {
+ return CompileTimeErrorCode
+ .NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY;
+ } else if (current is IfElement && current.condition == node) {
+ return CompileTimeErrorCode
+ .IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY;
+ } else if (current is ListLiteral) {
+ return CompileTimeErrorCode
+ .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY;
+ } else if (current is MapLiteralEntry) {
+ if (previous == current.key) {
+ return CompileTimeErrorCode
+ .NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY;
+ } else {
+ return CompileTimeErrorCode
+ .NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY;
+ }
+ } else if (current is SetOrMapLiteral) {
+ return CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY;
+ } else if (current is SpreadElement) {
+ return CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY;
+ } else if (current is SwitchCase) {
+ return CompileTimeErrorCode
+ .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY;
+ } else if (current is VariableDeclaration) {
+ return CompileTimeErrorCode
+ .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY;
+ }
+ previous = current;
+ current = current.parent;
+ }
+ }();
+ if (errorCode != null) {
+ _errorReporter.reportErrorForNode(errorCode, node.identifier);
+ }
+ }
+
void _reportNotPotentialConstants(AstNode node) {
var notPotentiallyConstants = getNotPotentiallyConstants(
node,
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 9fb931b..9d8e099 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -5276,20 +5276,27 @@
@override
void handleVariablePattern(Token? keyword, Token variable,
{required bool inAssignmentPattern}) {
- // TODO(paulberry, scheglov): use inAssignmentPattern
debugEvent('VariablePattern');
if (!_featureSet.isEnabled(Feature.patterns)) {
// TODO(paulberry): report the appropriate error
throw UnimplementedError('Patterns not enabled');
}
var type = pop() as TypeAnnotationImpl?;
- push(
- DeclaredVariablePatternImpl(
- keyword: keyword,
- type: type,
- name: variable,
- ),
- );
+ if (inAssignmentPattern) {
+ push(
+ AssignedVariablePatternImpl(
+ name: variable,
+ ),
+ );
+ } else {
+ push(
+ DeclaredVariablePatternImpl(
+ keyword: keyword,
+ type: type,
+ name: variable,
+ ),
+ );
+ }
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 633824f..fef7c32 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -326,7 +326,7 @@
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
- ConstantContextForExpressionImpl(initializer);
+ ConstantContextForExpressionImpl(element, initializer);
}
}
applyConstantOffsets?.perform();
@@ -2086,7 +2086,7 @@
var initializer = reader._readOptionalExpression();
if (initializer != null) {
element.constantInitializer = initializer;
- ConstantContextForExpressionImpl(initializer);
+ ConstantContextForExpressionImpl(element, initializer);
}
}
applyConstantOffsets?.perform();
diff --git a/pkg/analyzer/lib/src/summary2/detach_nodes.dart b/pkg/analyzer/lib/src/summary2/detach_nodes.dart
index a74d668..1d11afe 100644
--- a/pkg/analyzer/lib/src/summary2/detach_nodes.dart
+++ b/pkg/analyzer/lib/src/summary2/detach_nodes.dart
@@ -77,7 +77,7 @@
initializer = replaceNotSerializableNodes(initializer);
element.constantInitializer = initializer;
- ConstantContextForExpressionImpl(initializer);
+ ConstantContextForExpressionImpl(element, initializer);
}
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 8d5337c..1d3ab31 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -100,6 +100,10 @@
return _node(search, (n) => n is AssertStatement);
}
+ AssignedVariablePattern assignedVariablePattern(String search) {
+ return _node(search, (n) => n is AssignedVariablePattern);
+ }
+
AssignmentExpression assignment(String search) {
return _node(search, (n) => n is AssignmentExpression);
}
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 14c4cdd..787ce0d 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -1640,7 +1640,7 @@
```dart
import 'a.dart' deferred as a;
- var l = const [[!a.zero!]];
+ var l = const [a.[!zero!]];
```
#### Common fixes
@@ -2454,7 +2454,7 @@
```dart
import 'dart:math' deferred as math;
- const pi = [!math.pi!];
+ const pi = math.[!pi!];
```
#### Common fixes
@@ -6723,7 +6723,7 @@
const C(double d);
}
- @C([!math.pi!])
+ @C(math.[!pi!])
void f () {}
```
@@ -9445,7 +9445,7 @@
void f(int x) {
switch (x) {
- case [!a.zero!]:
+ case a.[!zero!]:
// ...
break;
}
@@ -9570,7 +9570,7 @@
```dart
import 'a.dart' deferred as a;
- void f({int x = [!a.zero!]}) {}
+ void f({int x = a.[!zero!]}) {}
```
#### Common fixes
diff --git a/pkg/analyzer/test/generated/patterns_parser_test.dart b/pkg/analyzer/test/generated/patterns_parser_test.dart
index 59d9386..db8c4bb 100644
--- a/pkg/analyzer/test/generated/patterns_parser_test.dart
+++ b/pkg/analyzer/test/generated/patterns_parser_test.dart
@@ -3520,9 +3520,9 @@
rightBracket: >
leftBracket: [
elements
- DeclaredVariablePattern
+ AssignedVariablePattern
name: a
- DeclaredVariablePattern
+ AssignedVariablePattern
name: b
rightBracket: ]
''');
@@ -3567,9 +3567,9 @@
ListPattern
leftBracket: [
elements
- DeclaredVariablePattern
+ AssignedVariablePattern
name: a
- DeclaredVariablePattern
+ AssignedVariablePattern
name: b
rightBracket: ]
''');
@@ -4504,13 +4504,13 @@
key: SimpleStringLiteral
literal: 'a'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: b
rightBracket: }
''');
@@ -4565,13 +4565,13 @@
key: SimpleStringLiteral
literal: 'a'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: b
rightBracket: }
''');
@@ -4592,13 +4592,13 @@
key: SimpleStringLiteral
literal: 'a'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: a
MapPatternEntry
key: SimpleStringLiteral
literal: 'b'
separator: :
- value: DeclaredVariablePattern
+ value: AssignedVariablePattern
name: b
rightBracket: }
''');
@@ -6160,7 +6160,7 @@
assertParsedNodeText(node, r'''
ParenthesizedPattern
leftParenthesis: (
- pattern: DeclaredVariablePattern
+ pattern: AssignedVariablePattern
name: a
rightParenthesis: )
''');
@@ -7102,7 +7102,7 @@
leftParenthesis: (
fields
RecordPatternField
- pattern: DeclaredVariablePattern
+ pattern: AssignedVariablePattern
name: a
rightParenthesis: )
''');
@@ -7120,10 +7120,10 @@
leftParenthesis: (
fields
RecordPatternField
- pattern: DeclaredVariablePattern
+ pattern: AssignedVariablePattern
name: a
RecordPatternField
- pattern: DeclaredVariablePattern
+ pattern: AssignedVariablePattern
name: b
rightParenthesis: )
''');
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index 3a3dad2..74b5899 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -100,6 +100,15 @@
);
}
+ void test_visitAssignedVariablePattern() {
+ var findNode = _parseStringToFindNode('''
+void f(int foo) {
+ (foo) = 0;
+}
+''');
+ _assertSource('foo', findNode.assignedVariablePattern('foo) = 0'));
+ }
+
void test_visitAssignmentExpression() {
final code = 'a = b';
final findNode = _parseStringToFindNode('''
@@ -874,6 +883,21 @@
_assertSource(code, findNode.continueStatement('continue'));
}
+ void test_visitDeclaredVariablePattern() {
+ var findNode = _parseStringToFindNode('''
+void f(x) {
+ switch (x) {
+ case int? _:
+ break;
+ }
+}
+''');
+ _assertSource(
+ 'int? _',
+ findNode.declaredVariablePattern('int?'),
+ );
+ }
+
void test_visitDefaultFormalParameter_annotation() {
final code = '@deprecated p = 0';
final findNode = _parseStringToFindNode('''
@@ -3726,21 +3750,6 @@
_assertSource(code, findNode.variableDeclarationList(code));
}
- void test_visitVariablePattern() {
- var findNode = _parseStringToFindNode('''
-void f(x) {
- switch (x) {
- case int? _:
- break;
- }
-}
-''');
- _assertSource(
- 'int? _',
- findNode.declaredVariablePattern('int?'),
- );
- }
-
void test_visitWhileStatement() {
final code = 'while (true) {}';
final findNode = _parseStringToFindNode('''
diff --git a/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_from_deferred_library_test.dart
index 3f7b454..64ef422 100644
--- a/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_from_deferred_library_test.dart
@@ -30,8 +30,8 @@
error(
CompileTimeErrorCode
.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY,
- 58,
- 3),
+ 60,
+ 1),
]);
}
@@ -48,8 +48,8 @@
error(
CompileTimeErrorCode
.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY,
- 58,
- 7),
+ 60,
+ 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
index 80176d0..bd5de22 100644
--- a/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
@@ -27,8 +27,8 @@
f() {
return const [if(a.c) 0];
}''', [
- error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
- 3),
+ error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 61,
+ 1),
]);
}
@@ -60,8 +60,8 @@
f() {
return const {if(a.c) 0 : 0};
}''', [
- error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
- 3),
+ error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 61,
+ 1),
]);
}
@@ -93,8 +93,8 @@
f() {
return const {if(a.c) 0};
}''', [
- error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
- 3),
+ error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 61,
+ 1),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_annotation_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_annotation_from_deferred_library_test.dart
index 0d9c533..07df008 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_annotation_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_annotation_from_deferred_library_test.dart
@@ -44,8 +44,8 @@
error(
CompileTimeErrorCode
.INVALID_ANNOTATION_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY,
- 79,
- 3),
+ 81,
+ 1),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart
index c528d64..b4b5f35 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_case_expression_from_deferred_library_test.dart
@@ -59,8 +59,8 @@
error(
CompileTimeErrorCode
.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
- 72,
- 7),
+ 74,
+ 1),
]);
}
@@ -82,8 +82,8 @@
error(
CompileTimeErrorCode
.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
- 72,
- 3),
+ 74,
+ 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_default_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_default_value_from_deferred_library_test.dart
index edc5449..1727b3e 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_default_value_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_default_value_from_deferred_library_test.dart
@@ -28,8 +28,8 @@
''', [
error(
CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY,
- 55,
- 3),
+ 57,
+ 1),
]);
}
@@ -45,8 +45,8 @@
''', [
error(
CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY,
- 55,
- 7),
+ 57,
+ 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
index 7ef1145..6f202d0 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
@@ -47,8 +47,8 @@
''', [
error(
CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
- 79,
- 3),
+ 81,
+ 1),
]);
}
@@ -61,8 +61,8 @@
''', [
error(
CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
- 49,
- 3),
+ 51,
+ 1),
]);
}
@@ -75,8 +75,8 @@
''', [
error(
CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
- 49,
- 7),
+ 51,
+ 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
index f12929b..e28e7ac 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
@@ -42,8 +42,8 @@
const cond = true;
var v = const { if (cond) a.c : 0};
''', [
- error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 79,
- 3),
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 81,
+ 1),
]);
}
@@ -54,8 +54,8 @@
import 'lib1.dart' deferred as a;
var v = const {a.c : 0};
''', [
- error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 49,
- 3),
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 51,
+ 1),
]);
}
@@ -66,8 +66,8 @@
import 'lib1.dart' deferred as a;
var v = const {a.c + 1 : 0};
''', [
- error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 49,
- 7),
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 51,
+ 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
index 47025d3..84df9e7 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
@@ -44,7 +44,7 @@
var v = const { if (cond) 'a' : a.c};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
- 85, 3),
+ 87, 1),
]);
}
@@ -56,7 +56,7 @@
var v = const {'a' : a.c};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
- 55, 3),
+ 57, 1),
]);
}
@@ -68,7 +68,7 @@
var v = const {'a' : a.c + 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
- 55, 7),
+ 57, 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
index b0afe54..c42b20b 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
@@ -40,7 +40,7 @@
const cond = true;
var v = const {if (cond) a.c};
''', [
- error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 78, 3),
+ error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 80, 1),
]);
}
@@ -51,7 +51,7 @@
import 'lib1.dart' deferred as a;
var v = const {a.c};
''', [
- error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 49, 3),
+ error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 51, 1),
]);
}
@@ -62,7 +62,7 @@
import 'lib1.dart' deferred as a;
var v = const {a.c + 1};
''', [
- error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 49, 7),
+ error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 51, 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
index 557e1bd..43737d4 100644
--- a/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
@@ -27,7 +27,7 @@
return const [...a.c];
}''', [
error(
- CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 61, 1),
]);
}
@@ -60,7 +60,7 @@
return const {...a.c};
}''', [
error(
- CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 61, 1),
]);
}
@@ -93,7 +93,7 @@
return const {...a.c};
}''', [
error(
- CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 61, 1),
]);
}
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index ce27a4e..e90d345 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -111,6 +111,19 @@
}
@override
+ void visitAssignedVariablePattern(
+ covariant AssignedVariablePatternImpl node,
+ ) {
+ _writeln('AssignedVariablePattern');
+ _withIndent(() {
+ _writeNamedChildEntities(node);
+ if (_withResolution) {
+ writeElement('element', node.element);
+ }
+ });
+ }
+
+ @override
void visitAssignmentExpression(AssignmentExpression node) {
_writeln('AssignmentExpression');
_withIndent(() {
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index ec8b459..5efed48 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -2303,7 +2303,7 @@
{% prettify dart tag=pre+code %}
import 'a.dart' deferred as a;
-var l = const [[!a.zero!]];
+var l = const [a.[!zero!]];
{% endprettify %}
#### Common fixes
@@ -2937,7 +2937,7 @@
{% prettify dart tag=pre+code %}
import 'dart:math' deferred as math;
-const pi = [!math.pi!];
+const pi = math.[!pi!];
{% endprettify %}
#### Common fixes
@@ -8226,7 +8226,7 @@
const C(double d);
}
-@C([!math.pi!])
+@C(math.[!pi!])
void f () {}
{% endprettify %}
@@ -12505,7 +12505,7 @@
void f(int x) {
switch (x) {
- case [!a.zero!]:
+ case a.[!zero!]:
// ...
break;
}
@@ -12626,7 +12626,7 @@
{% prettify dart tag=pre+code %}
import 'a.dart' deferred as a;
-void f({int x = [!a.zero!]}) {}
+void f({int x = a.[!zero!]}) {}
{% endprettify %}
#### Common fixes
diff --git a/pkg/compiler/lib/src/resolution/enqueuer.dart b/pkg/compiler/lib/src/resolution/enqueuer.dart
index a560e5d..2699d6c 100644
--- a/pkg/compiler/lib/src/resolution/enqueuer.dart
+++ b/pkg/compiler/lib/src/resolution/enqueuer.dart
@@ -13,7 +13,7 @@
import '../elements/types.dart';
import '../js_backend/annotations.dart';
import '../universe/member_usage.dart';
-import '../universe/resolution_world_builder_interfaces.dart';
+import '../universe/resolution_world_builder.dart' show ResolutionWorldBuilder;
import '../universe/use.dart'
show
ConstantUse,
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index d4759d8..0b00d1b 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1487,13 +1487,65 @@
return _isNonNullableByDefault(node.parent);
}
- /// Builds an SSA graph for FunctionNodes of external methods. This produces a
- /// graph for a method with Dart calling conventions that forwards to the
- /// actual external method.
+ /// Builds an SSA graph for FunctionNodes of external methods.
void _buildExternalFunctionNode(
FunctionEntity function, ir.FunctionNode functionNode) {
assert(functionNode.body == null);
+ if (closedWorld.nativeData.isNativeMember(targetElement)) {
+ _buildExternalNativeFunctionNode(function, functionNode);
+ return;
+ }
+
+ if (function.name == '==') {
+ if (_buildSpecialRuntimeEqualsMethod(function, functionNode)) return;
+ }
+
+ // `external` functions in `dart:_foreign_helper` are queued for compilation
+ // in a modular or staged compile, so just generate an empty function. The
+ // actual call sites for these methods are recognized and replaced, so the
+ // method generated here is never called.
+ if (_commonElements.isForeignHelper(function)) {
+ _openFunction(function,
+ functionNode: functionNode,
+ parameterStructure: function.parameterStructure,
+ checks: _checksForFunction(function));
+ _closeFunction();
+ return;
+ }
+
+ failedAt(CURRENT_ELEMENT_SPANNABLE, 'Unknown external method $function');
+ }
+
+ bool _buildSpecialRuntimeEqualsMethod(
+ FunctionEntity function, ir.FunctionNode functionNode) {
+ assert(function.name == '==');
+
+ if (function.enclosingClass == _commonElements.jsNullClass) {
+ _openFunction(function,
+ functionNode: functionNode,
+ parameterStructure: function.parameterStructure,
+ checks: _checksForFunction(function));
+ HInstruction instance = graph.addConstantNull(closedWorld);
+ HInstruction parameter = parameters.values.first;
+ HInstruction value =
+ HIdentity(instance, parameter, _abstractValueDomain.boolType);
+ add(value);
+ _closeAndGotoExit(HReturn(_abstractValueDomain, value,
+ _sourceInformationBuilder.buildReturn(functionNode)));
+ _closeFunction();
+ return true;
+ }
+
+ return false;
+ }
+
+ /// Builds an SSA graph for FunctionNodes of external methods that are
+ /// 'native' or 'js-interop' methods. This produces a graph for a method with
+ /// Dart calling conventions that forwards to the actual JavaScript `external`
+ /// method.
+ void _buildExternalNativeFunctionNode(
+ FunctionEntity function, ir.FunctionNode functionNode) {
bool isJsInterop = closedWorld.nativeData.isJsInteropMember(function);
_openFunction(function,
@@ -1501,74 +1553,71 @@
parameterStructure: function.parameterStructure,
checks: _checksForFunction(function));
- if (closedWorld.nativeData.isNativeMember(targetElement)) {
- List<HInstruction> inputs = [];
- if (targetElement.isInstanceMember) {
- inputs.add(localsHandler.readThis(
- sourceInformation:
- _sourceInformationBuilder.buildGet(functionNode)));
- }
+ List<HInstruction> inputs = [];
+ if (targetElement.isInstanceMember) {
+ inputs.add(localsHandler.readThis(
+ sourceInformation: _sourceInformationBuilder.buildGet(functionNode)));
+ }
- void handleParameter(ir.VariableDeclaration param) {
- Local local = _localsMap.getLocalVariable(param);
- // Convert Dart function to JavaScript function.
- HInstruction argument = localsHandler.readLocal(local);
- ir.DartType type = param.type;
- if (!isJsInterop && type is ir.FunctionType) {
- int arity = type.positionalParameters.length;
- _pushStaticInvocation(
- _commonElements.closureConverter,
- [argument, graph.addConstantInt(arity, closedWorld)],
- _abstractValueDomain.dynamicType,
- const <DartType>[],
- sourceInformation: null);
- argument = pop();
- }
- inputs.add(argument);
+ void handleParameter(ir.VariableDeclaration param) {
+ Local local = _localsMap.getLocalVariable(param);
+ // Convert Dart function to JavaScript function.
+ HInstruction argument = localsHandler.readLocal(local);
+ ir.DartType type = param.type;
+ if (!isJsInterop && type is ir.FunctionType) {
+ int arity = type.positionalParameters.length;
+ _pushStaticInvocation(
+ _commonElements.closureConverter,
+ [argument, graph.addConstantInt(arity, closedWorld)],
+ _abstractValueDomain.dynamicType,
+ const <DartType>[],
+ sourceInformation: null);
+ argument = pop();
}
+ inputs.add(argument);
+ }
- for (int position = 0;
- position < function.parameterStructure.positionalParameters;
- position++) {
- handleParameter(functionNode.positionalParameters[position]);
- }
- if (functionNode.namedParameters.isNotEmpty) {
- List<ir.VariableDeclaration> namedParameters = functionNode
- .namedParameters
- // Filter elided parameters.
- .where((p) =>
- function.parameterStructure.namedParameters.contains(p.name))
- .toList();
- // Sort by file offset to visit parameters in declaration order.
- namedParameters.sort(nativeOrdering);
- namedParameters.forEach(handleParameter);
- }
+ for (int position = 0;
+ position < function.parameterStructure.positionalParameters;
+ position++) {
+ handleParameter(functionNode.positionalParameters[position]);
+ }
+ if (functionNode.namedParameters.isNotEmpty) {
+ List<ir.VariableDeclaration> namedParameters = functionNode
+ .namedParameters
+ // Filter elided parameters.
+ .where((p) =>
+ function.parameterStructure.namedParameters.contains(p.name))
+ .toList();
+ // Sort by file offset to visit parameters in declaration order.
+ namedParameters.sort(nativeOrdering);
+ namedParameters.forEach(handleParameter);
+ }
- NativeBehavior nativeBehavior =
- _nativeData.getNativeMethodBehavior(function);
- AbstractValue returnType =
- _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
+ NativeBehavior nativeBehavior =
+ _nativeData.getNativeMethodBehavior(function);
+ AbstractValue returnType =
+ _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
- push(HInvokeExternal(targetElement, inputs, returnType, nativeBehavior,
- sourceInformation: null));
- HInstruction value = pop();
- // TODO(johnniwinther): Provide source information.
- if (options.nativeNullAssertions) {
- if (_isNonNullableByDefault(functionNode)) {
- DartType type = _getDartTypeIfValid(functionNode.returnType);
- if (dartTypes.isNonNullableIfSound(type) &&
- nodeIsInWebLibrary(functionNode)) {
- push(HNullCheck(value, _abstractValueDomain.excludeNull(returnType),
- sticky: true));
- value = pop();
- }
+ push(HInvokeExternal(targetElement, inputs, returnType, nativeBehavior,
+ sourceInformation: null));
+ HInstruction value = pop();
+ // TODO(johnniwinther): Provide source information.
+ if (options.nativeNullAssertions) {
+ if (_isNonNullableByDefault(functionNode)) {
+ DartType type = _getDartTypeIfValid(functionNode.returnType);
+ if (dartTypes.isNonNullableIfSound(type) &&
+ nodeIsInWebLibrary(functionNode)) {
+ push(HNullCheck(value, _abstractValueDomain.excludeNull(returnType),
+ sticky: true));
+ value = pop();
}
}
- if (targetElement.isSetter) {
- _closeAndGotoExit(HGoto(_abstractValueDomain));
- } else {
- _emitReturn(value, _sourceInformationBuilder.buildReturn(functionNode));
- }
+ }
+ if (targetElement.isSetter) {
+ _closeAndGotoExit(HGoto(_abstractValueDomain));
+ } else {
+ _emitReturn(value, _sourceInformationBuilder.buildReturn(functionNode));
}
_closeFunction();
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index f03bdf8..c7d8522 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -120,7 +120,8 @@
// Dart semantics for `a == b` check `a` and `b` against `null` outside
// the method invocation. For code size reasons, dart2js implements the
// null check on `a` by implementing `JSNull.==`, and the null check on
- // `b` by injecting the check into `==` methods, before any type checks.
+ // `b` by injecting the check into `==` methods, before any argument type
+ // checks.
//
// There are a small number of runtime library methods that do not have
// the check injected. For these we need to widen the argument type to
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 4af3426..814249d 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -28,7 +28,6 @@
import 'class_hierarchy.dart' show ClassHierarchyBuilder;
import 'class_set.dart';
import 'member_usage.dart';
-import 'resolution_world_builder_interfaces.dart' as interfaces;
import 'selector.dart' show Selector;
import 'use.dart'
show ConstantUse, DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
@@ -189,8 +188,7 @@
}
}
-class ResolutionWorldBuilder extends WorldBuilder
- implements World, interfaces.ResolutionWorldBuilder {
+class ResolutionWorldBuilder extends WorldBuilder implements World {
/// Instantiation information for all classes with instantiated types.
///
/// Invariant: Elements are declaration elements.
@@ -302,16 +300,13 @@
Iterable<ClassEntity> get processedClasses => _processedClasses.keys
.where((cls) => _processedClasses[cls]!.isInstantiated);
- @override
bool isMemberProcessed(MemberEntity member) =>
_processedMembers.contains(member);
- @override
void registerProcessedMember(MemberEntity member) {
_processedMembers.add(member);
}
- @override
Iterable<MemberEntity> get processedMembers => _processedMembers;
/// The closed world computed by this world builder.
@@ -326,7 +321,6 @@
}
// TODO(johnniwinther): Improve semantic precision.
- @override
Iterable<ClassEntity> get directlyInstantiatedClasses {
Set<ClassEntity> classes = {};
getInstantiationMap().forEach((ClassEntity cls, InstantiationInfo info) {
@@ -338,7 +332,6 @@
}
/// Registers that [element] has been closurized.
- @override
void registerClosurizedMember(MemberEntity element) {
FunctionType type =
_elementEnvironment.getFunctionType(element as FunctionEntity);
@@ -351,7 +344,6 @@
// TODO(johnniwinther): Fully enforce the separation between exact, through
// subclass and through subtype instantiated types/classes.
// TODO(johnniwinther): Support unknown type arguments for generic types.
- @override
void registerTypeInstantiation(
InterfaceType type, ClassUsedCallback classUsed,
{ConstructorEntity? constructor}) {
@@ -441,7 +433,6 @@
/// Applies the [dynamicUse] to applicable instance members. Calls
/// [membersUsed] with the usage changes for each member.
- @override
void registerDynamicUse(
DynamicUse dynamicUse, MemberUsedCallback memberUsed) {
Selector selector = dynamicUse.selector;
@@ -522,26 +513,22 @@
}
/// Registers that [type] is checked in this world builder.
- @override
void registerIsCheck(covariant DartType type) {
_isChecks.add(type);
}
- @override
void registerNamedTypeVariableNewRti(TypeVariableType type) {
_namedTypeVariablesNewRti.add(type);
}
/// Register the constant [use] with this world builder. Returns `true` if
/// the constant use was new to the world.
- @override
bool registerConstantUse(ConstantUse use) {
return _constantValues.add(use.value);
}
/// Applies the [staticUse] to applicable members. Calls [membersUsed] with
/// the usage changes for each member.
- @override
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
if (staticUse.kind == StaticUseKind.CLOSURE) {
Local localFunction = staticUse.element as Local;
@@ -677,7 +664,6 @@
/// If [checkEnqueuerConsistency] is `true` we check that no new member
/// usage can be found. This check is performed without changing the already
/// collected member usage.
- @override
void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
{bool checkEnqueuerConsistency = false}) {
_elementEnvironment.forEachClassMember(cls,
@@ -687,7 +673,6 @@
});
}
- @override
void processAbstractClassMembers(
ClassEntity cls, MemberUsedCallback memberUsed) {
_elementEnvironment.forEachLocalClassMember(cls, (MemberEntity member) {
@@ -869,7 +854,6 @@
}
}
- @override
void registerUsedElement(MemberEntity element) {
if (element.isInstanceMember) {
if (element.isAbstract) {
@@ -927,7 +911,6 @@
return assignedInstanceMembers;
}
- @override
void registerClass(ClassEntity cls) {
_classHierarchyBuilder.registerClass(cls);
}
@@ -945,7 +928,6 @@
/// Here `A.m` is inherited into `A`, `B`, and `C`. Because `B` and
/// `C` implement `I`, `isInheritedInSubtypeOf(A.m, I)` is true, but
/// `isInheritedInSubtypeOf(A.m, J)` is false.
- @override
bool isInheritedIn(
MemberEntity member, ClassEntity type, ClassRelation relation) {
// TODO(johnniwinther): Use the [member] itself to avoid enqueueing members
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart b/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
deleted file mode 100644
index a08f863..0000000
--- a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import '../elements/entities.dart';
-import '../elements/types.dart';
-import '../ir/class_relation.dart';
-import 'member_usage.dart';
-import 'use.dart';
-import '../world.dart';
-
-abstract class ResolutionWorldBuilder implements World {
- Iterable<ClassEntity> get directlyInstantiatedClasses;
-
- Iterable<MemberEntity> get processedMembers;
-
- void registerTypeInstantiation(
- InterfaceType type, ClassUsedCallback classUsed,
- {ConstructorEntity? constructor});
-
- void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
- {bool checkEnqueuerConsistency = false});
-
- void processAbstractClassMembers(
- ClassEntity cls, MemberUsedCallback memberUsed);
-
- bool isInheritedIn(
- MemberEntity member, ClassEntity type, ClassRelation relation);
-
- void registerDynamicUse(DynamicUse dynamicUse, MemberUsedCallback memberUsed);
-
- bool registerConstantUse(ConstantUse use);
-
- void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed);
-
- void registerTypeVariableTypeLiteral(TypeVariableType typeVariable);
-
- void registerIsCheck(covariant DartType type);
-
- void registerNamedTypeVariableNewRti(TypeVariableType type);
-
- void registerClosurizedMember(MemberEntity element);
-
- bool isMemberProcessed(MemberEntity member);
-
- void registerProcessedMember(MemberEntity member);
-
- void registerUsedElement(MemberEntity element);
-
- void registerClass(ClassEntity cls);
-}
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index f90ddfd..938b107 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -13,7 +13,7 @@
import '../world.dart' show World;
import 'selector.dart' show Selector;
import 'use.dart' show DynamicUse, StaticUse;
-import 'resolution_world_builder_interfaces.dart' show ResolutionWorldBuilder;
+import 'resolution_world_builder.dart' show ResolutionWorldBuilder;
import 'strong_mode_constraint.dart' show StrongModeConstraintInterface;
/// The combined constraints on receivers all the dynamic call sites of the same
diff --git a/pkg/dart2wasm/bin/dart2wasm.dart b/pkg/dart2wasm/bin/dart2wasm.dart
index bc0b106..3c4dd94 100644
--- a/pkg/dart2wasm/bin/dart2wasm.dart
+++ b/pkg/dart2wasm/bin/dart2wasm.dart
@@ -50,8 +50,12 @@
StringMultiOption(
"define", (o, values) => o.environment = processEnvironment(values),
abbr: "D"),
- StringMultiOption("enable-experiment",
- (o, values) => o.feExperimentalFlags = processFeExperimentalFlags(values))
+ StringMultiOption(
+ "enable-experiment",
+ (o, values) =>
+ o.feExperimentalFlags = processFeExperimentalFlags(values)),
+ StringOption("multi-root-scheme", (o, value) => o.multiRootScheme = value),
+ UriMultiOption("multi-root", (o, values) => o.multiRoots = values),
];
Map<fe.ExperimentalFlag, bool> processFeExperimentalFlags(
diff --git a/pkg/dart2wasm/lib/compile.dart b/pkg/dart2wasm/lib/compile.dart
index 145b6e7..47c2ca7 100644
--- a/pkg/dart2wasm/lib/compile.dart
+++ b/pkg/dart2wasm/lib/compile.dart
@@ -4,6 +4,11 @@
import 'dart:typed_data';
+import 'package:build_integration/file_system/multi_root.dart'
+ show MultiRootFileSystem;
+
+import 'package:front_end/src/api_prototype/standard_file_system.dart'
+ show StandardFileSystem;
import 'package:front_end/src/api_unstable/vm.dart'
show
CompilerOptions,
@@ -52,6 +57,12 @@
..verbose = false
..onDiagnostic = diagnosticMessageHandler
..nnbdMode = NnbdMode.Strong;
+ if (options.multiRootScheme != null) {
+ compilerOptions.fileSystem = new MultiRootFileSystem(
+ options.multiRootScheme!,
+ options.multiRoots.isEmpty ? [Uri.base] : options.multiRoots,
+ StandardFileSystem.instance);
+ }
if (options.platformPath != null) {
compilerOptions.sdkSummary = options.platformPath;
diff --git a/pkg/dart2wasm/lib/compiler_options.dart b/pkg/dart2wasm/lib/compiler_options.dart
index 015cf8c..6929bf4 100644
--- a/pkg/dart2wasm/lib/compiler_options.dart
+++ b/pkg/dart2wasm/lib/compiler_options.dart
@@ -18,6 +18,8 @@
String outputFile;
Map<String, String> environment = const {};
Map<fe.ExperimentalFlag, bool> feExperimentalFlags = const {};
+ String? multiRootScheme;
+ List<Uri> multiRoots = const [];
factory CompilerOptions.defaultOptions() =>
CompilerOptions(mainUri: Uri(), outputFile: '');
diff --git a/pkg/dart2wasm/lib/option.dart b/pkg/dart2wasm/lib/option.dart
index b8e20dc..7802d0b 100644
--- a/pkg/dart2wasm/lib/option.dart
+++ b/pkg/dart2wasm/lib/option.dart
@@ -51,6 +51,12 @@
defaultsTo: defaultsTo);
}
+class StringOption extends ValueOption<String> {
+ StringOption(String name, void applyToOptions(CompilerOptions o, String v),
+ {String? defaultsTo})
+ : super(name, applyToOptions, (v) => v, defaultsTo: defaultsTo);
+}
+
class UriOption extends ValueOption<Uri> {
UriOption(String name, void applyToOptions(CompilerOptions o, Uri v),
{String? defaultsTo})
@@ -86,3 +92,10 @@
: super(name, applyToOptions, (v) => v,
abbr: abbr, defaultsTo: defaultsTo);
}
+
+class UriMultiOption extends MultiValueOption<Uri> {
+ UriMultiOption(name, void applyToOptions(CompilerOptions o, List<Uri> v),
+ {Iterable<String>? defaultsTo})
+ : super(name, applyToOptions, (v) => Uri.file(Directory(v).absolute.path),
+ defaultsTo: defaultsTo);
+}
diff --git a/pkg/dart2wasm/pubspec.yaml b/pkg/dart2wasm/pubspec.yaml
index 6162b48..108cc6e 100644
--- a/pkg/dart2wasm/pubspec.yaml
+++ b/pkg/dart2wasm/pubspec.yaml
@@ -9,6 +9,7 @@
_fe_analyzer_shared: any
_js_interop_checks: any
args: any
+ build_integration: any
front_end: any
kernel: any
vm: any
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 9f8bd3d..ba3f32d 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5935,7 +5935,13 @@
case 'PRINT_LEGACY_STARS':
return js.boolean(_options.printLegacyStars);
case 'LEGACY':
- return js.boolean(!_options.soundNullSafety);
+ return _options.soundNullSafety
+ ? js.boolean(false)
+ // When running the new runtime type system with weak null
+ // safety this flag gets toggled when performing `is` and `as`
+ // checks. This allows DDC to produce optional warnings or
+ // errors when tests pass but would fail in sound null safety.
+ : runtimeCall('legacyTypeChecks');
case 'MINIFIED':
return js.boolean(false);
case 'NEW_RUNTIME_TYPES':
@@ -6563,16 +6569,24 @@
type.nullability == Nullability.nonNullable &&
type != _types.coreTypes.intNonNullableRawType) {
return js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
- } else {
- return _options.newRuntimeTypes
+ }
+
+ if (_options.newRuntimeTypes) {
+ // When using the new runtime type system with sound null safety we can
+ // call to the library directly. In weak mode we call a DDC only method
+ // that can optionally produce warnings or errors when the check passes
+ // but would fail with sound null safety.
+ return _options.soundNullSafety
? js.call('#.#(#)', [
_emitType(type),
_emitMemberName(js_ast.FixedNames.rtiIsField,
memberClass: rtiClass),
lhs
])
- : js.call('#.is(#)', [_emitType(type), lhs]);
+ : runtimeCall('is(#, #)', [lhs, _emitType(type)]);
}
+
+ return js.call('#.is(#)', [_emitType(type), lhs]);
}
@override
@@ -6649,15 +6663,21 @@
js_ast.Expression _emitCast(js_ast.Expression expr, DartType type) {
if (_types.isTop(type)) return expr;
-
- return _options.newRuntimeTypes
- ? js.call('#.#(#)', [
- _emitType(type),
- _emitMemberName(js_ast.FixedNames.rtiAsField,
- memberClass: rtiClass),
- expr
- ])
- : js.call('#.as(#)', [_emitType(type), expr]);
+ if (_options.newRuntimeTypes) {
+ // When using the new runtime type system with sound null safety we can
+ // call to the library directly. In weak mode we call a DDC only method
+ // that can optionally produce warnings or errors when the cast passes but
+ // would fail with sound null safety.
+ return _options.soundNullSafety
+ ? js.call('#.#(#)', [
+ _emitType(type),
+ _emitMemberName(js_ast.FixedNames.rtiAsField,
+ memberClass: rtiClass),
+ expr
+ ])
+ : runtimeCall('as(#, #)', [expr, _emitType(type)]);
+ }
+ return js.call('#.as(#)', [_emitType(type), expr]);
}
@override
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 97944df..1ddda26 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -456,12 +456,36 @@
@notNull
@JSExportName('is')
bool instanceOf(obj, type) {
- if (obj == null) {
- return _equalType(type, Null) ||
- _isTop(type) ||
- _jsInstanceOf(type, NullableType);
+ if (JS_GET_FLAG('NEW_RUNTIME_TYPES')) {
+ var testRti = JS<rti.Rti>('!', '#', type);
+ // When running without sound null safety is type tests are dispatched here
+ // to issue optional warnings/errors when the result is true but would be
+ // false with sound null safety.
+ var legacyErasedRecipe =
+ rti.Rti.getLegacyErasedRecipe(JS<rti.Rti>('!', '#', testRti));
+ var legacyErasedType = rti.findType(legacyErasedRecipe);
+ legacyTypeChecks = false;
+ var result = JS<bool>('bool', '#.#(#)', legacyErasedType,
+ JS_GET_NAME(JsGetName.RTI_FIELD_IS), obj);
+ legacyTypeChecks = true;
+ if (result) return true;
+ result =
+ JS('bool', '#.#(#)', testRti, JS_GET_NAME(JsGetName.RTI_FIELD_IS), obj);
+ if (result) {
+ // Type test passes put would fail with sound null safety.
+ var t1 = runtimeType(obj);
+ var t2 = rti.createRuntimeType(testRti);
+ _nullWarn('$t1 is not a subtype of $t2.');
+ }
+ return result;
+ } else {
+ if (obj == null) {
+ return _equalType(type, Null) ||
+ _isTop(type) ||
+ _jsInstanceOf(type, NullableType);
+ }
+ return isSubtypeOf(getReifiedType(obj), type);
}
- return isSubtypeOf(getReifiedType(obj), type);
}
/// General implementation of the Dart `as` operator.
@@ -477,12 +501,33 @@
// Check the null comparison cache to avoid emitting repeated warnings.
_nullWarnOnType(type);
return obj;
+ }
+ if (JS_GET_FLAG('NEW_RUNTIME_TYPES')) {
+ // When running without sound null safety casts are dispatched here to issue
+ // optional warnings/errors when casts pass but would fail with sound null
+ // safety.
+ var testRti = JS<rti.Rti>('!', '#', type);
+ var objRti = JS<rti.Rti>('!', '#', getReifiedType(obj));
+ var legacyErasedRecipe = rti.Rti.getLegacyErasedRecipe(testRti);
+ var legacyErasedType = rti.findType(legacyErasedRecipe);
+ legacyTypeChecks = false;
+ // Call `isSubtype()` to avoid throwing an error if it fails.
+ var result = rti.isSubtype(
+ JS_EMBEDDED_GLOBAL('', RTI_UNIVERSE), objRti, legacyErasedType);
+ legacyTypeChecks = true;
+ if (result) return obj;
+ // Perform the actual cast and allow the error to be thrown if it fails.
+ JS('bool', '#.#(#)', testRti, JS_GET_NAME(JsGetName.RTI_FIELD_AS), obj);
+ // Subtype check passes put would fail with sound null safety.
+ var t1 = runtimeType(obj);
+ var t2 = rti.createRuntimeType(testRti);
+ _nullWarn('$t1 is not a subtype of $t2.');
+ return obj;
} else {
var actual = getReifiedType(obj);
if (isSubtypeOf(actual, type)) return obj;
+ return castError(obj, type);
}
-
- return castError(obj, type);
}
bool test(bool? obj) {
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 46cd13d..9d3b79d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -10,7 +10,15 @@
import 'dart:_debugger' show stackTraceMapper, trackCall;
import 'dart:_foreign_helper'
- show JS, JS_CLASS_REF, JS_GET_FLAG, JS_GET_NAME, JSExportName, rest, spread;
+ show
+ JS,
+ JS_CLASS_REF,
+ JS_EMBEDDED_GLOBAL,
+ JS_GET_FLAG,
+ JS_GET_NAME,
+ JSExportName,
+ rest,
+ spread;
import 'dart:_interceptors'
show
JSArray,
@@ -37,9 +45,13 @@
import 'dart:_js_shared_embedded_names';
import 'dart:_rti' as rti
show
+ createRuntimeType,
constructorRtiCachePropertyName,
+ findType,
instanceType,
- interfaceTypeRecipePropertyName;
+ interfaceTypeRecipePropertyName,
+ isSubtype,
+ Rti;
export 'dart:_debugger' show getDynamicStats, clearDynamicStats, trackCall;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 3efd024..5d09d5e 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -16,6 +16,15 @@
_throwInvalidFlagError(String message) =>
throw UnsupportedError('Invalid flag combination.\n$message');
+/// When running the new runtime type system with weak null safety this flag
+/// gets toggled to change the behavior of the dart:_rti library when performing
+/// `is` and `as` checks.
+///
+/// This allows DDC to produce optional warnings or errors when tests pass but
+/// would fail in sound null safety.
+@notNull
+bool legacyTypeChecks = !compileTimeFlag("soundNullSafety");
+
@notNull
bool _weakNullSafetyWarnings = false;
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index bda0ac3..98690ef 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
@@ -313,7 +313,7 @@
abstract class Interceptor {
const Interceptor();
- bool operator ==(other) => identical(this, other);
+ bool operator ==(Object other) => identical(this, other);
int get hashCode => Primitives.objectHashCode(this);
@@ -369,7 +369,7 @@
class JSNull extends Interceptor implements Null {
const JSNull();
- bool operator ==(other) => identical(null, other);
+ external bool operator ==(Object other);
// Note: if you change this, also change the function [S].
String toString() => 'null';
diff --git a/tests/language/deferred/load_constants_test.dart b/tests/language/deferred/load_constants_test.dart
index 546b038..938da4a 100644
--- a/tests/language/deferred/load_constants_test.dart
+++ b/tests/language/deferred/load_constants_test.dart
@@ -28,32 +28,37 @@
// ^
// [cfe] Constant evaluation error:
// ^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.C]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.funtype]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.toplevel]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.C.staticfun]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
asyncEnd();
});
diff --git a/tests/language_2/deferred/load_constants_test.dart b/tests/language_2/deferred/load_constants_test.dart
index 45fb9aa..b96e944 100644
--- a/tests/language_2/deferred/load_constants_test.dart
+++ b/tests/language_2/deferred/load_constants_test.dart
@@ -30,32 +30,37 @@
// ^
// [cfe] Constant evaluation error:
// ^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.C]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.funtype]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.toplevel]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
Expect.throws(() => const [foo.C.staticfun]);
// ^
// [cfe] Constant evaluation error:
// ^^^^^^^^^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
// [cfe] 'foo' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.COLLECTION_ELEMENT_FROM_DEFERRED_LIBRARY
asyncEnd();
});
diff --git a/tools/VERSION b/tools/VERSION
index 4dcdfe1..a86b18c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 3
MINOR 0
PATCH 0
-PRERELEASE 4
+PRERELEASE 5
PRERELEASE_PATCH 0