Version 2.17.0-250.0.dev
Merge commit 'd4f0796619ebf8eaa0e181d5abb214fa000f20ae' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
index 59a5f61..69e49fe 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
@@ -6,6 +6,8 @@
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/filtering/fuzzy_matcher.dart';
+final _identifierPattern = RegExp(r'([_a-zA-Z][_a-zA-Z0-9]*)');
+
/// Filters and scores [suggestions] according to how well they match the
/// [pattern]. Sorts [suggestions] by the score, relevance, and name.
List<CompletionSuggestionBuilder> fuzzyFilterSort({
@@ -15,16 +17,18 @@
var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
double score(CompletionSuggestionBuilder suggestion) {
- var suggestionTextToMatch = suggestion.completion;
+ var textToMatch = suggestion.completion;
- if (suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
- var index = suggestionTextToMatch.indexOf(':');
- if (index != -1) {
- suggestionTextToMatch = suggestionTextToMatch.substring(0, index);
+ if (suggestion.kind == CompletionSuggestionKind.KEYWORD ||
+ suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
+ var identifier = _identifierPattern.matchAsPrefix(textToMatch)?.group(1);
+ if (identifier == null) {
+ return -1;
}
+ textToMatch = identifier;
}
- return matcher.score(suggestionTextToMatch);
+ return matcher.score(textToMatch);
}
var scored = suggestions
diff --git a/pkg/analysis_server/test/services/completion/dart/location/compilation_unit_test.dart b/pkg/analysis_server/test/services/completion/dart/location/compilation_unit_test.dart
new file mode 100644
index 0000000..d5130d5
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/location/compilation_unit_test.dart
@@ -0,0 +1,83 @@
+// 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 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../client/completion_driver_test.dart';
+import '../completion_check.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(CompilationUnitTest1);
+ defineReflectiveTests(CompilationUnitTest2);
+ });
+}
+
+@reflectiveTest
+class CompilationUnitTest1 extends AbstractCompletionDriverTest
+ with CompilationUnitTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version1;
+}
+
+@reflectiveTest
+class CompilationUnitTest2 extends AbstractCompletionDriverTest
+ with CompilationUnitTestCases {
+ @override
+ TestingCompletionProtocol get protocol => TestingCompletionProtocol.version2;
+}
+
+mixin CompilationUnitTestCases on AbstractCompletionDriverTest {
+ Future<void> test_definingUnit_export() async {
+ var response = await getTestCodeSuggestions('''
+exp^
+''');
+
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo("export '';")
+ ..kind.isKeyword
+ ..hasSelection(offset: 8),
+ ]);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.excludesAll([
+ (suggestion) => suggestion.completion.startsWith('import'),
+ ]);
+ }
+ }
+
+ Future<void> test_definingUnit_import() async {
+ var response = await getTestCodeSuggestions('''
+imp^
+''');
+
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo("import '';")
+ ..kind.isKeyword
+ ..hasSelection(offset: 8),
+ ]);
+
+ if (isProtocolVersion2) {
+ check(response).suggestions.excludesAll([
+ (suggestion) => suggestion.completion.startsWith('export'),
+ ]);
+ }
+ }
+
+ Future<void> test_definingUnit_part() async {
+ var response = await getTestCodeSuggestions('''
+par^
+''');
+
+ check(response).suggestions.includesAll([
+ (suggestion) => suggestion
+ ..completion.isEqualTo("part '';")
+ ..kind.isKeyword
+ ..hasSelection(offset: 6),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/location/test_all.dart b/pkg/analysis_server/test/services/completion/dart/location/test_all.dart
index 5fc5401..b0fe488 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/test_all.dart
@@ -5,6 +5,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'class_body_test.dart' as class_body;
+import 'compilation_unit_test.dart' as compilation_unit;
import 'enum_constant_test.dart' as enum_constant;
import 'enum_test.dart' as enum_;
import 'field_formal_parameter_test.dart' as field_formal_parameter;
@@ -15,6 +16,7 @@
void main() {
defineReflectiveSuite(() {
class_body.main();
+ compilation_unit.main();
enum_constant.main();
enum_.main();
field_formal_parameter.main();
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index da1e123..7c3815a 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -924,9 +924,14 @@
FunctionType? staticInvokeType;
/// Initialize a newly created binary expression.
- BinaryExpressionImpl(this._leftOperand, this.operator, this._rightOperand) {
- _becomeParentOf(_leftOperand);
- _becomeParentOf(_rightOperand);
+ BinaryExpressionImpl({
+ required ExpressionImpl leftOperand,
+ required this.operator,
+ required ExpressionImpl rightOperand,
+ }) : _leftOperand = leftOperand,
+ _rightOperand = rightOperand {
+ _becomeParentOf(leftOperand);
+ _becomeParentOf(rightOperand);
}
@override
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index b937129..7a31a07 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -93,11 +93,15 @@
Token awaitKeyword, Expression expression) =>
AwaitExpressionImpl(awaitKeyword, expression as ExpressionImpl);
+ @Deprecated('Use the constructor instead.')
@override
BinaryExpressionImpl binaryExpression(
Expression leftOperand, Token operator, Expression rightOperand) =>
- BinaryExpressionImpl(leftOperand as ExpressionImpl, operator,
- rightOperand as ExpressionImpl);
+ BinaryExpressionImpl(
+ leftOperand: leftOperand as ExpressionImpl,
+ operator: operator,
+ rightOperand: rightOperand as ExpressionImpl,
+ );
@override
BlockImpl block(
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index dd78df6..263dcde 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1696,10 +1696,10 @@
@override
bool visitBinaryExpression(covariant BinaryExpressionImpl node) {
if (identical(node.leftOperand, _oldNode)) {
- node.leftOperand = _newNode as Expression;
+ node.leftOperand = _newNode as ExpressionImpl;
return true;
} else if (identical(node.rightOperand, _oldNode)) {
- node.rightOperand = _newNode as Expression;
+ node.rightOperand = _newNode as ExpressionImpl;
return true;
}
return visitNode(node);
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 20996fa..612e610 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -60,23 +60,7 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/ast/ast.dart'
- show
- ArgumentListImpl,
- ClassDeclarationImpl,
- CompilationUnitImpl,
- ConstructorNameImpl,
- ConstructorSelectorImpl,
- EnumConstantArgumentsImpl,
- EnumConstantDeclarationImpl,
- EnumDeclarationImpl,
- ExtensionDeclarationImpl,
- ImportDirectiveImpl,
- MethodInvocationImpl,
- MixinDeclarationImpl,
- SimpleIdentifierImpl,
- TypeArgumentListImpl,
- TypeParameterImpl;
+import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/fasta/error_converter.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -739,10 +723,16 @@
identical("?..", operatorToken.stringValue)) {
doDotExpression(operatorToken);
} else {
- var right = pop() as Expression;
- var left = pop() as Expression;
+ var right = pop() as ExpressionImpl;
+ var left = pop() as ExpressionImpl;
reportErrorIfSuper(right);
- push(ast.binaryExpression(left, operatorToken, right));
+ push(
+ BinaryExpressionImpl(
+ leftOperand: left,
+ operator: operatorToken,
+ rightOperand: right,
+ ),
+ );
if (!enableTripleShift && operatorToken.type == TokenType.GT_GT_GT) {
var feature = ExperimentalFeatures.triple_shift;
handleRecoverableError(
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 34986e6..1264004 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -126,11 +126,6 @@
TokenFactory.tokenFromTypeAndString(TokenType.IDENTIFIER, "await"),
expression);
- static BinaryExpressionImpl binaryExpression(Expression leftOperand,
- TokenType operator, Expression rightOperand) =>
- astFactory.binaryExpression(
- leftOperand, TokenFactory.tokenFromType(operator), rightOperand);
-
static BlockImpl block([List<Statement> statements = const []]) =>
astFactory.block(
TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index df1bb2d..be75c39 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -270,13 +270,13 @@
}
BinaryExpression _readBinaryExpression() {
- var leftOperand = readNode() as Expression;
- var rightOperand = readNode() as Expression;
+ var leftOperand = readNode() as ExpressionImpl;
+ var rightOperand = readNode() as ExpressionImpl;
var operatorType = UnlinkedTokenType.values[_readByte()];
- var node = astFactory.binaryExpression(
- leftOperand,
- Tokens.fromType(operatorType),
- rightOperand,
+ var node = BinaryExpressionImpl(
+ leftOperand: leftOperand,
+ operator: Tokens.fromType(operatorType),
+ rightOperand: rightOperand,
);
node.staticElement = _reader.readElement() as MethodElement?;
node.staticInvokeType = _reader.readOptionalFunctionType();
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index d010025..a29e78d 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -5,14 +5,17 @@
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/parser_test_base.dart' show ParserTestCase;
+import '../../util/feature_sets.dart';
main() {
defineReflectiveSuite(() {
@@ -237,7 +240,7 @@
}
@reflectiveTest
-class IndexExpressionTest {
+class IndexExpressionTest extends _AstTest {
void test_inGetterContext_assignment_compound_left() {
IndexExpression expression = AstTestFactory.indexExpression(
target: AstTestFactory.identifier3("a"),
@@ -261,14 +264,10 @@
}
void test_inGetterContext_nonAssignment() {
- IndexExpression expression = AstTestFactory.indexExpression(
- target: AstTestFactory.identifier3("a"),
- index: AstTestFactory.identifier3("b"),
- );
- // a[b] + c
- AstTestFactory.binaryExpression(
- expression, TokenType.PLUS, AstTestFactory.identifier3("c"));
- expect(expression.inGetterContext(), isTrue);
+ var node = _parseStringToNode<IndexExpression>(r'''
+var v = ^a[b] + c;
+''');
+ expect(node.inGetterContext(), isTrue);
}
void test_inSetterContext_assignment_compound_left() {
@@ -316,14 +315,10 @@
}
void test_inSetterContext_nonAssignment() {
- IndexExpression expression = AstTestFactory.indexExpression(
- target: AstTestFactory.identifier3("a"),
- index: AstTestFactory.identifier3("b"),
- );
- AstTestFactory.binaryExpression(
- expression, TokenType.PLUS, AstTestFactory.identifier3("c"));
- // a[b] + cc
- expect(expression.inSetterContext(), isFalse);
+ var node = _parseStringToNode<IndexExpression>(r'''
+var v = ^a[b] + c;
+''');
+ expect(node.inSetterContext(), isFalse);
}
void test_inSetterContext_postfix_bang() {
@@ -1053,7 +1048,7 @@
}
@reflectiveTest
-class SimpleIdentifierTest extends ParserTestCase {
+class SimpleIdentifierTest extends _AstTest {
void test_inGetterContext() {
for (_WrapperKind wrapper in _WrapperKind.values) {
for (_AssignmentKind assignment in _AssignmentKind.values) {
@@ -1200,8 +1195,8 @@
SimpleIdentifier _createIdentifier(
_WrapperKind wrapper, _AssignmentKind assignment) {
- SimpleIdentifier identifier = AstTestFactory.identifier3("a");
- Expression expression = identifier;
+ var identifier = AstTestFactory.identifier3("a");
+ ExpressionImpl expression = identifier;
while (true) {
if (wrapper == _WrapperKind.PREFIXED_LEFT) {
expression = AstTestFactory.identifier(
@@ -1221,8 +1216,11 @@
}
while (true) {
if (assignment == _AssignmentKind.BINARY) {
- AstTestFactory.binaryExpression(
- expression, TokenType.PLUS, AstTestFactory.identifier3("_"));
+ BinaryExpressionImpl(
+ leftOperand: expression,
+ operator: TokenFactory.tokenFromType(TokenType.PLUS),
+ rightOperand: AstTestFactory.identifier3("_"),
+ );
} else if (assignment == _AssignmentKind.COMPOUND_LEFT) {
AstTestFactory.assignmentExpression(
expression, TokenType.PLUS_EQ, AstTestFactory.identifier3("_"));
@@ -1787,6 +1785,37 @@
String toString() => name;
}
+class _AstTest {
+ T _parseStringToNode<T extends AstNode>(String codeWithMark) {
+ var offset = codeWithMark.indexOf('^');
+ expect(offset, isNot(equals(-1)), reason: 'missing ^');
+
+ var nextOffset = codeWithMark.indexOf('^', offset + 1);
+ expect(nextOffset, equals(-1), reason: 'too many ^');
+
+ var codeBefore = codeWithMark.substring(0, offset);
+ var codeAfter = codeWithMark.substring(offset + 1);
+ var code = codeBefore + codeAfter;
+
+ var parseResult = parseString(
+ content: code,
+ featureSet: FeatureSets.latestWithExperiments,
+ );
+
+ var node = NodeLocator2(offset).searchWithin(parseResult.unit);
+ if (node == null) {
+ throw StateError('No node at $offset:\n$code');
+ }
+
+ var result = node.thisOrAncestorOfType<T>();
+ if (result == null) {
+ throw StateError('No node of $T at $offset:\n$code');
+ }
+
+ return result;
+ }
+}
+
class _WrapperKind {
static const _WrapperKind PREFIXED_LEFT = _WrapperKind('PREFIXED_LEFT', 0);
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 bb1b5fb..2aac19c 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
@@ -93,20 +93,23 @@
}
void test_visitBinaryExpression() {
+ var findNode = _parseStringToFindNode(r'''
+var v = a + b;
+''');
_assertSource(
- "a + b",
- AstTestFactory.binaryExpression(AstTestFactory.identifier3("a"),
- TokenType.PLUS, AstTestFactory.identifier3("b")));
+ 'a + b',
+ findNode.binary('a + b'),
+ );
}
void test_visitBinaryExpression_precedence() {
- var a = AstTestFactory.identifier3('a');
- var b = AstTestFactory.identifier3('b');
- var c = AstTestFactory.identifier3('c');
+ var findNode = _parseStringToFindNode(r'''
+var v = a * (b + c);
+''');
_assertSource(
- 'a * (b + c)',
- AstTestFactory.binaryExpression(a, TokenType.STAR,
- AstTestFactory.binaryExpression(b, TokenType.PLUS, c)));
+ 'a * (b + c)',
+ findNode.binary('a *'),
+ );
}
void test_visitBlock_empty() {
@@ -2787,12 +2790,13 @@
}
void test_visitPrefixExpression_precedence() {
- var a = AstTestFactory.identifier3('a');
- var b = AstTestFactory.identifier3('b');
+ var findNode = _parseStringToFindNode(r'''
+var v = !(a == b);
+''');
_assertSource(
- '!(a == b)',
- AstTestFactory.prefixExpression(TokenType.BANG,
- AstTestFactory.binaryExpression(a, TokenType.EQ_EQ, b)));
+ '!(a == b)',
+ findNode.prefix('!'),
+ );
}
void test_visitPropertyAccess() {
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index da1fbe1..4d58ce5 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -114,16 +114,8 @@
"Dynamic access of 'name'.": 1,
"Dynamic invocation of '-'.": 1
},
- "pkg/js_ast/lib/src/builder.dart": {
- "Dynamic invocation of 'call'.": 2
- },
"pkg/js_ast/lib/src/template.dart": {
- "Dynamic access of 'keys'.": 1,
- "Dynamic access of 'length'.": 1,
"Dynamic invocation of '[]'.": 9,
- "Dynamic invocation of 'containsKey'.": 2,
- "Dynamic invocation of 'join'.": 1,
- "Dynamic invocation of 'toStatement'.": 3,
- "Dynamic invocation of 'where'.": 1
+ "Dynamic invocation of 'toStatement'.": 1
}
}
\ No newline at end of file
diff --git a/pkg/dev_compiler/lib/src/js_ast/characters.dart b/pkg/dev_compiler/lib/src/js_ast/characters.dart
index 1ce0d48..e3382c3 100644
--- a/pkg/dev_compiler/lib/src/js_ast/characters.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/characters.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
const int $EOF = 0;
const int $STX = 2;
const int $BS = 8;
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 70ff407..cb6c11d 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
// ignore_for_file: always_declare_return_types
// ignore_for_file: always_require_non_null_named_parameters
// ignore_for_file: omit_local_variable_types
@@ -90,7 +88,6 @@
T visitExportDeclaration(ExportDeclaration node);
T visitExportClause(ExportClause node);
T visitNameSpecifier(NameSpecifier node);
- T visitModule(Module node);
T visitComment(Comment node);
T visitCommentExpression(CommentExpression node);
@@ -256,8 +253,6 @@
T visitExportClause(ExportClause node) => visitNode(node);
@override
T visitNameSpecifier(NameSpecifier node) => visitNode(node);
- @override
- T visitModule(Module node) => visitNode(node);
T visitInterpolatedNode(InterpolatedNode node) => visitNode(node);
@@ -322,7 +317,7 @@
abstract class Node {
/// Sets the source location of this node. For performance reasons, we allow
/// setting this after construction.
- Object sourceInformation;
+ Object? sourceInformation;
T accept<T>(NodeVisitor<T> visitor);
void visitChildren(NodeVisitor visitor);
@@ -371,7 +366,7 @@
// TODO(jmesserly): rename to Module.
class Program extends Node {
/// Script tag hash-bang, e.g. `#!/usr/bin/env node`.
- final String scriptTag;
+ final String? scriptTag;
/// Top-level statements in the program.
final List<ModuleItem> body;
@@ -379,7 +374,7 @@
/// The module's own name.
///
/// This is not used in ES6, but is provided to allow module lowering.
- final String name;
+ final String? name;
Program(this.body, {this.scriptTag, this.name});
@@ -439,9 +434,8 @@
/// True to preserve this [Block] for scoping reasons.
final bool isScope;
- Block(this.statements, {this.isScope = false}) {
- assert(statements.every((s) => s is Statement));
- }
+ Block(this.statements, {this.isScope = false});
+
Block.empty()
: statements = <Statement>[],
isScope = false;
@@ -516,13 +510,13 @@
final Statement otherwise;
If(this.condition, this.then, this.otherwise);
- If.noElse(this.condition, this.then) : this.otherwise = null;
+ If.noElse(this.condition, this.then) : this.otherwise = EmptyStatement();
@override
bool get alwaysReturns =>
hasElse && then.alwaysReturns && otherwise.alwaysReturns;
- bool get hasElse => otherwise != null;
+ bool get hasElse => otherwise is! EmptyStatement;
@override
T accept<T>(NodeVisitor<T> visitor) => visitor.visitIf(this);
@@ -531,7 +525,7 @@
void visitChildren(NodeVisitor visitor) {
condition.accept(visitor);
then.accept(visitor);
- otherwise?.accept(visitor);
+ otherwise.accept(visitor);
}
@override
@@ -544,9 +538,9 @@
}
class For extends Loop {
- final Expression init;
- final Expression condition;
- final Expression update;
+ final Expression? init;
+ final Expression? condition;
+ final Expression? update;
For(this.init, this.condition, this.update, Statement body) : super(body);
@@ -646,7 +640,8 @@
}
class Continue extends Statement {
- final String targetLabel; // Can be null.
+ /// Name of the label L for `continue L;` or `null` for `continue;`.
+ final String? targetLabel;
Continue(this.targetLabel);
@@ -660,7 +655,8 @@
}
class Break extends Statement {
- final String targetLabel; // Can be null.
+ /// Name of the label L for `break L;` or `null` for `break;`.
+ final String? targetLabel;
Break(this.targetLabel);
@@ -674,7 +670,7 @@
}
class Return extends Statement {
- final Expression value; // Can be null.
+ final Expression? value;
Return([this.value]);
@@ -736,8 +732,8 @@
class Try extends Statement {
final Block body;
- final Catch catchPart; // Can be null if [finallyPart] is non-null.
- final Block finallyPart; // Can be null if [catchPart] is non-null.
+ final Catch? catchPart; // Can be null if [finallyPart] is non-null.
+ final Block? finallyPart; // Can be null if [catchPart] is non-null.
Try(this.body, this.catchPart, this.finallyPart) {
assert(catchPart != null || finallyPart != null);
@@ -912,11 +908,11 @@
Expression();
factory Expression.binary(List<Expression> exprs, String op) {
- Expression comma;
+ Expression? comma;
for (var node in exprs) {
comma = (comma == null) ? node : Binary(op, comma, node);
}
- return comma;
+ return comma!;
}
int get precedenceLevel;
@@ -931,7 +927,7 @@
ExpressionStatement(Yield(this, star: star));
Expression toVoidExpression() => this;
- Expression toAssignExpression(Expression left, [String op]) =>
+ Expression toAssignExpression(Expression left, [String? op]) =>
Assignment.compound(left, op, this);
// TODO(jmesserly): make this work for more cases?
@@ -963,7 +959,9 @@
class VariableDeclarationList extends Expression {
/// The `var` or `let` or `const` keyword used for this variable declaration
/// list.
- final String keyword;
+ ///
+ /// Can be null in the case of non-static field declarations.
+ final String? keyword;
final List<VariableInitialization> declarations;
VariableDeclarationList(this.keyword, this.declarations);
@@ -1000,10 +998,12 @@
class Assignment extends Expression {
final Expression leftHandSide;
- final String op; // Null, if the assignment is not compound.
+ final String? op; // `null` if the assignment is not compound.
final Expression value;
Assignment(this.leftHandSide, this.value) : op = null;
+
+ // If `this.op == null` this will be a non-compound assignment.
Assignment.compound(this.leftHandSide, this.op, this.value);
@override
@@ -1017,7 +1017,7 @@
@override
void visitChildren(NodeVisitor visitor) {
leftHandSide.accept(visitor);
- value?.accept(visitor);
+ value.accept(visitor);
}
@override
@@ -1026,9 +1026,9 @@
class VariableInitialization extends Expression {
final VariableBinding declaration;
- final Expression value; // May be null.
+ // The initializing value can be missing, e.g. for `a` in `var a, b=1;`.
+ final Expression? value;
- /// [value] may be null.
VariableInitialization(this.declaration, this.value);
@override
@@ -1067,20 +1067,16 @@
/// console.log(foo); // "bar"
///
// TODO(jmesserly): parser does not support this feature.
- final Expression property;
-
- final BindingPattern structure;
- final Expression defaultValue;
+ final Expression? property;
+ final BindingPattern? structure;
+ final Expression? defaultValue;
DestructuredVariable(
- {this.name, this.property, this.structure, this.defaultValue}) {
- assert(name != null || structure != null);
- }
+ {required this.name, this.property, this.structure, this.defaultValue});
@override
bool shadows(Set<String> names) {
- return (name?.shadows(names) ?? false) ||
- (structure?.shadows(names) ?? false);
+ return name.shadows(names) || (structure?.shadows(names) ?? false);
}
@override
@@ -1088,7 +1084,7 @@
visitor.visitDestructuredVariable(this);
@override
void visitChildren(NodeVisitor visitor) {
- name?.accept(visitor);
+ name.accept(visitor);
structure?.accept(visitor);
defaultValue?.accept(visitor);
}
@@ -1850,7 +1846,7 @@
// TODO(jmesserly): parser does not support this yet.
class Yield extends Expression {
- final Expression value; // Can be null.
+ final Expression? value;
/// Whether this yield expression is a `yield*` that iterates each item in
/// [value].
@@ -1888,7 +1884,7 @@
class ClassExpression extends Expression {
final Identifier name;
- final Expression heritage; // Can be null.
+ final Expression? heritage;
final List<Method> methods;
ClassExpression(this.name, this.heritage, this.methods);
@@ -2215,26 +2211,24 @@
abstract class ModuleItem extends Node {}
class ImportDeclaration extends ModuleItem {
- final Identifier defaultBinding; // Can be null.
+ final Identifier? defaultBinding;
- // Can be null, a single specifier of `* as name`, or a list.
- final List<NameSpecifier> namedImports;
+ // Can be `null`, a single specifier of `* as name`, or a list.
+ final List<NameSpecifier>? namedImports;
final LiteralString from;
- ImportDeclaration({this.defaultBinding, this.namedImports, this.from}) {
- assert(from != null);
- }
+ ImportDeclaration(
+ {this.defaultBinding, this.namedImports, required this.from});
/// The `import "name.js"` form of import.
ImportDeclaration.all(LiteralString module) : this(from: module);
/// If this import has `* as name` returns the name, otherwise null.
- Identifier get importStarAs {
- if (namedImports != null &&
- namedImports.length == 1 &&
- namedImports[0].isStar) {
- return namedImports[0].asName;
+ Identifier? get importStarAs {
+ var imports = namedImports;
+ if (imports != null && imports.length == 1 && imports[0].isStar) {
+ return imports[0].asName;
}
return null;
}
@@ -2243,8 +2237,9 @@
T accept<T>(NodeVisitor<T> visitor) => visitor.visitImportDeclaration(this);
@override
void visitChildren(NodeVisitor visitor) {
- if (namedImports != null) {
- for (NameSpecifier name in namedImports) {
+ var imports = namedImports;
+ if (imports != null) {
+ for (NameSpecifier name in imports) {
name.accept(visitor);
}
}
@@ -2279,7 +2274,7 @@
/// if this is an `export *`.
///
/// This can be useful for lowering to other module formats.
- List<NameSpecifier> get exportedNames {
+ List<NameSpecifier>? get exportedNames {
if (isDefault) return [NameSpecifier(Identifier('default'))];
var exported = this.exported;
@@ -2310,7 +2305,7 @@
class ExportClause extends Node {
final List<NameSpecifier> exports;
- final LiteralString from; // Can be null.
+ final LiteralString? from;
ExportClause(this.exports, {this.from});
@@ -2337,8 +2332,8 @@
/// An import or export specifier.
class NameSpecifier extends Node {
- final Identifier name;
- final Identifier asName; // Can be null.
+ final Identifier? name;
+ final Identifier? asName;
NameSpecifier(this.name, {this.asName});
NameSpecifier.star() : this(null);
@@ -2353,26 +2348,3 @@
@override
NameSpecifier _clone() => NameSpecifier(name, asName: asName);
}
-
-// TODO(jmesserly): should this be related to [Program]?
-class Module extends Node {
- /// The module's name.
- // TODO(jmesserly): this is not declared in ES6, but is known by the loader.
- // We use this because some ES5 desugarings require it.
- final String name;
-
- final List<ModuleItem> body;
- Module(this.body, {this.name});
-
- @override
- T accept<T>(NodeVisitor<T> visitor) => visitor.visitModule(this);
- @override
- void visitChildren(NodeVisitor visitor) {
- for (ModuleItem item in body) {
- item.accept(visitor);
- }
- }
-
- @override
- Module _clone() => Module(body);
-}
diff --git a/pkg/dev_compiler/lib/src/js_ast/precedence.dart b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
index 50f69ed..f149dc2 100644
--- a/pkg/dev_compiler/lib/src/js_ast/precedence.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/precedence.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
const EXPRESSION = 0;
// TODO(nshahan) No longer used for the spread operator.
// All precedence levels need to be updated to be more accurate.
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index 1c5767b..adddaae 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
// ignore_for_file: always_declare_return_types
// ignore_for_file: library_prefixes
// ignore_for_file: omit_local_variable_types
@@ -58,7 +56,7 @@
/// Callback after printing the last character representing [node].
void exitNode(Node node) {}
- Printer printer;
+ late Printer printer;
}
/// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
@@ -100,7 +98,7 @@
static final expressionContinuationRegExp = RegExp(r'^[-+([]');
Printer(JavaScriptPrintingOptions options, JavaScriptPrintingContext context,
- {LocalNamer localNamer})
+ {LocalNamer? localNamer})
: options = options,
context = context,
shouldCompressOutput = options.shouldCompressOutput,
@@ -110,7 +108,7 @@
}
static LocalNamer determineRenamer(
- LocalNamer localNamer, JavaScriptPrintingOptions options) {
+ LocalNamer? localNamer, JavaScriptPrintingOptions options) {
if (localNamer != null) return localNamer;
return (options.shouldCompressOutput && options.minifyLocalVariables)
? MinifyRenamer()
@@ -148,9 +146,9 @@
if (!shouldCompressOutput) out(" ");
}
- String lastAddedString;
+ String lastAddedString = '\u0000';
+
int get lastCharCode {
- if (lastAddedString == null) return 0;
assert(lastAddedString.isNotEmpty);
return lastAddedString.codeUnitAt(lastAddedString.length - 1);
}
@@ -236,7 +234,7 @@
}
visitCommaSeparated(List<Expression> nodes, int hasRequiredType,
- {bool newInForInit, bool newAtStatementBegin}) {
+ {required bool newInForInit, required bool newAtStatementBegin}) {
for (int i = 0; i < nodes.length; i++) {
if (i != 0) {
atStatementBegin = false;
@@ -260,10 +258,11 @@
visitAll(program.body);
}
- bool blockBody(Node body, {bool needsSeparation, bool needsNewline}) {
+ bool blockBody(Node body,
+ {required bool needsSeparation, required bool needsNewline}) {
if (body is Block) {
spaceOut();
- blockOut(body, false, needsNewline);
+ blockOut(body, shouldIndent: false, needsNewline: needsNewline);
return true;
}
if (shouldCompressOutput && needsSeparation) {
@@ -290,7 +289,8 @@
}
}
- void blockOut(Block node, bool shouldIndent, bool needsNewline) {
+ void blockOut(Block node,
+ {required bool shouldIndent, required bool needsNewline}) {
if (shouldIndent) indent();
context.enterNode(node);
out("{");
@@ -306,7 +306,7 @@
@override
visitBlock(Block block) {
- blockOut(block, true, true);
+ blockOut(block, shouldIndent: true, needsNewline: true);
}
@override
@@ -387,19 +387,19 @@
spaceOut();
out("(");
if (loop.init != null) {
- visitNestedExpression(loop.init, EXPRESSION,
+ visitNestedExpression(loop.init!, EXPRESSION,
newInForInit: true, newAtStatementBegin: false);
}
out(";");
if (loop.condition != null) {
spaceOut();
- visitNestedExpression(loop.condition, EXPRESSION,
+ visitNestedExpression(loop.condition!, EXPRESSION,
newInForInit: false, newAtStatementBegin: false);
}
out(";");
if (loop.update != null) {
spaceOut();
- visitNestedExpression(loop.update, EXPRESSION,
+ visitNestedExpression(loop.update!, EXPRESSION,
newInForInit: false, newAtStatementBegin: false);
}
out(")");
@@ -491,7 +491,7 @@
} else {
outIndent("return");
pendingSpace = true;
- visitNestedExpression(node.value, EXPRESSION,
+ visitNestedExpression(node.value!, EXPRESSION,
newInForInit: false, newAtStatementBegin: false);
}
outSemicolonLn();
@@ -524,12 +524,12 @@
outIndent("try");
blockBody(node.body, needsSeparation: true, needsNewline: false);
if (node.catchPart != null) {
- visit(node.catchPart);
+ visit(node.catchPart!);
}
if (node.finallyPart != null) {
spaceOut();
out("finally");
- blockBody(node.finallyPart, needsSeparation: true, needsNewline: true);
+ blockBody(node.finallyPart!, needsSeparation: true, needsNewline: true);
} else {
lineOut();
}
@@ -593,7 +593,7 @@
blockBody(node.body, needsSeparation: false, needsNewline: true);
}
- void functionOut(Fun fun, Identifier name) {
+ void functionOut(Fun fun, Identifier? name) {
out("function");
if (fun.isGenerator) out("*");
if (name != null) {
@@ -604,10 +604,10 @@
}
localNamer.enterScope(fun);
out("(");
- if (fun.params != null) {
- visitCommaSeparated(fun.params, PRIMARY,
- newInForInit: false, newAtStatementBegin: false);
- }
+
+ visitCommaSeparated(fun.params, PRIMARY,
+ newInForInit: false, newAtStatementBegin: false);
+
out(")");
switch (fun.asyncModifier) {
case const AsyncModifier.sync():
@@ -637,7 +637,7 @@
}
visitNestedExpression(Expression node, int requiredPrecedence,
- {bool newInForInit, bool newAtStatementBegin}) {
+ {required bool newInForInit, required bool newAtStatementBegin}) {
int nodePrecedence = node.precedenceLevel;
bool needsParentheses =
// a - (b + c).
@@ -669,7 +669,7 @@
visitVariableDeclarationList(VariableDeclarationList list) {
// Note: keyword can be null for non-static field declarations.
if (list.keyword != null) {
- out(list.keyword);
+ out(list.keyword!);
out(" ");
}
visitCommaSeparated(list.declarations, ASSIGNMENT,
@@ -696,16 +696,15 @@
visitDestructuredVariable(DestructuredVariable node) {
var name = node.name;
var property = node.property;
- if (name != null) {
- visit(node.name);
- } else if (property != null) {
+ visit(name);
+ if (property != null) {
out("[");
- visit(node.property);
+ visit(property);
out("]");
}
var structure = node.structure;
if (structure != null) {
- if (name != null || property != null) {
+ if (property != null) {
out(":");
spaceOut();
}
@@ -730,26 +729,24 @@
visitAssignment(Assignment assignment) {
visitNestedExpression(assignment.leftHandSide, LEFT_HAND_SIDE,
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
- if (assignment.value != null) {
- spaceOut();
- String op = assignment.op;
- if (op != null) out(op);
- out("=");
- spaceOut();
- visitNestedExpression(assignment.value, ASSIGNMENT,
- newInForInit: inForInit, newAtStatementBegin: false);
- }
+ spaceOut();
+ String? op = assignment.op;
+ if (op != null) out(op);
+ out("=");
+ spaceOut();
+ visitNestedExpression(assignment.value, ASSIGNMENT,
+ newInForInit: inForInit, newAtStatementBegin: false);
}
@override
- visitVariableInitialization(VariableInitialization init) {
- visitNestedExpression(init.declaration, LEFT_HAND_SIDE,
+ visitVariableInitialization(VariableInitialization initialization) {
+ visitNestedExpression(initialization.declaration, LEFT_HAND_SIDE,
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
- if (init.value != null) {
+ if (initialization.value != null) {
spaceOut();
out("=");
spaceOut();
- visitNestedExpression(init.value, ASSIGNMENT,
+ visitNestedExpression(initialization.value!, ASSIGNMENT,
newInForInit: inForInit, newAtStatementBegin: false);
}
}
@@ -874,6 +871,8 @@
rightPrecedenceRequirement = UNARY;
break;
default:
+ leftPrecedenceRequirement = EXPRESSION;
+ rightPrecedenceRequirement = EXPRESSION;
context.error("Forgot operator: $op");
}
@@ -932,7 +931,7 @@
out(yield.star ? "yield*" : "yield");
if (yield.value == null) return;
out(" ");
- visitNestedExpression(yield.value, yield.precedenceLevel,
+ visitNestedExpression(yield.value!, yield.precedenceLevel,
newInForInit: inForInit, newAtStatementBegin: false);
}
@@ -1195,7 +1194,7 @@
visit(node.name);
if (node.heritage != null) {
out(' extends ');
- visit(node.heritage);
+ visit(node.heritage!);
}
spaceOut();
if (node.methods.isNotEmpty) {
@@ -1233,10 +1232,8 @@
var fun = node.function;
localNamer.enterScope(fun);
out("(");
- if (fun.params != null) {
- visitCommaSeparated(fun.params, SPREAD,
- newInForInit: false, newAtStatementBegin: false);
- }
+ visitCommaSeparated(fun.params, SPREAD,
+ newInForInit: false, newAtStatementBegin: false);
out(")");
// TODO(jmesserly): async modifiers
if (fun.body.statements.isEmpty) {
@@ -1244,7 +1241,7 @@
out("{}");
} else {
spaceOut();
- blockOut(fun.body, false, false);
+ blockOut(fun.body, shouldIndent: false, needsNewline: false);
}
localNamer.leaveScope();
}
@@ -1281,13 +1278,15 @@
indent();
out('import ');
if (node.defaultBinding != null) {
- visit(node.defaultBinding);
+ visit(node.defaultBinding!);
if (node.namedImports != null) {
out(',');
spaceOut();
}
}
- nameSpecifierListOut(node.namedImports, false);
+ if (node.namedImports != null) {
+ nameSpecifierListOut(node.namedImports!, false);
+ }
fromClauseOut(node.from);
outSemicolonLn();
}
@@ -1305,13 +1304,13 @@
@override
visitExportClause(ExportClause node) {
nameSpecifierListOut(node.exports, true);
- fromClauseOut(node.from);
+ if (node.from != null) {
+ fromClauseOut(node.from!);
+ }
}
nameSpecifierListOut(List<NameSpecifier> names, bool export) {
- if (names == null) return;
-
- if (names.length == 1 && names[0].name.name == '*') {
+ if (names.length == 1 && names[0].name!.name == '*') {
nameSpecifierOut(names[0], export);
return;
}
@@ -1330,11 +1329,9 @@
}
fromClauseOut(LiteralString from) {
- if (from != null) {
- out(' from');
- spaceOut();
- out("'${from.valueWithoutQuotes}.js'");
- }
+ out(' from');
+ spaceOut();
+ out("'${from.valueWithoutQuotes}.js'");
}
/// This is unused, see [nameSpecifierOut].
@@ -1347,11 +1344,13 @@
if (node.isStar) {
out('*');
} else {
- var localName = localNamer.getName(node.name);
+ assert(node.name != null);
+ var nodeName = node.name!;
+ var localName = localNamer.getName(nodeName);
if (node.asName == null) {
// If our local was renamed, generate an implicit "as".
// This is a convenience feature so imports and exports can be renamed.
- var name = node.name.name;
+ var name = nodeName.name;
if (localName != name) {
out(export ? localName : name);
out(' as ');
@@ -1363,16 +1362,11 @@
}
if (node.asName != null) {
out(' as ');
- visitIdentifier(node.asName);
+ visitIdentifier(node.asName!);
}
}
@override
- visitModule(Module node) {
- visitAll(node.body);
- }
-
- @override
visitLiteralExpression(LiteralExpression node) {
out(node.template);
}
@@ -1467,12 +1461,10 @@
void collectVarsInFunction(FunctionExpression fun) {
if (!nested) {
nested = true;
- if (fun.params != null) {
- for (var param in fun.params) {
- // TODO(jmesserly): add ES6 support. Currently not needed because
- // dart2js does not emit ES6 rest param or destructuring.
- params.add((param as Identifier).name);
- }
+ for (var param in fun.params) {
+ // TODO(jmesserly): add ES6 support. Currently not needed because
+ // dart2js does not emit ES6 rest param or destructuring.
+ params.add((param as Identifier).name);
}
fun.body.accept(this);
nested = false;
@@ -1587,9 +1579,9 @@
@override
bool visitTry(Try node) {
if (node.finallyPart != null) {
- return node.finallyPart.accept(this);
+ return node.finallyPart!.accept(this);
} else {
- return node.catchPart.accept(this);
+ return node.catchPart!.accept(this);
}
}
@@ -1782,7 +1774,7 @@
@override
visitDestructuredVariable(DestructuredVariable node) {
var name = node.name;
- if (name is Identifier) _scanVariableBinding(name);
+ _scanVariableBinding(name);
super.visitDestructuredVariable(node);
}
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index 792d32b..71b7662 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -774,9 +774,6 @@
return (a) => Await(makeExpr(a));
}
- // Note: these are not supported yet in the interpolation grammar.
- @override
- Instantiator visitModule(Module node) => throw UnimplementedError();
@override
Instantiator visitNameSpecifier(NameSpecifier node) =>
throw UnimplementedError();
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index adb167d..bd0d2d8 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -4379,8 +4379,12 @@
@override
js_ast.Statement visitIfStatement(IfStatement node) {
- return js_ast.If(_visitTest(node.condition), _visitScope(node.then),
- _visitScope(node.otherwise));
+ var condition = _visitTest(node.condition);
+ var then = _visitScope(node.then);
+ if (node.otherwise != null) {
+ return js_ast.If(condition, then, _visitScope(node.otherwise));
+ }
+ return js_ast.If.noElse(condition, then);
}
/// Visits a statement, and ensures the resulting AST handles block scope
diff --git a/pkg/js_ast/lib/src/builder.dart b/pkg/js_ast/lib/src/builder.dart
index d5771ee..cd92fab 100644
--- a/pkg/js_ast/lib/src/builder.dart
+++ b/pkg/js_ast/lib/src/builder.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.15
+
/// Utilities for building JS ASTs at runtime. Contains a builder class and a
/// parser that parses part of the language.
library js_ast.builder;
@@ -198,19 +200,19 @@
/// '#' signs.
Expression call(String source, [var arguments]) {
Template template = _findExpressionTemplate(source);
- if (arguments == null) return template.instantiate([]);
+ arguments ??= [];
// We allow a single argument to be given directly.
if (arguments is! List && arguments is! Map) arguments = [arguments];
- return template.instantiate(arguments);
+ return template.instantiate(arguments) as Expression;
}
/// Parses a JavaScript Statement, otherwise just like [call].
Statement statement(String source, [var arguments]) {
Template template = _findStatementTemplate(source);
- if (arguments == null) return template.instantiate([]);
+ arguments ??= [];
// We allow a single argument to be given directly.
if (arguments is! List && arguments is! Map) arguments = [arguments];
- return template.instantiate(arguments);
+ return template.instantiate(arguments) as Statement;
}
/// Parses JavaScript written in the `JS` foreign instruction.
@@ -229,7 +231,7 @@
}
Template _findExpressionTemplate(String source) {
- Template template = templateManager.lookupExpressionTemplate(source);
+ Template? template = templateManager.lookupExpressionTemplate(source);
if (template == null) {
MiniJsParser parser = MiniJsParser(source);
Expression expression = parser.expression();
@@ -239,7 +241,7 @@
}
Template _findStatementTemplate(String source) {
- Template template = templateManager.lookupStatementTemplate(source);
+ Template? template = templateManager.lookupStatementTemplate(source);
if (template == null) {
MiniJsParser parser = MiniJsParser(source);
Statement statement = parser.statement();
@@ -272,11 +274,11 @@
/// Create an Expression template which has [ast] as the result. This is used
/// to wrap a generated AST in a zero-argument Template so it can be passed to
/// context that expects a template.
- Template expressionTemplateYielding(Node ast) {
+ Template expressionTemplateYielding(Expression ast) {
return Template.withExpressionResult(ast);
}
- Template statementTemplateYielding(Node ast) {
+ Template statementTemplateYielding(Statement ast) {
return Template.withStatementResult(ast);
}
@@ -739,7 +741,7 @@
if (lastToken == '=>') {
lastCategory = ARROW;
} else {
- int binaryPrecedence = BINARY_PRECEDENCE[lastToken];
+ int? binaryPrecedence = BINARY_PRECEDENCE[lastToken];
if (binaryPrecedence == null &&
!UNARY_OPERATORS.contains(lastToken)) {
error("Unknown operator");
@@ -791,7 +793,7 @@
return false;
}
- void error(message) {
+ Never error(message) {
throw MiniJsParserError(this, message);
}
@@ -850,7 +852,7 @@
expectCategory(COMMA);
}
return ArrayInitializer(values);
- } else if (last != null && last.startsWith("/")) {
+ } else if (last.startsWith("/")) {
String regexp = getRegExp(lastPosition);
getToken();
String flags = lastToken;
@@ -865,7 +867,6 @@
return expression;
} else {
error("Expected primary expression");
- return null;
}
}
@@ -877,7 +878,7 @@
return parseFun();
}
- Expression parseFun() {
+ Fun parseFun() {
List<Parameter> params = [];
expectCategory(LPAREN);
if (!acceptCategory(RPAREN)) {
@@ -951,7 +952,7 @@
Expression value = parseAssignment();
return Property(propertyName, value);
} else {
- Expression fun = parseFun();
+ final fun = parseFun();
return MethodDefinition(propertyName, fun);
}
}
@@ -1066,27 +1067,29 @@
Expression parseBinary(int maxPrecedence) {
Expression lhs = parseUnaryLow();
- int minPrecedence;
- String lastSymbol;
- Expression rhs; // This is null first time around.
+ Expression? rhs; // This is null first time around.
+ late int minPrecedence;
+ late String lastSymbol;
+
while (true) {
- String symbol = lastToken;
- if (lastCategory != SYMBOL ||
- !BINARY_PRECEDENCE.containsKey(symbol) ||
- BINARY_PRECEDENCE[symbol] > maxPrecedence) {
- break;
- }
+ final symbol = lastToken;
+ if (lastCategory != SYMBOL) break;
+ final symbolPrecedence = BINARY_PRECEDENCE[symbol];
+ if (symbolPrecedence == null) break;
+ if (symbolPrecedence > maxPrecedence) break;
+
expectCategory(SYMBOL);
- if (rhs == null || BINARY_PRECEDENCE[symbol] >= minPrecedence) {
+ if (rhs == null || symbolPrecedence >= minPrecedence) {
if (rhs != null) lhs = Binary(lastSymbol, lhs, rhs);
- minPrecedence = BINARY_PRECEDENCE[symbol];
+ minPrecedence = symbolPrecedence;
rhs = parseUnaryLow();
lastSymbol = symbol;
} else {
- Expression higher = parseBinary(BINARY_PRECEDENCE[symbol]);
+ Expression higher = parseBinary(symbolPrecedence);
rhs = Binary(symbol, rhs, higher);
}
}
+
if (rhs == null) return lhs;
return Binary(lastSymbol, lhs, rhs);
}
@@ -1173,7 +1176,7 @@
var initialization = <VariableInitialization>[];
void declare(Declaration declaration) {
- Expression initializer = null;
+ Expression? initializer = null;
if (acceptString("=")) {
initializer = parseAssignment();
}
@@ -1318,7 +1321,7 @@
return Throw(expression);
}
- Statement parseBreakOrContinue(constructor) {
+ Statement parseBreakOrContinue(Statement Function(String?) constructor) {
var identifier = lastToken;
if (!skippedNewline && acceptCategory(ALPHA)) {
expectSemicolon();
@@ -1349,13 +1352,13 @@
//
// for (var variable in Expression) Statement
//
- Statement finishFor(Expression init) {
- Expression condition = null;
+ Statement finishFor(Expression? init) {
+ Expression? condition = null;
if (!acceptCategory(SEMICOLON)) {
condition = parseExpression();
expectCategory(SEMICOLON);
}
- Expression update = null;
+ Expression? update = null;
if (!acceptCategory(RPAREN)) {
update = parseExpression();
expectCategory(RPAREN);
@@ -1407,16 +1410,16 @@
Statement parseFunctionDeclaration() {
Declaration name = parseVariableDeclaration();
- Expression fun = parseFun();
+ Fun fun = parseFun();
return FunctionDeclaration(name, fun);
}
Statement parseTry() {
expectCategory(LBRACE);
Block body = parseBlock();
- Catch catchPart = null;
+ Catch? catchPart = null;
if (acceptString('catch')) catchPart = parseCatch();
- Block finallyPart = null;
+ Block? finallyPart = null;
if (acceptString('finally')) {
expectCategory(LBRACE);
finallyPart = parseBlock();
@@ -1427,7 +1430,7 @@
}
SwitchClause parseSwitchClause() {
- Expression expression = null;
+ Expression? expression = null;
if (acceptString('case')) {
expression = parseExpression();
expectCategory(COLON);
@@ -1437,7 +1440,7 @@
}
expectCategory(COLON);
}
- List statements = <Statement>[];
+ List<Statement> statements = [];
while (lastCategory != RBRACE &&
lastToken != 'case' &&
lastToken != 'default') {
diff --git a/pkg/js_ast/lib/src/template.dart b/pkg/js_ast/lib/src/template.dart
index bbf759e..662ff13 100644
--- a/pkg/js_ast/lib/src/template.dart
+++ b/pkg/js_ast/lib/src/template.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.15
+
library js_ast.template;
import 'nodes.dart';
@@ -12,7 +14,7 @@
TemplateManager();
- Template lookupExpressionTemplate(String source) {
+ Template? lookupExpressionTemplate(String source) {
return expressionTemplates[source];
}
@@ -23,7 +25,7 @@
return template;
}
- Template lookupStatementTemplate(String source) {
+ Template? lookupStatementTemplate(String source) {
return statementTemplates[source];
}
@@ -41,66 +43,75 @@
/// The [instantiate] method creates an AST that looks like the original with
/// the placeholders replaced by the arguments to [instantiate].
class Template {
- final String source;
+ final String? source;
final bool isExpression;
final bool forceCopy;
final Node ast;
- Instantiator instantiator;
+ final Instantiator instantiator;
- int positionalArgumentCount = -1;
+ final int positionalArgumentCount;
- // Null, unless there are named holes.
- List<String> holeNames;
- bool get isPositional => holeNames == null;
+ // Names of named holes, empty if there are no named holes.
+ final List<String> holeNames;
- Template(this.source, this.ast,
- {this.isExpression = true, this.forceCopy = false}) {
- assert(this.isExpression ? ast is Expression : ast is Statement);
- _compile();
+ bool get isPositional => holeNames.isEmpty;
+
+ Template._(this.source, this.ast,
+ {required this.instantiator,
+ required this.isExpression,
+ required this.forceCopy,
+ required this.positionalArgumentCount,
+ this.holeNames = const []});
+
+ factory Template(String? source, Node ast,
+ {bool isExpression = true, bool forceCopy = false}) {
+ assert(isExpression ? ast is Expression : ast is Statement);
+
+ final generator = InstantiatorGeneratorVisitor(forceCopy);
+ final instantiator = generator.compile(ast);
+ final positionalArgumentCount = generator.analysis.count;
+ final names = generator.analysis.holeNames;
+ final holeNames = names.toList(growable: false);
+
+ return Template._(source, ast,
+ instantiator: instantiator,
+ isExpression: isExpression,
+ forceCopy: forceCopy,
+ positionalArgumentCount: positionalArgumentCount,
+ holeNames: holeNames);
}
- Template.withExpressionResult(this.ast)
- : source = null,
- isExpression = true,
- forceCopy = false {
- assert(ast is Expression);
- assert(_checkNoPlaceholders());
- positionalArgumentCount = 0;
- instantiator = (arguments) => ast;
+ factory Template.withExpressionResult(Expression ast) {
+ assert(_checkNoPlaceholders(ast));
+ return Template._(null, ast,
+ instantiator: (arguments) => ast,
+ isExpression: true,
+ forceCopy: false,
+ positionalArgumentCount: 0);
}
- Template.withStatementResult(this.ast)
- : source = null,
- isExpression = false,
- forceCopy = false {
- assert(ast is Statement);
- assert(_checkNoPlaceholders());
- positionalArgumentCount = 0;
- instantiator = (arguments) => ast;
+ factory Template.withStatementResult(Statement ast) {
+ assert(_checkNoPlaceholders(ast));
+ return Template._(null, ast,
+ instantiator: (arguments) => ast,
+ isExpression: false,
+ forceCopy: false,
+ positionalArgumentCount: 0);
}
- bool _checkNoPlaceholders() {
+ static bool _checkNoPlaceholders(Node ast) {
InstantiatorGeneratorVisitor generator =
InstantiatorGeneratorVisitor(false);
generator.compile(ast);
return generator.analysis.count == 0;
}
- void _compile() {
- InstantiatorGeneratorVisitor generator =
- InstantiatorGeneratorVisitor(forceCopy);
- instantiator = generator.compile(ast);
- positionalArgumentCount = generator.analysis.count;
- Set<String> names = generator.analysis.holeNames;
- holeNames = names.toList(growable: false);
- }
-
/// Instantiates the template with the given [arguments].
///
/// This method fills in the holes with the given arguments. The [arguments]
/// must be either a [List] or a [Map].
- Node instantiate(var arguments) {
+ Node instantiate(Object arguments) {
if (arguments is List) {
if (arguments.length != positionalArgumentCount) {
throw 'Wrong number of template arguments, given ${arguments.length}, '
@@ -109,20 +120,23 @@
}
return instantiator(arguments);
}
- assert(arguments is Map);
- if (holeNames.length < arguments.length) {
- // This search is in O(n), but we only do it in case of an error, and the
- // number of holes should be quite limited.
- String unusedNames =
- arguments.keys.where((name) => !holeNames.contains(name)).join(", ");
- throw "Template arguments has unused mappings: $unusedNames";
+ if (arguments is Map) {
+ if (holeNames.length < arguments.length) {
+ // This search is in O(n), but we only do it in case of an error, and the
+ // number of holes should be quite limited.
+ String unusedNames = arguments.keys
+ .where((name) => !holeNames.contains(name))
+ .join(", ");
+ throw "Template arguments has unused mappings: $unusedNames";
+ }
+ if (!holeNames.every((String name) => arguments.containsKey(name))) {
+ String notFound =
+ holeNames.where((name) => !arguments.containsKey(name)).join(", ");
+ throw "Template arguments is missing mappings for: $notFound";
+ }
+ return instantiator(arguments);
}
- if (!holeNames.every((String name) => arguments.containsKey(name))) {
- String notFound =
- holeNames.where((name) => !arguments.containsKey(name)).join(", ");
- throw "Template arguments is missing mappings for: $notFound";
- }
- return instantiator(arguments);
+ throw ArgumentError.value(arguments, 'arguments', 'Must be a List or Map');
}
}
@@ -149,12 +163,12 @@
return result;
}
- static error(String message) {
+ static Never error(String message) {
throw message;
}
static Instantiator same(Node node) => (arguments) => node;
- static Node makeNull(arguments) => null;
+ static Null makeNull(arguments) => null;
Instantiator visit(Node node) {
if (forceCopy || analysis.containsInterpolatedNodes(node)) {
@@ -163,7 +177,7 @@
return same(node);
}
- Instantiator visitNullable(Node node) {
+ Instantiator visitNullable(Node? node) {
if (node == null) return makeNull;
return visit(node);
}
@@ -310,44 +324,34 @@
List<Instantiator> instantiators =
node.body.map(visitSplayableStatement).toList();
return (arguments) {
- List<Statement> statements = [];
- void add(node) {
- if (node is EmptyStatement) return;
- if (node is Iterable) {
- statements.addAll(node);
- } else {
- statements.add(node.toStatement());
- }
- }
-
- for (Instantiator instantiator in instantiators) {
- add(instantiator(arguments));
- }
- return Program(statements);
+ return Program(splayStatements(instantiators, arguments));
};
}
+ List<Statement> splayStatements(List<Instantiator> instantiators, arguments) {
+ var statements = <Statement>[];
+ for (var instantiator in instantiators) {
+ final node = instantiator(arguments);
+ if (node is EmptyStatement) continue;
+ if (node is Iterable) {
+ statements.addAll(node as Iterable<Statement>);
+ } else if (node is Block /*&& !node.isScope*/) {
+ statements.addAll(node.statements);
+ } else if (node is Statement) {
+ statements.add(node);
+ } else {
+ error('Not splayable as statement: $node');
+ }
+ }
+ return statements;
+ }
+
@override
Instantiator visitBlock(Block node) {
List<Instantiator> instantiators =
node.statements.map(visitSplayableStatement).toList();
return (arguments) {
- List<Statement> statements = [];
- void add(node) {
- if (node is EmptyStatement) return;
- if (node is Iterable) {
- statements.addAll(node);
- } else if (node is Block) {
- statements.addAll(node.statements);
- } else {
- statements.add(node.toStatement());
- }
- }
-
- for (Instantiator instantiator in instantiators) {
- add(instantiator(arguments));
- }
- return Block(statements);
+ return Block(splayStatements(instantiators, arguments));
};
}
@@ -365,40 +369,35 @@
@override
Instantiator visitIf(If node) {
- if (node.condition is InterpolatedExpression) {
- return visitIfConditionalCompilation(node);
+ final condition = node.condition;
+ if (condition is InterpolatedExpression) {
+ return visitIfConditionalCompilation(node, condition);
} else {
return visitIfNormal(node);
}
}
- Instantiator visitIfConditionalCompilation(If node) {
- // Special version of visitInterpolatedExpression that permits bools.
- compileCondition(InterpolatedExpression node) {
- var nameOrPosition = node.nameOrPosition;
- return (arguments) {
- var value = arguments[nameOrPosition];
- if (value is bool) return value;
- if (value is Expression) return value;
- if (value is String) return convertStringToVariableUse(value);
- throw error('Interpolated value #$nameOrPosition '
- 'is not an Expression: $value');
- };
- }
-
- var makeCondition = compileCondition(node.condition);
+ Instantiator visitIfConditionalCompilation(
+ If node, InterpolatedExpression condition) {
+ final nameOrPosition = condition.nameOrPosition;
Instantiator makeThen = visit(node.then);
Instantiator makeOtherwise = visit(node.otherwise);
return (arguments) {
- var condition = makeCondition(arguments);
- if (condition is bool) {
- if (condition == true) {
- return makeThen(arguments);
- } else {
- return makeOtherwise(arguments);
- }
+ // Allow booleans to be used for conditional compilation.
+ var value = arguments[nameOrPosition];
+ if (value is bool) {
+ return value ? makeThen(arguments) : makeOtherwise(arguments);
}
- return If(condition, makeThen(arguments), makeOtherwise(arguments));
+ Expression newCondition;
+ if (value is Expression) {
+ newCondition = value;
+ } else if (value is String) {
+ newCondition = convertStringToVariableUse(value);
+ } else {
+ error('Interpolated value #$nameOrPosition '
+ 'is not an Expression: $value');
+ }
+ return If(newCondition, makeThen(arguments), makeOtherwise(arguments));
};
}
@@ -567,8 +566,8 @@
@override
Instantiator visitAssignment(Assignment node) {
Instantiator makeLeftHandSide = visit(node.leftHandSide);
- String op = node.op;
- Instantiator makeValue = visitNullable(node.value);
+ String? op = node.op;
+ Instantiator makeValue = visit(node.value);
return (arguments) {
return Assignment.compound(
makeLeftHandSide(arguments), op, makeValue(arguments));
@@ -611,15 +610,7 @@
// copying.
return (arguments) {
Node target = makeTarget(arguments);
- List<Expression> callArguments = [];
- for (Instantiator instantiator in argumentMakers) {
- var result = instantiator(arguments);
- if (result is Iterable) {
- callArguments.addAll(result);
- } else {
- callArguments.add(result);
- }
- }
+ List<Expression> callArguments = splay(argumentMakers, arguments);
return finish(target, callArguments.toList(growable: false));
};
}
@@ -683,16 +674,8 @@
Instantiator makeBody = visit(node.body);
// TODO(sra): Avoid copying params if no interpolation or forced copying.
return (arguments) {
- List<Parameter> params = [];
- for (Instantiator instantiator in paramMakers) {
- var result = instantiator(arguments);
- if (result is Iterable) {
- params.addAll(result);
- } else {
- params.add(result);
- }
- }
- Statement body = makeBody(arguments);
+ List<Parameter> params = splayParameters(paramMakers, arguments);
+ Block body = makeBody(arguments);
return Fun(params, body);
};
}
@@ -703,21 +686,34 @@
Instantiator makeBody = visit(node.body);
// TODO(sra): Avoid copying params if no interpolation or forced copying.
return (arguments) {
- List<Parameter> params = [];
- for (Instantiator instantiator in paramMakers) {
- var result = instantiator(arguments);
- if (result is Iterable) {
- params.addAll(result);
- } else {
- params.add(result);
- }
- }
+ List<Parameter> params = splayParameters(paramMakers, arguments);
// Either a Block or Expression.
Node body = makeBody(arguments);
return ArrowFunction(params, body);
};
}
+ List<Parameter> splayParameters(List<Instantiator> instantiators, arguments) {
+ // TODO(sra): This will be different when parameters include destructuring
+ // and default values.
+ return splay<Parameter>(instantiators, arguments);
+ }
+
+ List<T> splay<T>(Iterable<Instantiator> instantiators, arguments) {
+ List<T> results = [];
+ for (Instantiator instantiator in instantiators) {
+ var result = instantiator(arguments);
+ if (result is Iterable) {
+ for (final item in result) {
+ results.add(item as T);
+ }
+ } else {
+ results.add(result as T);
+ }
+ }
+ return results;
+ }
+
@override
Instantiator visitDeferredExpression(DeferredExpression node) => same(node);
@@ -751,9 +747,10 @@
List<Instantiator> partMakers =
node.parts.map(visit).toList(growable: false);
return (arguments) {
- List<Literal> parts = partMakers
- .map((Instantiator instantiator) => instantiator(arguments))
- .toList(growable: false);
+ List<Literal> parts = [
+ for (final instantiator in partMakers)
+ instantiator(arguments) as Literal
+ ];
return StringConcatenation(parts);
};
}
@@ -795,15 +792,7 @@
node.properties.map(visitSplayable).toList();
bool isOneLiner = node.isOneLiner;
return (arguments) {
- List<Property> properties = [];
- for (Instantiator instantiator in propertyMakers) {
- var result = instantiator(arguments);
- if (result is Iterable) {
- properties.addAll(result);
- } else {
- properties.add(result);
- }
- }
+ List<Property> properties = splay(propertyMakers, arguments);
return ObjectInitializer(properties, isOneLiner: isOneLiner);
};
}
diff --git a/runtime/vm/heap/gc_shared.h b/runtime/vm/heap/gc_shared.h
index b7aac40..1a0d98d7 100644
--- a/runtime/vm/heap/gc_shared.h
+++ b/runtime/vm/heap/gc_shared.h
@@ -129,7 +129,7 @@
raw_finalizer->untag(), callback, peer);
}
raw_entry.untag()->set_token(raw_entry);
- callback(peer);
+ (*callback)(peer);
if (external_size > 0) {
if (FLAG_trace_finalizers) {
TRACE_FINALIZER("Clearing external size %" Pd " bytes in %s space",
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 11bda3c..e042e93 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -5043,7 +5043,8 @@
#undef FINALIZER_CROSS_GEN_TEST_CASE
-void NativeFinalizer_TwoEntriesCrossGen_Finalizer(intptr_t* token) {
+void NativeFinalizer_TwoEntriesCrossGen_Finalizer(void* peer) {
+ intptr_t* token = reinterpret_cast<intptr_t*>(peer);
(*token)++;
}
diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart
index f6b7d8c..cb9d386 100644
--- a/sdk/lib/ffi/c_type.dart
+++ b/sdk/lib/ffi/c_type.dart
@@ -24,19 +24,19 @@
@AbiSpecificIntegerMapping({
Abi.androidArm: Uint8(),
Abi.androidArm64: Uint8(),
- Abi.androidIA32: Uint8(),
- Abi.androidX64: Uint8(),
- Abi.fuchsiaArm64: Int8(),
+ Abi.androidIA32: Int8(),
+ Abi.androidX64: Int8(),
+ Abi.fuchsiaArm64: Uint8(),
Abi.fuchsiaX64: Int8(),
- Abi.iosArm: Uint8(),
+ Abi.iosArm: Int8(),
Abi.iosArm64: Int8(),
Abi.iosX64: Int8(),
Abi.linuxArm: Uint8(),
- Abi.linuxArm64: Int8(),
+ Abi.linuxArm64: Uint8(),
Abi.linuxIA32: Int8(),
Abi.linuxX64: Int8(),
- Abi.linuxRiscv32: Int8(),
- Abi.linuxRiscv64: Int8(),
+ Abi.linuxRiscv32: Uint8(),
+ Abi.linuxRiscv64: Uint8(),
Abi.macosArm64: Int8(),
Abi.macosX64: Int8(),
Abi.windowsArm64: Int8(),
diff --git a/tools/VERSION b/tools/VERSION
index c15e757..6c0f1d1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 249
+PRERELEASE 250
PRERELEASE_PATCH 0
\ No newline at end of file