Version 2.13.0-217.0.dev
Merge commit 'd6824468f90b8e0ec04abde6978a8a04acaa335a' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fe24ae..9dcfa0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,10 @@
*even if the set is empty* (in which case it just compares the element
to itself).
+#### `dart:developer`
+
+- Added `serverWebSocketUri` property to `ServiceProtocolInfo`.
+
### Dart VM
### Tools
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index e576474..221f315 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 19.0.0
+version: 20.0.0
description: Logic that is shared between the front_end and analyzer packages.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
index d072cad..542af9c 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.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
-
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -52,7 +50,7 @@
/// Return the content of the [source] in which the completion is being
/// requested, or `null` if the content could not be accessed.
- String get sourceContents;
+ String? get sourceContents;
/// Throw [AbortCompletion] if the completion request has been aborted.
void checkAborted();
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index e69c357..2c71a1e 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.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
-
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -46,10 +44,10 @@
ResourceProvider get resourceProvider => result.session.resourceProvider;
@override
- Source get source => result.unit.declaredElement.source;
+ Source get source => result.unit!.declaredElement!.source;
@override
- String get sourceContents => result?.content;
+ String? get sourceContents => result.content;
/// Abort the current completion request.
void abort() {
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index dd3480e..b0c2ac4 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -2,19 +2,14 @@
// 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
-
import 'package:analyzer/src/util/performance/operation_performance.dart';
/// Compute a string representing a code completion operation at the
/// given source and location.
///
/// This string is useful for displaying to users in a diagnostic context.
-String computeCompletionSnippet(String contents, int offset) {
- if (contents == null ||
- offset == null ||
- offset < 0 ||
- contents.length < offset) {
+String _computeCompletionSnippet(String contents, int offset) {
+ if (offset < 0 || contents.length < offset) {
return '???';
}
var start = offset;
@@ -40,13 +35,17 @@
/// Overall performance of a code completion operation.
class CompletionPerformance {
- String path;
+ String? path;
String snippet = '';
int suggestionCount = -1;
- OperationPerformanceImpl _operation;
+ OperationPerformance? _operation;
int get elapsedInMilliseconds {
- return _operation.elapsed.inMilliseconds;
+ var operation = _operation;
+ if (operation == null) {
+ throw StateError('Access of elapsed time before the operation is run');
+ }
+ return operation.elapsed.inMilliseconds;
}
String get suggestionCountStr {
@@ -68,6 +67,6 @@
}
void setContentsAndOffset(String contents, int offset) {
- snippet = computeCompletionSnippet(contents, offset);
+ snippet = _computeCompletionSnippet(contents, offset);
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 1b6eea7..9fd0c36 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.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
-
/// Utility methods to compute the value of the features used for code
/// completion.
import 'dart:math' as math;
@@ -46,27 +44,6 @@
'string'
];
-DartType impliedDartTypeWithName(TypeProvider typeProvider, String name) {
- if (typeProvider == null || name == null || name.isEmpty) {
- return null;
- }
- if (intNames.contains(name)) {
- return typeProvider.intType;
- } else if (numNames.contains(name)) {
- return typeProvider.numType;
- } else if (listNames.contains(name)) {
- return typeProvider.listType(typeProvider.dynamicType);
- } else if (stringNames.contains(name)) {
- return typeProvider.stringType;
- } else if (name == 'iterator') {
- return typeProvider.iterableDynamicType;
- } else if (name == 'map') {
- return typeProvider.mapType(
- typeProvider.dynamicType, typeProvider.dynamicType);
- }
- return null;
-}
-
/// Convert a relevance score (assumed to be between `0.0` and `1.0` inclusive)
/// to a relevance value between `0` and `1000`.
int toRelevance(double score) {
@@ -106,6 +83,27 @@
return (average + 1.0) / 2.0;
}
+DartType? _impliedDartTypeWithName(TypeProvider typeProvider, String name) {
+ if (name.isEmpty) {
+ return null;
+ }
+ if (intNames.contains(name)) {
+ return typeProvider.intType;
+ } else if (numNames.contains(name)) {
+ return typeProvider.numType;
+ } else if (listNames.contains(name)) {
+ return typeProvider.listType(typeProvider.dynamicType);
+ } else if (stringNames.contains(name)) {
+ return typeProvider.stringType;
+ } else if (name == 'iterator') {
+ return typeProvider.iterableDynamicType;
+ } else if (name == 'map') {
+ return typeProvider.mapType(
+ typeProvider.dynamicType, typeProvider.dynamicType);
+ }
+ return null;
+}
+
/// Return the weighted average of the given [values], applying the given
/// [weights]. The number of weights must be equal to the number of values.
double _weightedAverage(List<double> values, List<double> weights) {
@@ -165,7 +163,7 @@
/// Return the type imposed when completing at the given [offset], where the
/// offset is within the given [node], or `null` if the context does not
/// impose any type.
- DartType computeContextType(AstNode node, int offset) {
+ DartType? computeContextType(AstNode node, int offset) {
var type = node
.accept(_ContextTypeVisitor(typeProvider, offset))
?.resolveToBound(typeProvider.objectType);
@@ -193,7 +191,7 @@
} else if (element is FieldElement && element.isEnumConstant) {
return protocol.ElementKind.ENUM_CONSTANT;
} else if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
+ element = element.variable;
}
var kind = element.kind;
if (kind == ElementKind.CONSTRUCTOR) {
@@ -229,7 +227,7 @@
/// Return the value of the _context type_ feature for an element with the
/// given [elementType] when completing in a location with the given
/// [contextType].
- double contextTypeFeature(DartType contextType, DartType elementType) {
+ double contextTypeFeature(DartType? contextType, DartType? elementType) {
if (contextType == null || elementType == null) {
// Disable the feature if we don't have both types.
return 0.0;
@@ -252,8 +250,8 @@
/// Return the value of the _element kind_ feature for the [element] when
/// completing at the given [completionLocation]. If a [distance] is given it
/// will be used to provide finer-grained relevance scores.
- double elementKindFeature(Element element, String completionLocation,
- {double distance}) {
+ double elementKindFeature(Element element, String? completionLocation,
+ {double? distance}) {
if (completionLocation == null) {
return 0.0;
}
@@ -327,7 +325,7 @@
/// Return the value of the _keyword_ feature for the [keyword] when
/// completing at the given [completionLocation].
- double keywordFeature(String keyword, String completionLocation) {
+ double keywordFeature(String keyword, String? completionLocation) {
if (completionLocation == null) {
return 0.0;
}
@@ -357,7 +355,7 @@
/// declarations between the local variable and the reference.
int localVariableDistance(AstNode reference, LocalVariableElement variable) {
var distance = 0;
- var node = reference;
+ AstNode? node = reference;
while (node != null) {
if (node is ForStatement || node is ForElement) {
var loopParts = node is ForStatement
@@ -440,7 +438,7 @@
/// Return the value of the _super matches_ feature.
double superMatchesFeature(
- String containingMethodName, String proposedMemberName) =>
+ String? containingMethodName, String proposedMemberName) =>
containingMethodName == null
? 0.0
: (proposedMemberName == containingMethodName ? 1.0 : 0.0);
@@ -451,7 +449,7 @@
if (distance < 0) {
return 0.0;
}
- return math.pow(0.9, distance);
+ return math.pow(0.9, distance) as double;
}
/// Return the inheritance distance between the [subclass] and the
@@ -459,7 +457,7 @@
/// cycles in the type graph.
///
/// This is the implementation of [inheritanceDistance].
- int _inheritanceDistance(ClassElement subclass, ClassElement superclass,
+ int _inheritanceDistance(ClassElement? subclass, ClassElement superclass,
Set<ClassElement> visited) {
if (subclass == null) {
return -1;
@@ -504,7 +502,7 @@
_ContextTypeVisitor(this.typeProvider, this.offset);
@override
- DartType visitAdjacentStrings(AdjacentStrings node) {
+ DartType? visitAdjacentStrings(AdjacentStrings node) {
if (offset == node.offset) {
return _visitParent(node);
}
@@ -512,7 +510,7 @@
}
@override
- DartType visitArgumentList(ArgumentList node) {
+ DartType? visitArgumentList(ArgumentList node) {
if (range
.endStart(node.leftParenthesis, node.rightParenthesis)
.contains(offset)) {
@@ -523,7 +521,7 @@
var index = 0;
- DartType typeOfIndexPositionalParameter() {
+ DartType? typeOfIndexPositionalParameter() {
if (index < parameters.length) {
var parameter = parameters[index];
if (parameter.isPositional) {
@@ -533,7 +531,7 @@
return null;
}
- Expression previousArgument;
+ Expression? previousArgument;
for (var argument in node.arguments) {
if (argument is NamedExpression) {
if (offset <= argument.offset) {
@@ -560,7 +558,7 @@
}
@override
- DartType visitAsExpression(AsExpression node) {
+ DartType? visitAsExpression(AsExpression node) {
if (node.asOperator.end < offset) {
return node.expression.staticType;
}
@@ -568,10 +566,10 @@
}
@override
- DartType visitAssertInitializer(AssertInitializer node) {
+ DartType? visitAssertInitializer(AssertInitializer node) {
if (range
.endStart(node.leftParenthesis,
- node.message?.beginToken?.previous ?? node.rightParenthesis)
+ node.message?.beginToken.previous ?? node.rightParenthesis)
.contains(offset)) {
return typeProvider.boolType;
}
@@ -579,10 +577,10 @@
}
@override
- DartType visitAssertStatement(AssertStatement node) {
+ DartType? visitAssertStatement(AssertStatement node) {
if (range
.endStart(node.leftParenthesis,
- node.message?.beginToken?.previous ?? node.rightParenthesis)
+ node.message?.beginToken.previous ?? node.rightParenthesis)
.contains(offset)) {
return typeProvider.boolType;
}
@@ -590,7 +588,7 @@
}
@override
- DartType visitAssignmentExpression(AssignmentExpression node) {
+ DartType? visitAssignmentExpression(AssignmentExpression node) {
if (node.operator.end <= offset) {
// RHS
if (node.operator.type == TokenType.EQ) {
@@ -599,7 +597,7 @@
var method = node.staticElement;
if (method != null) {
var parameters = method.parameters;
- if (parameters != null && parameters.isNotEmpty) {
+ if (parameters.isNotEmpty) {
return parameters[0].type;
}
}
@@ -608,12 +606,12 @@
}
@override
- DartType visitAwaitExpression(AwaitExpression node) {
+ DartType? visitAwaitExpression(AwaitExpression node) {
return _visitParent(node);
}
@override
- DartType visitBinaryExpression(BinaryExpression node) {
+ DartType? visitBinaryExpression(BinaryExpression node) {
if (node.operator.end <= offset) {
return node.rightOperand.staticParameterElement?.type;
}
@@ -621,15 +619,15 @@
}
@override
- DartType visitCascadeExpression(CascadeExpression node) {
- if (node.target != null && offset == node.target.offset) {
+ DartType? visitCascadeExpression(CascadeExpression node) {
+ if (offset == node.target.offset) {
return _visitParent(node);
}
return null;
}
@override
- DartType visitConditionalExpression(ConditionalExpression node) {
+ DartType? visitConditionalExpression(ConditionalExpression node) {
if (offset <= node.question.offset) {
return typeProvider.boolType;
} else {
@@ -638,8 +636,8 @@
}
@override
- DartType visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- if (node.equals != null && node.equals.end <= offset) {
+ DartType? visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ if (node.equals.end <= offset) {
var element = node.fieldName.staticElement;
if (element is FieldElement) {
return element.type;
@@ -649,15 +647,16 @@
}
@override
- DartType visitDefaultFormalParameter(DefaultFormalParameter node) {
- if (node.separator != null && node.separator.end <= offset) {
- return node.parameter.declaredElement.type;
+ DartType? visitDefaultFormalParameter(DefaultFormalParameter node) {
+ var separator = node.separator;
+ if (separator != null && separator.end <= offset) {
+ return node.parameter.declaredElement?.type;
}
return null;
}
@override
- DartType visitDoStatement(DoStatement node) {
+ DartType? visitDoStatement(DoStatement node) {
if (range
.endStart(node.leftParenthesis, node.rightParenthesis)
.contains(offset)) {
@@ -667,7 +666,7 @@
}
@override
- DartType visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ DartType? visitExpressionFunctionBody(ExpressionFunctionBody node) {
if (range.endEnd(node.functionDefinition, node).contains(offset)) {
var parent = node.parent;
if (parent is MethodDeclaration) {
@@ -684,7 +683,7 @@
} else if (parent is FunctionExpression) {
var grandparent = parent.parent;
if (grandparent is FunctionDeclaration) {
- return BodyInferenceContext.of(parent.body).contextType;
+ return BodyInferenceContext.of(parent.body)?.contextType;
}
return _visitParent(parent);
}
@@ -693,15 +692,15 @@
}
@override
- DartType visitFieldDeclaration(FieldDeclaration node) {
- if (node.fields != null && node.fields.contains(offset)) {
+ DartType? visitFieldDeclaration(FieldDeclaration node) {
+ if (node.fields.contains(offset)) {
return node.fields.accept(this);
}
return null;
}
@override
- DartType visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+ DartType? visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
if (range
.startOffsetEndOffset(node.inKeyword.end, node.end)
.contains(offset)) {
@@ -716,7 +715,7 @@
}
@override
- DartType visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+ DartType? visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
if (range.endEnd(node.inKeyword, node).contains(offset)) {
var parent = node.parent;
if ((parent is ForStatement && parent.awaitKeyword != null) ||
@@ -729,31 +728,27 @@
}
@override
- DartType visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
- if (node.leftSeparator != null &&
- node.rightSeparator != null &&
- range
- .endStart(node.leftSeparator, node.rightSeparator)
- .contains(offset)) {
+ DartType? visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+ if (range
+ .endStart(node.leftSeparator, node.rightSeparator)
+ .contains(offset)) {
return typeProvider.boolType;
}
return null;
}
@override
- DartType visitForPartsWithExpression(ForPartsWithExpression node) {
- if (node.leftSeparator != null &&
- node.rightSeparator != null &&
- range
- .endStart(node.leftSeparator, node.rightSeparator)
- .contains(offset)) {
+ DartType? visitForPartsWithExpression(ForPartsWithExpression node) {
+ if (range
+ .endStart(node.leftSeparator, node.rightSeparator)
+ .contains(offset)) {
return typeProvider.boolType;
}
return null;
}
@override
- DartType visitFunctionExpressionInvocation(
+ DartType? visitFunctionExpressionInvocation(
FunctionExpressionInvocation node) {
if (node.function.contains(offset)) {
return _visitParent(node);
@@ -762,7 +757,7 @@
}
@override
- DartType visitIfElement(IfElement node) {
+ DartType? visitIfElement(IfElement node) {
if (range
.endStart(node.leftParenthesis, node.rightParenthesis)
.contains(offset)) {
@@ -772,7 +767,7 @@
}
@override
- DartType visitIfStatement(IfStatement node) {
+ DartType? visitIfStatement(IfStatement node) {
if (range
.endStart(node.leftParenthesis, node.rightParenthesis)
.contains(offset)) {
@@ -782,7 +777,7 @@
}
@override
- DartType visitIndexExpression(IndexExpression node) {
+ DartType? visitIndexExpression(IndexExpression node) {
if (range.endStart(node.leftBracket, node.rightBracket).contains(offset)) {
var parameters = node.staticElement?.parameters;
if (parameters != null && parameters.isNotEmpty) {
@@ -793,7 +788,7 @@
}
@override
- DartType visitIsExpression(IsExpression node) {
+ DartType? visitIsExpression(IsExpression node) {
if (node.isOperator.end < offset) {
return node.expression.staticType;
}
@@ -801,7 +796,7 @@
}
@override
- DartType visitLabel(Label node) {
+ DartType? visitLabel(Label node) {
if (offset == node.offset) {
return _visitParent(node);
}
@@ -812,7 +807,7 @@
}
@override
- DartType visitListLiteral(ListLiteral node) {
+ DartType? visitListLiteral(ListLiteral node) {
if (range.endStart(node.leftBracket, node.rightBracket).contains(offset)) {
return (node.staticType as InterfaceType).typeArguments[0];
}
@@ -820,10 +815,11 @@
}
@override
- DartType visitMapLiteralEntry(MapLiteralEntry node) {
+ DartType? visitMapLiteralEntry(MapLiteralEntry node) {
var literal = node.thisOrAncestorOfType<SetOrMapLiteral>();
- if (literal != null && literal.staticType.isDartCoreMap) {
- var typeArguments = (literal.staticType as InterfaceType).typeArguments;
+ var literalType = literal?.staticType;
+ if (literalType is InterfaceType && literalType.isDartCoreMap) {
+ var typeArguments = literalType.typeArguments;
if (offset <= node.separator.offset) {
return typeArguments[0];
} else {
@@ -834,7 +830,7 @@
}
@override
- DartType visitMethodInvocation(MethodInvocation node) {
+ DartType? visitMethodInvocation(MethodInvocation node) {
if (offset == node.offset) {
return _visitParent(node);
}
@@ -842,7 +838,7 @@
}
@override
- DartType visitNamedExpression(NamedExpression node) {
+ DartType? visitNamedExpression(NamedExpression node) {
if (offset == node.offset) {
return _visitParent(node);
}
@@ -853,65 +849,66 @@
}
@override
- DartType visitParenthesizedExpression(ParenthesizedExpression node) {
+ DartType? visitParenthesizedExpression(ParenthesizedExpression node) {
return _visitParent(node);
}
@override
- DartType visitPostfixExpression(PostfixExpression node) {
+ DartType? visitPostfixExpression(PostfixExpression node) {
return node.operand.staticParameterElement?.type;
}
@override
- DartType visitPrefixedIdentifier(PrefixedIdentifier node) {
+ DartType? visitPrefixedIdentifier(PrefixedIdentifier node) {
return _visitParent(node);
}
@override
- DartType visitPrefixExpression(PrefixExpression node) {
+ DartType? visitPrefixExpression(PrefixExpression node) {
return node.operand.staticParameterElement?.type;
}
@override
- DartType visitPropertyAccess(PropertyAccess node) {
+ DartType? visitPropertyAccess(PropertyAccess node) {
return _visitParent(node);
}
@override
- DartType visitReturnStatement(ReturnStatement node) {
+ DartType? visitReturnStatement(ReturnStatement node) {
if (node.returnKeyword.end < offset) {
var functionBody = node.thisOrAncestorOfType<FunctionBody>();
if (functionBody != null) {
- return BodyInferenceContext.of(functionBody).contextType;
+ return BodyInferenceContext.of(functionBody)?.contextType;
}
}
return null;
}
@override
- DartType visitSetOrMapLiteral(SetOrMapLiteral node) {
+ DartType? visitSetOrMapLiteral(SetOrMapLiteral node) {
var type = node.staticType;
- if (range.endStart(node.leftBracket, node.rightBracket).contains(offset) &&
+ if (type is InterfaceType &&
+ range.endStart(node.leftBracket, node.rightBracket).contains(offset) &&
(type.isDartCoreMap || type.isDartCoreSet)) {
- return (type as InterfaceType).typeArguments[0];
+ return type.typeArguments[0];
}
return null;
}
@override
- DartType visitSimpleIdentifier(SimpleIdentifier node) {
+ DartType? visitSimpleIdentifier(SimpleIdentifier node) {
return _visitParent(node);
}
@override
- DartType visitSimpleStringLiteral(SimpleStringLiteral node) {
+ DartType? visitSimpleStringLiteral(SimpleStringLiteral node) {
// The only completion inside of a String literal would be a directive,
// where the context type would not be of value.
return null;
}
@override
- DartType visitSpreadElement(SpreadElement node) {
+ DartType? visitSpreadElement(SpreadElement node) {
if (node.spreadOperator.end <= offset) {
var currentNode = node.parent;
while (currentNode != null) {
@@ -931,44 +928,45 @@
}
@override
- DartType visitSwitchCase(SwitchCase node) {
+ DartType? visitSwitchCase(SwitchCase node) {
if (range.endStart(node.keyword, node.colon).contains(offset)) {
var parent = node.parent;
if (parent is SwitchStatement) {
- return parent.expression?.staticType;
+ return parent.expression.staticType;
}
}
return super.visitSwitchCase(node);
}
@override
- DartType visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
- if (node.variables != null && node.variables.contains(offset)) {
+ DartType? visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+ if (node.variables.contains(offset)) {
return node.variables.accept(this);
}
return null;
}
@override
- DartType visitVariableDeclaration(VariableDeclaration node) {
- if (node.equals != null && node.equals.end <= offset) {
+ DartType? visitVariableDeclaration(VariableDeclaration node) {
+ var equals = node.equals;
+ if (equals != null && equals.end <= offset) {
var parent = node.parent;
if (parent is VariableDeclarationList) {
return parent.type?.type ??
- impliedDartTypeWithName(typeProvider, node.name?.name);
+ _impliedDartTypeWithName(typeProvider, node.name.name);
}
}
return null;
}
@override
- DartType visitVariableDeclarationList(VariableDeclarationList node) {
+ DartType? visitVariableDeclarationList(VariableDeclarationList node) {
for (var varDecl in node.variables) {
- if (varDecl != null && varDecl.contains(offset)) {
+ if (varDecl.contains(offset)) {
var equals = varDecl.equals;
if (equals != null && equals.end <= offset) {
return node.type?.type ??
- impliedDartTypeWithName(typeProvider, varDecl.name?.name);
+ _impliedDartTypeWithName(typeProvider, varDecl.name.name);
}
}
}
@@ -976,7 +974,7 @@
}
@override
- DartType visitWhileStatement(WhileStatement node) {
+ DartType? visitWhileStatement(WhileStatement node) {
if (range
.endStart(node.leftParenthesis, node.rightParenthesis)
.contains(offset)) {
@@ -986,11 +984,11 @@
}
@override
- DartType visitYieldStatement(YieldStatement node) {
+ DartType? visitYieldStatement(YieldStatement node) {
if (range.endStart(node.yieldKeyword, node.semicolon).contains(offset)) {
var functionBody = node.thisOrAncestorOfType<FunctionBody>();
if (functionBody != null) {
- return BodyInferenceContext.of(functionBody).contextType;
+ return BodyInferenceContext.of(functionBody)?.contextType;
}
}
return null;
@@ -999,7 +997,7 @@
/// Return the result of visiting the parent of the [node] after setting the
/// [childNode] to the [node]. Note that this method is destructive in that it
/// does not reset the [childNode] before returning.
- DartType _visitParent(AstNode node) {
+ DartType? _visitParent(AstNode node) {
var parent = node.parent;
if (parent == null) {
return null;
@@ -1016,7 +1014,7 @@
/// Some useful extensions on [ArgumentList] for this computer.
extension on ArgumentList {
/// Return the [FunctionType], if there is one, for this [ArgumentList].
- FunctionType get functionType {
+ FunctionType? get functionType {
var parent = this.parent;
if (parent is InstanceCreationExpression) {
return parent.constructorName.staticElement?.type;
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
index 7fd44bd..7f60edd 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/completion/yaml/producer.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
index e1f1d55..15ef594 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.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
-
import 'package:analysis_server/src/services/completion/yaml/producer.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
import 'package:analyzer/file_system/file_system.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
index c56f9d2..960346f 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -2,12 +2,9 @@
// 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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
/// An object that represents the location of a Boolean value.
@@ -117,8 +114,9 @@
/// Initialize a producer representing a key/value pair in a map.
const KeyValueProducer();
- /// Returns a producer for values of the given [key].
- Producer producerForKey(String key);
+ /// Returns a producer for values of the given [key], or `null` if there is
+ /// no registered producer for the [key].
+ Producer? producerForKey(String key);
}
/// An object that represents the location of an element in a list.
@@ -155,7 +153,7 @@
const MapProducer(this._children);
@override
- Producer producerForKey(String key) => _children[key];
+ Producer? producerForKey(String key) => _children[key];
@override
Iterable<CompletionSuggestion> suggestions(
@@ -198,7 +196,7 @@
final ResourceProvider resourceProvider;
/// The Pub package service used for looking up package names/versions.
- final PubPackageService pubPackageService;
+ final PubPackageService? pubPackageService;
/// The absolute path of the file in which completions are being requested.
final String filePath;
@@ -208,8 +206,8 @@
/// Initialize a newly created completion request.
YamlCompletionRequest(
- {@required this.filePath,
- @required this.precedingText,
- @required this.resourceProvider,
- @required this.pubPackageService});
+ {required this.filePath,
+ required this.precedingText,
+ required this.resourceProvider,
+ required this.pubPackageService});
}
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
index 629db2a..a1e73c3 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/completion/yaml/producer.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
@@ -17,10 +15,12 @@
@override
Iterable<CompletionSuggestion> suggestions(
YamlCompletionRequest request) sync* {
- final cachedPackages = request.pubPackageService.cachedPackages;
- var relevance = cachedPackages.length;
- yield* cachedPackages.map((package) =>
- packageName('${package.packageName}: ', relevance: relevance--));
+ final cachedPackages = request.pubPackageService?.cachedPackages;
+ if (cachedPackages != null) {
+ var relevance = cachedPackages.length;
+ yield* cachedPackages.map((package) =>
+ packageName('${package.packageName}: ', relevance: relevance--));
+ }
}
}
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
index b6bff4c..724475f 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/yaml_completion_generator.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/completion/yaml/producer.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
@@ -19,9 +17,9 @@
/// completion was requested.
final ResourceProvider resourceProvider;
- /// A service used for collecting Pub package information. May be null for
+ /// A service used for collecting Pub package information. May be `null` for
/// generators that do not use Pub packages.
- final PubPackageService pubPackageService;
+ final PubPackageService? pubPackageService;
/// Initialize a newly created generator to use the [resourceProvider] to
/// access the content of the file in which completion was requested.
@@ -86,15 +84,21 @@
}
}
final node = nodePath.isNotEmpty ? nodePath.last : null;
- final replaceNode = node is YamlScalar && node.containsOffset(offset);
- final replacementOffset = replaceNode ? node.span.start.offset : offset;
- final replacementLength = replaceNode ? node.span.length : 0;
+ int replacementOffset;
+ int replacementLength;
+ if (node is YamlScalar && node.containsOffset(offset)) {
+ replacementOffset = node.span.start.offset;
+ replacementLength = node.span.length;
+ } else {
+ replacementOffset = offset;
+ replacementLength = 0;
+ }
return YamlCompletionResults(
suggestions, replacementOffset, replacementLength);
}
/// Return the result of parsing the file [content] into a YAML node.
- YamlNode _parseYaml(String content) {
+ YamlNode? _parseYaml(String content) {
try {
return loadYamlNode(content, recover: true);
} on YamlException {
@@ -108,7 +112,7 @@
/// and the node containing the offset is the last element in the list.
List<YamlNode> _pathToOffset(YamlNode root, int offset) {
var path = <YamlNode>[];
- var node = root;
+ YamlNode? node = root;
while (node != null) {
path.add(node);
node = node.childContainingOffset(offset);
@@ -118,19 +122,19 @@
/// Return the producer that should be used to produce completion suggestions
/// for the last node in the node [path].
- Producer _producerForPath(List<YamlNode> path) {
- var producer = topLevelProducer;
+ Producer? _producerForPath(List<YamlNode> path) {
+ Producer? producer = topLevelProducer;
for (var i = 0; i < path.length - 1; i++) {
var node = path[i];
if (node is YamlMap && producer is KeyValueProducer) {
var key = node.keyAtValue(path[i + 1]);
if (key is YamlScalar) {
- producer = (producer as KeyValueProducer).producerForKey(key.value);
+ producer = producer.producerForKey(key.value);
} else {
return null;
}
} else if (node is YamlList && producer is ListProducer) {
- producer = (producer as ListProducer).element;
+ producer = producer.element;
} else {
return producer;
}
@@ -141,7 +145,7 @@
/// Return a list of the suggestions that should not be suggested because they
/// are already in the structure.
List<String> _siblingsOnPath(List<YamlNode> path) {
- List<String> siblingsInList(YamlList list, YamlNode currentElement) {
+ List<String> siblingsInList(YamlList list, YamlNode? currentElement) {
var siblings = <String>[];
for (var element in list.nodes) {
if (element != currentElement &&
@@ -153,7 +157,7 @@
return siblings;
}
- List<String> siblingsInMap(YamlMap map, YamlNode currentKey) {
+ List<String> siblingsInMap(YamlMap map, YamlNode? currentKey) {
var siblings = <String>[];
for (var key in map.nodes.keys) {
if (key != currentKey && key is YamlScalar && key.value is String) {
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 903f88f..e69df10 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -2,12 +2,12 @@
// 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
-
import 'dart:math';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:analysis_server/src/protocol_server.dart'
show doSourceChange_addElementEdit;
+import 'package:analysis_server/src/utilities/extensions/ast.dart';
import 'package:analysis_server/src/utilities/strings.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -18,6 +18,8 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.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/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -26,7 +28,6 @@
show SourceChange, SourceEdit;
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as pathos;
/// Adds edits to the given [change] that ensure that all the [libraries] are
@@ -38,14 +39,18 @@
var libUtils = CorrectionUtils(resolveResult);
var eol = libUtils.endOfLine;
// Prepare information about existing imports.
- LibraryDirective libraryDirective;
+ LibraryDirective? libraryDirective;
var importDirectives = <_ImportDirectiveInfo>[];
for (var directive in libUtils.unit.directives) {
if (directive is LibraryDirective) {
libraryDirective = directive;
} else if (directive is ImportDirective) {
- importDirectives.add(_ImportDirectiveInfo(
- directive.uri.stringValue, directive.offset, directive.end));
+ var uriStr = directive.uri.stringValue;
+ if (uriStr != null) {
+ importDirectives.add(
+ _ImportDirectiveInfo(uriStr, directive.offset, directive.end),
+ );
+ }
}
}
@@ -126,7 +131,7 @@
/// Climbs up [PrefixedIdentifier] and [PropertyAccess] nodes that include
/// [node].
-Expression climbPropertyAccess(AstNode node) {
+Expression climbPropertyAccess(Expression node) {
while (true) {
var parent = node.parent;
if (parent is PrefixedIdentifier && parent.identifier == node) {
@@ -156,31 +161,29 @@
List<SourceRange> getCommentRanges(CompilationUnit unit) {
var ranges = <SourceRange>[];
var token = unit.beginToken;
- while (token != null && token.type != TokenType.EOF) {
- Token commentToken = token.precedingComments;
+ while (token.type != TokenType.EOF) {
+ var commentToken = token.precedingComments;
while (commentToken != null) {
ranges.add(range.token(commentToken));
- commentToken = commentToken.next;
+ commentToken = commentToken.next as CommentToken?;
}
- token = token.next;
+ token = token.next!;
}
return ranges;
}
String getDefaultValueCode(DartType type) {
- if (type != null) {
- if (type.isDartCoreBool) {
- return 'false';
- }
- if (type.isDartCoreInt) {
- return '0';
- }
- if (type.isDartCoreDouble) {
- return '0.0';
- }
- if (type.isDartCoreString) {
- return "''";
- }
+ if (type.isDartCoreBool) {
+ return 'false';
+ }
+ if (type.isDartCoreInt) {
+ return '0';
+ }
+ if (type.isDartCoreDouble) {
+ return '0.0';
+ }
+ if (type.isDartCoreString) {
+ return "''";
}
// no better guess
return 'null';
@@ -204,10 +207,10 @@
if (kind == ElementKind.CONSTRUCTOR ||
kind == ElementKind.FIELD ||
kind == ElementKind.METHOD) {
- return '${element.enclosingElement.displayName}.${element.displayName}';
+ return '${element.enclosingElement!.displayName}.${element.displayName}';
} else if (kind == ElementKind.LIBRARY) {
// Libraries may not have names, so use a path relative to the context root.
- final session = element.session;
+ final session = element.session!;
final pathContext = session.resourceProvider.pathContext;
final rootPath = session.analysisContext.contextRoot.root.path;
final library = element as LibraryElement;
@@ -220,13 +223,13 @@
/// If the given [node] is in a class, enum or mixin declaration, return the
/// declared [ClassElement]. Otherwise return `null`.
-ClassElement getEnclosingClassElement(AstNode node) =>
+ClassElement? getEnclosingClassElement(AstNode node) =>
node.thisOrAncestorOfType<ClassOrMixinDeclaration>()?.declaredElement;
-/// Returns a class or an unit member enclosing the given [node].
-AstNode getEnclosingClassOrUnitMember(AstNode node) {
- var member = node;
- while (node != null) {
+/// Returns a class or an unit member enclosing the given [input].
+AstNode? getEnclosingClassOrUnitMember(AstNode input) {
+ var member = input;
+ for (var node in input.withParents) {
if (node is ClassDeclaration) {
return member;
}
@@ -234,14 +237,13 @@
return member;
}
member = node;
- node = node.parent;
}
return null;
}
/// Return the [ExecutableElement] of the enclosing executable [AstNode].
-ExecutableElement getEnclosingExecutableElement(AstNode node) {
- while (node != null) {
+ExecutableElement? getEnclosingExecutableElement(AstNode input) {
+ for (var node in input.withParents) {
if (node is FunctionDeclaration) {
return node.declaredElement;
}
@@ -251,14 +253,13 @@
if (node is MethodDeclaration) {
return node.declaredElement;
}
- node = node.parent;
}
return null;
}
/// Return the enclosing executable [AstNode].
-AstNode getEnclosingExecutableNode(AstNode node) {
- while (node != null) {
+AstNode? getEnclosingExecutableNode(AstNode input) {
+ for (var node in input.withParents) {
if (node is FunctionDeclaration) {
return node;
}
@@ -268,14 +269,13 @@
if (node is MethodDeclaration) {
return node;
}
- node = node.parent;
}
return null;
}
/// If the given [node] is in an extension, return the declared
/// [ExtensionElement]. Otherwise return `null`.
-ExtensionElement getEnclosingExtensionElement(AstNode node) =>
+ExtensionElement? getEnclosingExtensionElement(AstNode node) =>
node.thisOrAncestorOfType<ExtensionDeclaration>()?.declaredElement;
/// Returns [getExpressionPrecedence] for the parent of [node], or
@@ -283,7 +283,7 @@
///
/// The reason is that `(expr)` is always executed after `expr`.
Precedence getExpressionParentPrecedence(AstNode node) {
- var parent = node.parent;
+ var parent = node.parent!;
if (parent is ParenthesizedExpression) {
return Precedence.assignment;
} else if (parent is IndexExpression && parent.index == node) {
@@ -342,7 +342,7 @@
/// Return the [LocalVariableElement] if given [node] is a reference to a local
/// variable, or `null` in the other case.
-LocalVariableElement getLocalVariableElement(SimpleIdentifier node) {
+LocalVariableElement? getLocalVariableElement(SimpleIdentifier node) {
var element = node.staticElement;
if (element is LocalVariableElement) {
return element;
@@ -351,7 +351,7 @@
}
/// Return the nearest common ancestor of the given [nodes].
-AstNode getNearestCommonAncestor(List<AstNode> nodes) {
+AstNode? getNearestCommonAncestor(List<AstNode> nodes) {
// may be no nodes
if (nodes.isEmpty) {
return null;
@@ -378,7 +378,7 @@
/// Returns the [Expression] qualifier if given [node] is the name part of a
/// [PropertyAccess] or a [PrefixedIdentifier]. Maybe `null`.
-Expression getNodeQualifier(SimpleIdentifier node) {
+Expression? getNodeQualifier(SimpleIdentifier node) {
var parent = node.parent;
if (parent is MethodInvocation && identical(parent.methodName, node)) {
return parent.target;
@@ -394,7 +394,7 @@
/// Returns the [ParameterElement] if the given [node] is a reference to a
/// parameter, or `null` in the other case.
-ParameterElement getParameterElement(SimpleIdentifier node) {
+ParameterElement? getParameterElement(SimpleIdentifier node) {
var element = node.staticElement;
if (element is ParameterElement) {
return element;
@@ -405,29 +405,12 @@
/// Return parent [AstNode]s from compilation unit (at index "0") to the given
/// [node].
List<AstNode> getParents(AstNode node) {
- // prepare number of parents
- var numParents = 0;
- {
- var current = node.parent;
- while (current != null) {
- numParents++;
- current = current.parent;
- }
- }
- // fill array of parents
- var parents = List<AstNode>.filled(numParents, null);
- var current = node.parent;
- var index = numParents;
- while (current != null) {
- parents[--index] = current;
- current = current.parent;
- }
- return parents;
+ return node.withParents.toList().reversed.toList();
}
/// If given [node] is name of qualified property extraction, returns target
/// from which this property is extracted, otherwise `null`.
-Expression getQualifiedPropertyTarget(AstNode node) {
+Expression? getQualifiedPropertyTarget(AstNode node) {
var parent = node.parent;
if (parent is PrefixedIdentifier) {
var prefixed = parent;
@@ -446,7 +429,7 @@
/// Returns the given [statement] if not a block, or the first child statement
/// if a block, or `null` if more than one child.
-Statement getSingleStatement(Statement statement) {
+Statement? getSingleStatement(Statement statement) {
if (statement is Block) {
List<Statement> blockStatements = statement.statements;
if (blockStatements.length != 1) {
@@ -467,11 +450,8 @@
}
/// Checks if the given [element]'s display name equals to the given [name].
-bool hasDisplayName(Element element, String name) {
- if (element == null) {
- return false;
- }
- return element.displayName == name;
+bool hasDisplayName(Element? element, String name) {
+ return element?.displayName == name;
}
/// Checks if given [DartNode] is the left hand side of an assignment, or a
@@ -502,7 +482,7 @@
/// If the given [expression] is the `expression` property of a
/// [NamedExpression] then returns this [NamedExpression], otherwise returns
/// [expression].
-Expression stepUpNamedExpression(Expression expression) {
+Expression? stepUpNamedExpression(Expression? expression) {
if (expression != null) {
var parent = expression.parent;
if (parent is NamedExpression && parent.expression == expression) {
@@ -528,7 +508,7 @@
/// These inconsistencies may happen as a part of normal workflow, e.g. because
/// a resource was deleted, or an analysis result was invalidated.
class CancelCorrectionException {
- final Object exception;
+ final Object? exception;
CancelCorrectionException({this.exception});
}
@@ -549,37 +529,39 @@
/// The [ClassElement] the generated code is inserted to, so we can decide if
/// a type parameter may or may not be used.
- ClassElement targetClassElement;
+ ClassElement? targetClassElement;
- ExecutableElement targetExecutableElement;
+ ExecutableElement? targetExecutableElement;
- String _endOfLine;
+ String? _endOfLine;
CorrectionUtils(ResolvedUnitResult result)
- : unit = result.unit,
+ : unit = result.unit!,
_library = result.libraryElement,
- _buffer = result.content;
+ _buffer = result.content!;
/// Returns the EOL to use for this [CompilationUnit].
String get endOfLine {
- if (_endOfLine == null) {
- if (_buffer.contains('\r\n')) {
- _endOfLine = '\r\n';
- } else {
- _endOfLine = '\n';
- }
+ var endOfLine = _endOfLine;
+ if (endOfLine != null) {
+ return endOfLine;
}
- return _endOfLine;
+
+ if (_buffer.contains('\r\n')) {
+ return _endOfLine = '\r\n';
+ } else {
+ return _endOfLine = '\n';
+ }
}
/// Returns the [AstNode] that encloses the given offset.
- AstNode findNode(int offset) => NodeLocator(offset).searchWithin(unit);
+ AstNode? findNode(int offset) => NodeLocator(offset).searchWithin(unit);
/// Returns names of elements that might conflict with a new local variable
/// declared at [offset].
Set<String> findPossibleLocalVariableConflicts(int offset) {
var conflicts = <String>{};
- var enclosingNode = findNode(offset);
+ var enclosingNode = findNode(offset)!;
var enclosingBlock = enclosingNode.thisOrAncestorOfType<Block>();
if (enclosingBlock != null) {
var visitor = _CollectReferencedUnprefixedNames();
@@ -747,8 +729,9 @@
// end
var endOffset = sourceRange.end;
var afterEndLineOffset = endOffset;
- var lineStart = unit.lineInfo.getOffsetOfLine(
- unit.lineInfo.getLocation(startLineOffset).lineNumber - 1);
+ var lineInfo = unit.lineInfo!;
+ var lineStart = lineInfo
+ .getOffsetOfLine(lineInfo.getLocation(startLineOffset).lineNumber - 1);
if (lineStart == startLineOffset) {
// Only consume line ends after the end of the range if there is nothing
// else on the line containing the beginning of the range. Otherwise this
@@ -814,13 +797,15 @@
///
/// Fills [librariesToImport] with [LibraryElement]s whose elements are
/// used by the generated source, but not imported.
- String getTypeSource(DartType type, Set<Source> librariesToImport,
- {StringBuffer parametersBuffer}) {
- if (type.aliasElement != null) {
+ String? getTypeSource(DartType type, Set<Source> librariesToImport,
+ {StringBuffer? parametersBuffer}) {
+ var aliasElement = type.aliasElement;
+ var aliasArguments = type.aliasArguments;
+ if (aliasElement != null && aliasArguments != null) {
return _getTypeCodeElementArguments(
librariesToImport: librariesToImport,
- element: type.aliasElement,
- typeArguments: type.aliasArguments,
+ element: aliasElement,
+ typeArguments: aliasArguments,
);
}
@@ -888,7 +873,7 @@
}
// update line
if (indentLeft) {
- line = removeStart(line, indent);
+ line = removeStart(line, indent)!;
} else {
line = '$indent$line';
}
@@ -907,8 +892,8 @@
/// Return `true` if the given class, mixin, enum or extension [declaration]
/// has open '{' and close '}' on the same line, e.g. `class X {}`.
bool isClassWithEmptyBody(CompilationUnitMember declaration) {
- return getLineThis(_getLeftBracket(declaration).offset) ==
- getLineThis(_getRightBracket(declaration).offset);
+ return getLineThis(_getLeftBracket(declaration)!.offset) ==
+ getLineThis(_getRightBracket(declaration)!.offset);
}
/// Return <code>true</code> if [range] contains only whitespace or comments.
@@ -922,12 +907,12 @@
return TokenUtils.getTokens(trimmedText, unit.featureSet).isEmpty;
}
- ClassMemberLocation prepareNewClassMemberLocation(
+ ClassMemberLocation? prepareNewClassMemberLocation(
CompilationUnitMember declaration,
bool Function(ClassMember existingMember) shouldSkip) {
var indent = getIndent(1);
// Find the last target member.
- ClassMember targetMember;
+ ClassMember? targetMember;
var members = _getMembers(declaration);
if (members == null) {
return null;
@@ -949,10 +934,10 @@
? endOfLine
: '';
return ClassMemberLocation(
- endOfLine + indent, _getLeftBracket(declaration).end, suffix);
+ endOfLine + indent, _getLeftBracket(declaration)!.end, suffix);
}
- ClassMemberLocation prepareNewConstructorLocation(
+ ClassMemberLocation? prepareNewConstructorLocation(
ClassDeclaration classDeclaration) {
return prepareNewClassMemberLocation(
classDeclaration,
@@ -960,13 +945,13 @@
member is FieldDeclaration || member is ConstructorDeclaration);
}
- ClassMemberLocation prepareNewFieldLocation(
+ ClassMemberLocation? prepareNewFieldLocation(
CompilationUnitMember declaration) {
return prepareNewClassMemberLocation(
declaration, (member) => member is FieldDeclaration);
}
- ClassMemberLocation prepareNewGetterLocation(
+ ClassMemberLocation? prepareNewGetterLocation(
CompilationUnitMember declaration) {
return prepareNewClassMemberLocation(
declaration,
@@ -976,7 +961,7 @@
member is MethodDeclaration && member.isGetter);
}
- ClassMemberLocation prepareNewMethodLocation(
+ ClassMemberLocation? prepareNewMethodLocation(
CompilationUnitMember declaration) {
return prepareNewClassMemberLocation(
declaration,
@@ -998,7 +983,6 @@
if (token.type == TokenType.STRING) {
lineRanges.add(range.token(token));
}
- token = token.next;
}
}
// re-indent lines
@@ -1072,7 +1056,7 @@
/// Return the import element used to import given [element] into the library.
/// May be `null` if was not imported, i.e. declared in the same library.
- ImportElement _getImportElement(Element element) {
+ ImportElement? _getImportElement(Element element) {
for (var imp in _library.imports) {
var definedNames = getImportNamespace(imp);
if (definedNames.containsValue(element)) {
@@ -1082,7 +1066,7 @@
return null;
}
- Token _getLeftBracket(CompilationUnitMember declaration) {
+ Token? _getLeftBracket(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
return declaration.leftBracket;
} else if (declaration is ExtensionDeclaration) {
@@ -1091,7 +1075,7 @@
return null;
}
- List<ClassMember> _getMembers(CompilationUnitMember declaration) {
+ List<ClassMember>? _getMembers(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
return declaration.members;
} else if (declaration is ExtensionDeclaration) {
@@ -1100,7 +1084,7 @@
return null;
}
- Token _getRightBracket(CompilationUnitMember declaration) {
+ Token? _getRightBracket(CompilationUnitMember declaration) {
if (declaration is ClassOrMixinDeclaration) {
return declaration.rightBracket;
} else if (declaration is ExtensionDeclaration) {
@@ -1109,10 +1093,10 @@
return null;
}
- String _getTypeCodeElementArguments({
- @required Set<Source> librariesToImport,
- @required Element element,
- @required List<DartType> typeArguments,
+ String? _getTypeCodeElementArguments({
+ required Set<Source> librariesToImport,
+ required Element element,
+ required List<DartType> typeArguments,
}) {
var sb = StringBuffer();
@@ -1126,8 +1110,9 @@
// ensure import
var importElement = _getImportElement(element);
if (importElement != null) {
- if (importElement.prefix != null) {
- sb.write(importElement.prefix.displayName);
+ var prefix = importElement.prefix;
+ if (prefix != null) {
+ sb.write(prefix.displayName);
sb.write('.');
}
} else {
@@ -1222,7 +1207,7 @@
} else if (expression is ParenthesizedExpression) {
return _invertCondition0(expression.unParenthesized);
}
- var type = expression.staticType;
+ var type = expression.typeOrThrow;
if (type.isDartCoreBool) {
return _InvertedCondition._simple('!${getNodeText(expression)}');
}
@@ -1271,7 +1256,7 @@
class TokenUtils {
static List<Token> getNodeTokens(AstNode node) {
var result = <Token>[];
- for (var token = node.beginToken;; token = token.next) {
+ for (var token = node.beginToken;; token = token.next!) {
result.add(token);
if (token == node.endToken) {
break;
@@ -1285,15 +1270,18 @@
static List<Token> getTokens(String s, FeatureSet featureSet) {
try {
var tokens = <Token>[];
- var scanner = Scanner(null, CharSequenceReader(s), null)
- ..configureFeatures(
+ var scanner = Scanner(
+ _SourceMock(),
+ CharSequenceReader(s),
+ AnalysisErrorListener.NULL_LISTENER,
+ )..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
var token = scanner.tokenize();
while (token.type != TokenType.EOF) {
tokens.add(token);
- token = token.next;
+ token = token.next!;
}
return tokens;
} catch (e) {
@@ -1396,3 +1384,8 @@
}
}
}
+
+class _SourceMock implements Source {
+ @override
+ dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_api.dart b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
index 2ba45d0..e52dc50 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_api.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
@@ -41,7 +41,7 @@
};
PubApi(this.instrumentationService, http.Client? httpClient,
- String envPubHostedUrl)
+ String? envPubHostedUrl)
: httpClient =
httpClient != null ? _NoCloseHttpClient(httpClient) : http.Client(),
_pubHostedUrl = _validPubHostedUrl(envPubHostedUrl);
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
index fd493a4..c6d2078 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
@@ -60,6 +60,19 @@
bool get inSwitch => thisOrAncestorOfType<SwitchStatement>() != null;
bool get inWhileLoop => thisOrAncestorOfType<WhileStatement>() != null;
+
+ /// Return this node and all its parents.
+ Iterable<AstNode> get withParents sync* {
+ var current = this;
+ while (true) {
+ yield current;
+ var parent = current.parent;
+ if (parent == null) {
+ break;
+ }
+ current = parent;
+ }
+ }
}
extension ExpressionExtensions on Expression {
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 6e2a9e5..a889acf 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -23,7 +23,7 @@
late String testCode;
late String testFile;
- ResolvedUnitResult? testAnalysisResult;
+ late ResolvedUnitResult testAnalysisResult;
late CompilationUnit testUnit;
late CompilationUnitElement testUnitElement;
late LibraryElement testLibraryElement;
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index da9514d..e802863 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.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
-
import 'package:analysis_server/plugin/protocol/protocol_dart.dart';
import 'package:analyzer/dart/element/element.dart' as engine;
import 'package:analyzer/src/dart/element/element.dart' as engine;
@@ -88,7 +86,7 @@
expect(element.name, '_A');
expect(element.typeParameters, isNull);
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 27);
expect(location.length, '_A'.length);
@@ -125,7 +123,7 @@
expect(element.name, 'myConstructor');
expect(element.typeParameters, isNull);
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 20);
expect(location.length, 'myConstructor'.length);
@@ -210,7 +208,7 @@
expect(element.name, '_E1');
expect(element.typeParameters, isNull);
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 17);
expect(location.length, '_E1'.length);
@@ -246,7 +244,7 @@
expect(element.kind, ElementKind.ENUM_CONSTANT);
expect(element.name, 'one');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 23);
expect(location.length, 'one'.length);
@@ -270,7 +268,7 @@
expect(element.kind, ElementKind.ENUM_CONSTANT);
expect(element.name, 'three');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 44);
expect(location.length, 'three'.length);
@@ -288,7 +286,7 @@
expect(element.kind, ElementKind.FIELD);
expect(element.name, 'index');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, -1);
expect(location.length, 'index'.length);
@@ -306,7 +304,7 @@
expect(element.kind, ElementKind.FIELD);
expect(element.name, 'values');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, -1);
expect(location.length, 'values'.length);
@@ -330,7 +328,7 @@
expect(element.kind, ElementKind.FIELD);
expect(element.name, 'myField');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 25);
expect(location.length, 'myField'.length);
@@ -353,7 +351,7 @@
expect(element.name, 'F');
expect(element.typeParameters, '<T>');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 8);
expect(location.length, 'F'.length);
@@ -376,7 +374,7 @@
expect(element.name, 'F');
expect(element.typeParameters, '<out T>');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 8);
expect(location.length, 'F'.length);
@@ -400,7 +398,7 @@
expect(element.name, 'F');
expect(element.typeParameters, '<T>');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 12);
expect(location.length, 'F'.length);
@@ -424,7 +422,7 @@
expect(element.kind, ElementKind.GETTER);
expect(element.name, 'myGetter');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 23);
expect(location.length, 'myGetter'.length);
@@ -450,7 +448,7 @@
expect(element.kind, ElementKind.LABEL);
expect(element.name, 'myLabel');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 9);
expect(location.length, 'myLabel'.length);
@@ -475,7 +473,7 @@
expect(element.kind, ElementKind.METHOD);
expect(element.name, 'myMethod');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 32);
expect(location.length, 'myGetter'.length);
@@ -499,7 +497,7 @@
expect(element.name, 'A');
expect(element.typeParameters, isNull);
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 6);
expect(location.length, 'A'.length);
@@ -522,7 +520,7 @@
expect(element.kind, ElementKind.SETTER);
expect(element.name, 'mySetter');
{
- var location = element.location;
+ var location = element.location!;
expect(location.file, testFile);
expect(location.offset, 16);
expect(location.length, 'mySetter'.length);
diff --git a/pkg/analysis_server/test/plugin/test_all.dart b/pkg/analysis_server/test/plugin/test_all.dart
index 66ab7e3..56ce709 100644
--- a/pkg/analysis_server/test/plugin/test_all.dart
+++ b/pkg/analysis_server/test/plugin/test_all.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
-
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'protocol_dart_test.dart' as protocol_dart_test;
diff --git a/pkg/analysis_server/test/search/search_result_test.dart b/pkg/analysis_server/test/search/search_result_test.dart
index 978f0ec..25308ca 100644
--- a/pkg/analysis_server/test/search/search_result_test.dart
+++ b/pkg/analysis_server/test/search/search_result_test.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:test/test.dart';
@@ -30,7 +28,6 @@
SearchResultKind.REFERENCE);
expect(newSearchResultKind_fromEngine(MatchKind.INVOCATION),
SearchResultKind.INVOCATION);
- expect(newSearchResultKind_fromEngine(null), SearchResultKind.UNKNOWN);
}
void test_fromName() {
diff --git a/pkg/analysis_server/test/services/correction/change_test.dart b/pkg/analysis_server/test/services/correction/change_test.dart
index 8616a2c..dead4df 100644
--- a/pkg/analysis_server/test/services/correction/change_test.dart
+++ b/pkg/analysis_server/test/services/correction/change_test.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test/test.dart';
@@ -34,8 +32,7 @@
change.addEdit('/a.dart', 0, edit2);
expect(change.edits, hasLength(1));
{
- var fileEdit = change.getFileEdit('/a.dart');
- expect(fileEdit, isNotNull);
+ var fileEdit = change.getFileEdit('/a.dart')!;
expect(fileEdit.edits, unorderedEquals([edit1, edit2]));
}
}
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 3bcc7a9..41c0eec 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.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
-
import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
@@ -28,7 +26,7 @@
await resolveTestCode('class MyClass {}');
var element = findElement.class_('MyClass');
// check
- var location = newLocation_fromElement(element);
+ var location = newLocation_fromElement(element)!;
expect(location.file, testFile);
expect(location.offset, 6);
expect(location.length, 7);
@@ -114,9 +112,10 @@
var problems = refactoringStatus.problems;
expect(problems, hasLength(1));
expect(problems[0].message, 'msg');
- expect(problems[0].location.file, '/test.dart');
- expect(problems[0].location.offset, 1);
- expect(problems[0].location.length, 2);
+ var problemLocation = problems[0].location!;
+ expect(problemLocation.file, '/test.dart');
+ expect(problemLocation.offset, 1);
+ expect(problemLocation.length, 2);
// add WARNING, resulting severity is still FATAL
refactoringStatus.addWarning('warning');
expect(refactoringStatus.severity, RefactoringProblemSeverity.FATAL);
@@ -202,22 +201,22 @@
refactoringStatus.addError('msgError');
refactoringStatus.addWarning('msgWarning');
refactoringStatus.addFatalError('msgFatalError');
+ var problem = refactoringStatus.problem!;
// get entry
- {
- var problem = refactoringStatus.problem;
- expect(problem.severity, RefactoringProblemSeverity.FATAL);
- expect(problem.message, 'msgFatalError');
- }
+ expect(problem.severity, RefactoringProblemSeverity.FATAL);
+ expect(problem.message, 'msgFatalError');
// get message
- expect(refactoringStatus.problem.message, 'msgFatalError');
+ expect(problem.message, 'msgFatalError');
}
void test_newError() {
var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
var refactoringStatus = RefactoringStatus.error('msg', location);
+ var problem = refactoringStatus.problem!;
+ var problemLocation = problem.location!;
expect(refactoringStatus.severity, RefactoringProblemSeverity.ERROR);
- expect(refactoringStatus.problem.message, 'msg');
- expect(refactoringStatus.problem.location.file, '/test.dart');
+ expect(problem.message, 'msg');
+ expect(problemLocation.file, '/test.dart');
}
void test_newFatalError() {
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart
index 203ccf9..fcbee98 100644
--- a/pkg/analysis_server/test/services/correction/util_test.dart
+++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -2,17 +2,15 @@
// 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
-
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../abstract_single_unit.dart';
-import '../../src/services/correction/assist/assist_processor.dart';
void main() {
defineReflectiveSuite(() {
@@ -324,8 +322,7 @@
await addLibraryImports(testAnalysisResult.session, change,
testLibraryElement, newLibraries.toSet());
var testEdit = change.getFileEdit(testFile);
- expect(testEdit, isNotNull);
- var resultCode = SourceEdit.applySequence(testCode, testEdit.edits);
+ var resultCode = SourceEdit.applySequence(testCode, testEdit!.edits);
expect(resultCode, expectedCode);
}
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index 21879f2..8d8fa21 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -339,6 +339,7 @@
}
Future<void> test_folder_outside_workspace_returns_failure() async {
+ await resolveTestFile();
_createRefactoring('/tmp-new', oldFile: '/tmp');
// TODO(dantup): These paths should all use convertPath so they're as expected
// on Windows.
@@ -348,6 +349,7 @@
}
Future<void> test_nonexistent_file_returns_failure() async {
+ await resolveTestFile();
_createRefactoring(convertPath('/home/test/test_missing_new.dart'),
oldFile: convertPath('/home/test/test_missing.dart'));
await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
@@ -363,6 +365,7 @@
}
Future<void> test_projectFolder() async {
+ await resolveTestFile();
_createRefactoring('/home/test2', oldFile: '/home/test');
await _assertFailedRefactoring(RefactoringProblemSeverity.FATAL,
expectedMessage: 'Renaming an analysis root is not supported '
diff --git a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
index 4dbb904..6e27b10 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.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
-
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:test/test.dart';
@@ -19,10 +17,10 @@
@reflectiveTest
class ContextTypeTest extends FeatureComputerTest {
- Future<void> assertContextType(String content, String expectedType) async {
+ Future<void> assertContextType(String content, [String? expectedType]) async {
await completeIn(content);
- var computer = FeatureComputer(
- testAnalysisResult.typeSystem, testAnalysisResult.typeProvider);
+ var result = testAnalysisResult;
+ var computer = FeatureComputer(result.typeSystem, result.typeProvider);
var type = computer.computeContextType(
completionTarget.containingNode, cursorIndex);
@@ -68,7 +66,7 @@
void g() {
f(i^:);
}
-''', null);
+''');
}
Future<void> test_argumentList_named_beforeLabel() async {
@@ -77,7 +75,7 @@
void g() {
f(^i:);
}
-''', null);
+''');
}
Future<void>
@@ -118,7 +116,7 @@
void g() {
f(j: ^);
}
-''', null);
+''');
}
Future<void> test_argumentList_named_unresolved_noNamedParameters() async {
@@ -128,7 +126,7 @@
void g() {
f(j: ^);
}
-''', null);
+''');
}
Future<void> test_argumentList_named_with_requiredPositional() async {
@@ -156,7 +154,7 @@
void g() {
f(^);
}
-''', null);
+''');
}
Future<void> test_argumentList_noParameters_whitespace() async {
@@ -165,7 +163,7 @@
void g() {
f( ^ );
}
-''', null);
+''');
}
Future<void> test_argumentList_noParameters_whitespace_left() async {
@@ -174,7 +172,7 @@
void g() {
f( ^);
}
-''', null);
+''');
}
Future<void> test_argumentList_noParameters_whitespace_right() async {
@@ -183,7 +181,7 @@
void g() {
f(^ );
}
-''', null);
+''');
}
Future<void> test_argumentList_positional() async {
@@ -201,7 +199,7 @@
void g() {
f(i: ^);
}
-''', null);
+''');
}
Future<void> test_argumentList_positional_asNamed_beforeColon() async {
@@ -210,7 +208,7 @@
void g() {
f(i^:);
}
-''', null);
+''');
}
Future<void> test_argumentList_positional_asNamed_beforeLabel() async {
@@ -266,7 +264,7 @@
void g() {
f(i: ^);
}
-''', null);
+''');
}
Future<void> test_argumentList_requiredPositional_first() async {
@@ -421,7 +419,7 @@
void g(String s) {
var x = ^s.length;
}
-''', null);
+''');
}
Future<void> test_assignmentExpression_withType() async {
@@ -485,7 +483,7 @@
class Foo {
var x =^;
}
-''', null);
+''');
}
Future<void> test_fieldDeclaration_var_impliedType_int() async {
@@ -517,7 +515,7 @@
class Foo {
var x = ^ ;
}
-''', null);
+''');
}
Future<void> test_ifElement() async {
@@ -565,7 +563,7 @@
void f(int e) {
var l = ^<int>[e];
}
-''', null);
+''');
}
Future<void> test_listLiteral_element() async {
@@ -589,7 +587,7 @@
void f(int e) {
var l = <^int>[e];
}
-''', null);
+''');
}
Future<void> test_mapLiteralEntry_key() async {
@@ -633,7 +631,7 @@
void f() {
var m = ^<int, int>{};
}
-''', null);
+''');
}
Future<void> test_setOrMapLiteral_map_element() async {
@@ -649,7 +647,7 @@
void f() {
var m = <int, ^int>{};
}
-''', null);
+''');
}
Future<void> test_setOrMapLiteral_set_beforeTypeParameter() async {
@@ -657,7 +655,7 @@
void f() {
var s = ^<int>{};
}
-''', null);
+''');
}
Future<void> test_setOrMapLiteral_set_element() async {
@@ -673,7 +671,7 @@
void f() {
var s = <^int>{};
}
-''', null);
+''');
}
Future<void> test_topLevelVariableDeclaration_int() async {
@@ -710,26 +708,26 @@
Future<void> test_topLevelVariableDeclaration_var() async {
await assertContextType('''
var x=^;
-''', null);
+''');
}
Future<void> test_topLevelVariableDeclaration_var_noEqual() async {
await assertContextType('''
int x^;
-''', null);
+''');
}
Future<void> test_topLevelVariableDeclaration_var_whitespace() async {
await assertContextType('''
var x= ^ ;
-''', null);
+''');
}
}
abstract class FeatureComputerTest extends AbstractSingleUnitTest {
int cursorIndex = 0;
- CompletionTarget completionTarget;
+ late CompletionTarget completionTarget;
@override
bool verifyNoTestUnitErrors = false;
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart
index c9e33de..c86dc28 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/analysis_options_generator_test.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
-
import 'package:analysis_server/src/services/completion/yaml/analysis_options_generator.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:linter/src/rules.dart';
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart
index 3ded781..4634360 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/fix_data_generator_test.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
-
import 'package:analysis_server/src/services/completion/yaml/fix_data_generator.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 07d2bb7..3df9b93 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.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
-
import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
import 'package:analysis_server/src/services/pub/pub_api.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
@@ -23,9 +21,10 @@
@reflectiveTest
class PubspecGeneratorTest extends YamlGeneratorTest {
- MockHttpClient httpClient;
+ late MockHttpClient httpClient;
- PubPackageService pubPackageService;
+ late PubPackageService pubPackageService;
+
@override
String get fileName => 'pubspec.yaml';
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart b/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart
index e793c59..0d82611 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/test_all.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/test_all.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
-
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'analysis_options_generator_test.dart' as analysis_options_generator;
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart b/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart
index 254a855..90a8df5 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/yaml_generator_test_support.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
-
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
@@ -11,7 +9,7 @@
abstract class YamlGeneratorTest with ResourceProviderMixin {
/// The completion results produced by [getCompletions].
- /* late */ List<CompletionSuggestion> results;
+ late List<CompletionSuggestion> results;
/// Return the name of the file being tested.
String get fileName;
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 547bea6..47717d2 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.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
-
import 'dart:io' as io;
import 'dart:math' as math;
@@ -36,7 +34,6 @@
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:args/args.dart';
-import 'package:meta/meta.dart';
import 'output_utilities.dart';
@@ -83,7 +80,7 @@
}
/// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
if (error != null) {
print(error);
print('');
@@ -271,20 +268,20 @@
InheritanceManager3 inheritanceManager = InheritanceManager3();
/// The library containing the compilation unit being visited.
- LibraryElement enclosingLibrary;
+ late LibraryElement enclosingLibrary;
/// A flag indicating whether we are currently in a context in which type
/// parameters are visible.
bool inGenericContext = false;
/// The type provider associated with the current compilation unit.
- TypeProvider typeProvider;
+ late TypeProvider typeProvider;
/// The type system associated with the current compilation unit.
- TypeSystem typeSystem;
+ late TypeSystem typeSystem;
/// The object used to compute the values of features.
- FeatureComputer featureComputer;
+ late FeatureComputer featureComputer;
/// Initialize a newly created collector to add data points to the given
/// [data].
@@ -461,10 +458,8 @@
inGenericContext = inGenericContext || node.typeParameters != null;
_recordDataForNode('ClassTypeAlias (superclass)', node.superclass);
var context = 'superclass';
- if (node.withClause != null) {
- _recordTokenType('ClassDeclaration ($context)', node.withClause);
- context = 'with';
- }
+ _recordTokenType('ClassDeclaration ($context)', node.withClause);
+ context = 'with';
_recordTokenType('ClassDeclaration ($context)', node.implementsClause);
super.visitClassTypeAlias(node);
inGenericContext = wasInGenericContext;
@@ -489,7 +484,7 @@
@override
void visitCompilationUnit(CompilationUnit node) {
- enclosingLibrary = node.declaredElement.library;
+ enclosingLibrary = node.declaredElement!.library;
typeProvider = enclosingLibrary.typeProvider;
typeSystem = enclosingLibrary.typeSystem;
inheritanceManager = InheritanceManager3();
@@ -510,12 +505,6 @@
data.recordPercentage(
'Compilation units with at least one prefix', hasPrefix);
super.visitCompilationUnit(node);
-
- featureComputer = null;
- inheritanceManager = null;
- typeSystem = null;
- typeProvider = null;
- enclosingLibrary = null;
}
@override
@@ -865,13 +854,14 @@
@override
void visitImportDirective(ImportDirective node) {
var context = 'uri';
- if (node.deferredKeyword != null) {
- data.recordTokenType(
- 'ImportDirective ($context)', node.deferredKeyword.type);
+ var deferredKeyword = node.deferredKeyword;
+ if (deferredKeyword != null) {
+ data.recordTokenType('ImportDirective ($context)', deferredKeyword.type);
context = 'deferred';
}
- if (node.asKeyword != null) {
- data.recordTokenType('ImportDirective ($context)', node.asKeyword.type);
+ var asKeyword = node.asKeyword;
+ if (asKeyword != null) {
+ data.recordTokenType('ImportDirective ($context)', asKeyword.type);
context = 'prefix';
}
if (node.configurations.isNotEmpty) {
@@ -977,7 +967,7 @@
// There are no completions.
data.recordPercentage(
'Methods with type parameters', node.typeParameters != null);
- var element = node.declaredElement;
+ var element = node.declaredElement!;
if (!element.isStatic && element.enclosingElement is ClassElement) {
var overriddenMembers = inheritanceManager.getOverridden2(
element.enclosingElement as ClassElement,
@@ -1293,8 +1283,9 @@
allowedKeywords: [Keyword.ON]);
context = 'catch';
}
- if (node.finallyKeyword != null) {
- data.recordTokenType('TryStatement ($context)', node.finallyKeyword.type);
+ var finallyKeyword = node.finallyKeyword;
+ if (finallyKeyword != null) {
+ data.recordTokenType('TryStatement ($context)', finallyKeyword.type);
}
super.visitTryStatement(node);
}
@@ -1329,7 +1320,7 @@
@override
void visitVariableDeclaration(VariableDeclaration node) {
- var keywords = node.parent.parent is FieldDeclaration
+ var keywords = node.parent?.parent is FieldDeclaration
? [Keyword.COVARIANT, ...expressionKeywords]
: expressionKeywords;
_recordDataForNode('VariableDeclaration (initializer)', node.initializer,
@@ -1375,7 +1366,7 @@
/// Return the context in which the [node] occurs. The [node] is expected to
/// be the parent of the argument expression.
- String _argumentListContext(AstNode node) {
+ String _argumentListContext(AstNode? node) {
if (node is ArgumentList) {
var parent = node.parent;
if (parent is InstanceCreationExpression) {
@@ -1412,17 +1403,17 @@
return 0;
}
var depth = 0;
- var currentElement = element;
+ Element? currentElement = element;
while (currentElement != enclosingLibrary) {
depth++;
- currentElement = currentElement.enclosingElement;
+ currentElement = currentElement?.enclosingElement;
}
return depth;
}
/// Return the first child of the [node] that is neither a comment nor an
/// annotation.
- SyntacticEntity _firstChild(AstNode node) {
+ SyntacticEntity? _firstChild(AstNode node) {
var children = node.childEntities.toList();
for (var i = 0; i < children.length; i++) {
var child = children[i];
@@ -1435,13 +1426,13 @@
/// Return the element associated with the left-most identifier that is a
/// child of the [node].
- Element _leftMostElement(AstNode node) =>
+ Element? _leftMostElement(AstNode node) =>
_leftMostIdentifier(node)?.staticElement;
/// Return the left-most child of the [node] if it is a simple identifier, or
/// `null` if the left-most child is not a simple identifier. Comments and
/// annotations are ignored for this purpose.
- SimpleIdentifier _leftMostIdentifier(AstNode node) {
+ SimpleIdentifier? _leftMostIdentifier(AstNode? node) {
var currentNode = node;
while (currentNode != null && currentNode is! SimpleIdentifier) {
var firstChild = _firstChild(currentNode);
@@ -1451,17 +1442,18 @@
currentNode = null;
}
}
- if (currentNode is SimpleIdentifier && currentNode.inDeclarationContext()) {
- return null;
+ if (currentNode is SimpleIdentifier &&
+ !currentNode.inDeclarationContext()) {
+ return currentNode;
}
- return currentNode;
+ return null;
}
/// Return the element kind of the element associated with the left-most
/// identifier that is a child of the [node].
- ElementKind _leftMostKind(AstNode node) {
+ ElementKind? _leftMostKind(AstNode node) {
if (node is InstanceCreationExpression) {
- return convertElementToElementKind(node.constructorName.staticElement);
+ return convertElementToElementKind(node.constructorName.staticElement!);
}
var element = _leftMostElement(node);
if (element == null) {
@@ -1470,17 +1462,17 @@
if (element is ClassElement) {
var parent = node.parent;
if (parent is Annotation && parent.arguments != null) {
- element = parent.element;
+ element = parent.element!;
}
}
return convertElementToElementKind(element);
}
/// Return the left-most token that is a child of the [node].
- Token _leftMostToken(AstNode node) {
- SyntacticEntity entity = node;
+ Token? _leftMostToken(AstNode node) {
+ SyntacticEntity? entity = node;
while (entity is AstNode) {
- entity = _firstChild(entity as AstNode);
+ entity = _firstChild(entity);
}
if (entity is Token) {
return entity;
@@ -1490,7 +1482,7 @@
/// Return the number of functions between the [reference] and the [function]
/// in which the referenced parameter is declared.
- int _parameterReferenceDepth(AstNode reference, Element function) {
+ int _parameterReferenceDepth(AstNode? reference, Element function) {
var depth = 0;
var node = reference;
while (node != null) {
@@ -1515,7 +1507,7 @@
return -1;
}
- void _recordContextType(DartType type) {
+ void _recordContextType(DartType? type) {
if (type == null) {
data.incrementCount('has no context type');
} else {
@@ -1525,7 +1517,7 @@
/// Record information about the given [node] occurring in the given
/// [context].
- void _recordDataForNode(String context, AstNode node,
+ void _recordDataForNode(String context, AstNode? node,
{List<Keyword> allowedKeywords = noKeywords}) {
_recordElementKind(context, node);
if (inGenericContext) {
@@ -1557,7 +1549,7 @@
/// Record the element kind of the element associated with the left-most
/// identifier that is a child of the [node] in the given [context].
- void _recordElementKind(String context, AstNode node) {
+ void _recordElementKind(String context, AstNode? node) {
if (node != null) {
var kind = _leftMostKind(node);
if (kind != null) {
@@ -1573,7 +1565,7 @@
/// Record the distance between the static type of the target (the
/// [targetType]) and the [member] to which the reference was resolved.
- void _recordMemberDepth(DartType targetType, Element member) {
+ void _recordMemberDepth(DartType? targetType, Element? member) {
if (member == null) {
return;
}
@@ -1593,7 +1585,7 @@
/// superclasses caused by mixins.
int getSuperclassDepth() {
var depth = 0;
- var currentClass = targetClass;
+ ClassElement? currentClass = targetClass;
while (currentClass != null) {
if (currentClass == memberClass) {
return depth;
@@ -1614,7 +1606,7 @@
/// includes all of the implicit superclasses caused by mixins.
int getTargetDepth() {
var depth = 0;
- var currentClass = targetClass;
+ ClassElement? currentClass = targetClass;
while (currentClass != null) {
depth += currentClass.mixins.length + 1;
currentClass = currentClass.supertype?.element;
@@ -1663,8 +1655,8 @@
}
}
- void recordParameterOverride(ParameterElement overrideParameter,
- ParameterElement overriddenParameter) {
+ void recordParameterOverride(ParameterElement? overrideParameter,
+ ParameterElement? overriddenParameter) {
var overrideType = overrideParameter?.type;
var overriddenType = overriddenParameter?.type;
if (overrideType == null ||
@@ -1692,11 +1684,11 @@
/// Record the depth of the element associated with the left-most identifier
/// that is a child of the given [node].
- void _recordReferenceDepth(AstNode node) {
+ void _recordReferenceDepth(AstNode? node) {
var reference = _leftMostIdentifier(node);
var element = reference?.staticElement;
if (element is ParameterElement) {
- var definingElement = element.enclosingElement;
+ var definingElement = element.enclosingElement!;
var depth = _parameterReferenceDepth(node, definingElement);
_recordDistance('function depth of referenced parameter', depth);
} else if (element is LocalVariableElement) {
@@ -1705,7 +1697,9 @@
// additionally measuring the number of function boundaries that are
// crossed and then reporting the distance with a label such as
// 'local variable ($boundaryCount)'.
- var distance = featureComputer.localVariableDistance(node, element);
+ var distance = node == null
+ ? -1
+ : featureComputer.localVariableDistance(node, element);
_recordDistance('distance to local variable', distance);
} else if (element != null) {
// TODO(brianwilkerson) We might want to cross reference the depth of
@@ -1718,20 +1712,20 @@
/// Record the number of tokens between a given identifier and the nearest
/// previous token with the same lexeme.
- void _recordTokenDistance(AstNode node) {
+ void _recordTokenDistance(AstNode? node) {
var identifier = _leftMostIdentifier(node);
if (identifier != null) {
int distance() {
var token = identifier.token;
var lexeme = token.lexeme;
var distance = 1;
- token = token.previous;
+ token = token.previous!;
while (!token.isEof && distance <= 100) {
if (token.lexeme == lexeme) {
return distance;
}
distance++;
- token = token.previous;
+ token = token.previous!;
}
return -1;
}
@@ -1742,13 +1736,13 @@
/// Record the token type of the left-most token that is a child of the
/// [node] in the given [context].
- void _recordTokenType(String context, AstNode node,
+ void _recordTokenType(String context, AstNode? node,
{List<Keyword> allowedKeywords = noKeywords}) {
if (node != null) {
var token = _leftMostToken(node);
if (token != null) {
var type = token.type;
- if (token.isKeyword && token.keyword.isBuiltInOrPseudo) {
+ if (token.isKeyword && token.keyword!.isBuiltInOrPseudo) {
// These keywords can be used as identifiers, so determine whether it
// is being used as a keyword or an identifier.
if (!allowedKeywords.contains(token.keyword)) {
@@ -1851,7 +1845,7 @@
/// Return the return type of the [element], or `null` if the element doesn't
/// have a return type.
- DartType _returnType(Element element) {
+ DartType? _returnType(Element? element) {
if (element is ExecutableElement) {
return element.returnType;
}
@@ -1871,7 +1865,7 @@
/// Compute the metrics for the file(s) in the [rootPath].
/// If [corpus] is true, treat rootPath as a container of packages, creating
/// a new context collection for each subdirectory.
- Future<void> compute(String rootPath, {@required bool verbose}) async {
+ Future<void> compute(String rootPath, {required bool verbose}) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1933,7 +1927,7 @@
/// output if [verbose] is `true`.
Future<void> _computeInContext(
ContextRoot root, RelevanceDataCollector collector,
- {@required bool verbose}) async {
+ {required bool verbose}) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
includedPaths: root.includedPaths.toList(),
@@ -1950,13 +1944,7 @@
//
// Check for errors that cause the file to be skipped.
//
- if (resolvedUnitResult == null) {
- print('File $filePath skipped because resolved unit was null.');
- if (verbose) {
- print('');
- }
- continue;
- } else if (resolvedUnitResult.state != ResultState.VALID) {
+ if (resolvedUnitResult.state != ResultState.VALID) {
print('File $filePath skipped because it could not be analyzed.');
if (verbose) {
print('');
@@ -1976,7 +1964,7 @@
continue;
}
- resolvedUnitResult.unit.accept(collector);
+ resolvedUnitResult.unit!.accept(collector);
} catch (exception, stacktrace) {
print('Exception caught analyzing: "$filePath"');
print(exception);
@@ -2005,7 +1993,7 @@
/// Convert the contents of a single [map] into the values for each row in the
/// column occupied by the map.
- List<String> _convertMap<T extends Object>(String context, Map<T, int> map) {
+ List<String> _convertMap<T extends Object>(String context, Map<T, int>? map) {
var columns = <String>[];
if (map == null) {
return columns;
@@ -2062,13 +2050,15 @@
/// Write a [contextMap] containing one kind of metric data to the [sink].
void _writeContextMap(
StringSink sink, Map<String, Map<String, int>> contextMap) {
- var contexts = contextMap.keys.toList()..sort();
- for (var i = 0; i < contexts.length; i++) {
+ var entries = contextMap.entries.toList()
+ ..sort((first, second) => first.key.compareTo(second.key));
+ for (var i = 0; i < entries.length; i++) {
if (i > 0) {
sink.writeln();
}
- var context = contexts[i];
- var lines = _convertMap(context, contextMap[context]);
+ var context = entries[i].key;
+ var data = entries[i].value;
+ var lines = _convertMap(context, data);
for (var line in lines) {
sink.writeln(' $line');
}
@@ -2132,9 +2122,11 @@
/// Write a [percentageMap] containing one kind of metric data to the [sink].
void _writePercentageData(
StringSink sink, Map<String, _PercentageData> percentageMap) {
- var names = percentageMap.keys.toList()..sort();
- for (var name in names) {
- var data = percentageMap[name];
+ var entries = percentageMap.entries.toList()
+ ..sort((first, second) => first.key.compareTo(second.key));
+ for (var entry in entries) {
+ var name = entry.key;
+ var data = entry.value;
var total = data.total;
var value = data.positive;
var percent = total == 0 ? ' 0.0' : _formatPercent(value, total);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 004c776..e5848fa 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.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
-
import 'dart:convert';
import 'dart:io' as io;
@@ -29,7 +27,6 @@
import 'package:analyzer_utilities/package_root.dart' as package_root;
import 'package:analyzer_utilities/tools.dart';
import 'package:args/args.dart';
-import 'package:meta/meta.dart';
/// Compute metrics to determine whether they should be used to compute a
/// relevance score for completion suggestions.
@@ -123,7 +120,7 @@
}
/// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
if (error != null) {
print(error);
print('');
@@ -195,7 +192,7 @@
if (key.startsWith('e')) {
kind = _ElementKind(ElementKind(key.substring(1)));
} else if (key.startsWith('k')) {
- kind = _Keyword(Keyword.keywords[key.substring(1)]);
+ kind = _Keyword(Keyword.keywords[key.substring(1)]!);
} else {
throw StateError('Invalid initial character in unique key "$key"');
}
@@ -298,21 +295,21 @@
final RelevanceData data;
/// The compilation unit in which data is currently being collected.
- CompilationUnit unit;
+ late CompilationUnit unit;
- InheritanceManager3 inheritanceManager = InheritanceManager3();
+ late InheritanceManager3 inheritanceManager = InheritanceManager3();
/// The library containing the compilation unit being visited.
- LibraryElement enclosingLibrary;
+ late LibraryElement enclosingLibrary;
/// The type provider associated with the current compilation unit.
- TypeProvider typeProvider;
+ late TypeProvider typeProvider;
/// The type system associated with the current compilation unit.
- TypeSystem typeSystem;
+ late TypeSystem typeSystem;
/// The object used to compute the values of features.
- FeatureComputer featureComputer;
+ late FeatureComputer featureComputer;
/// Initialize a newly created collector to add data points to the given
/// [data].
@@ -320,7 +317,7 @@
/// Initialize this collector prior to visiting the unit in the [result].
void initializeFrom(ResolvedUnitResult result) {
- unit = result.unit;
+ unit = result.unit!;
}
@override
@@ -468,10 +465,8 @@
void visitClassTypeAlias(ClassTypeAlias node) {
_recordDataForNode('ClassTypeAlias_superclass', node.superclass);
var context = 'superclass';
- if (node.withClause != null) {
- _recordKeyword('ClassTypeAlias_$context', node.withClause);
- context = 'with';
- }
+ _recordKeyword('ClassTypeAlias_$context', node.withClause);
+ context = 'with';
_recordKeyword('ClassTypeAlias_$context', node.implementsClause);
super.visitClassTypeAlias(node);
}
@@ -490,7 +485,7 @@
@override
void visitCompilationUnit(CompilationUnit node) {
- enclosingLibrary = node.declaredElement.library;
+ enclosingLibrary = node.declaredElement!.library;
typeProvider = enclosingLibrary.typeProvider;
typeSystem = enclosingLibrary.typeSystem;
inheritanceManager = InheritanceManager3();
@@ -505,12 +500,6 @@
allowedKeywords: declarationKeywords);
}
super.visitCompilationUnit(node);
-
- featureComputer = null;
- inheritanceManager = null;
- typeSystem = null;
- typeProvider = null;
- enclosingLibrary = null;
}
@override
@@ -839,12 +828,14 @@
@override
void visitImportDirective(ImportDirective node) {
var context = 'uri';
- if (node.deferredKeyword != null) {
- data.recordKeyword('ImportDirective_$context', node.deferredKeyword.type);
+ var deferredKeyword = node.deferredKeyword;
+ if (deferredKeyword != null) {
+ data.recordKeyword('ImportDirective_$context', deferredKeyword.keyword!);
context = 'deferred';
}
- if (node.asKeyword != null) {
- data.recordKeyword('ImportDirective_$context', node.asKeyword.type);
+ var asKeyword = node.asKeyword;
+ if (asKeyword != null) {
+ data.recordKeyword('ImportDirective_$context', asKeyword.keyword!);
context = 'prefix';
}
if (node.configurations.isNotEmpty) {
@@ -1192,8 +1183,9 @@
allowedKeywords: [Keyword.ON]);
context = 'catch';
}
- if (node.finallyKeyword != null) {
- data.recordKeyword('TryStatement_$context', node.finallyKeyword.type);
+ var finallyKeyword = node.finallyKeyword;
+ if (finallyKeyword != null) {
+ data.recordKeyword('TryStatement_$context', finallyKeyword.keyword!);
}
super.visitTryStatement(node);
}
@@ -1228,7 +1220,7 @@
@override
void visitVariableDeclaration(VariableDeclaration node) {
- var keywords = node.parent.parent is FieldDeclaration
+ var keywords = node.parent?.parent is FieldDeclaration
? [Keyword.COVARIANT, ...expressionKeywords]
: expressionKeywords;
_recordDataForNode('VariableDeclaration_initializer', node.initializer,
@@ -1309,7 +1301,7 @@
/// Return the first child of the [node] that is neither a comment nor an
/// annotation.
- SyntacticEntity _firstChild(AstNode node) {
+ SyntacticEntity? _firstChild(AstNode node) {
var children = node.childEntities.toList();
for (var i = 0; i < children.length; i++) {
var child = children[i];
@@ -1322,14 +1314,14 @@
/// Return the element associated with the left-most identifier that is a
/// child of the [node].
- Element _leftMostElement(AstNode node) =>
+ Element? _leftMostElement(AstNode node) =>
_leftMostIdentifier(node)?.staticElement;
/// Return the left-most child of the [node] if it is a simple identifier, or
/// `null` if the left-most child is not a simple identifier. Comments and
/// annotations are ignored for this purpose.
- SimpleIdentifier _leftMostIdentifier(AstNode node) {
- var currentNode = node;
+ SimpleIdentifier? _leftMostIdentifier(AstNode node) {
+ AstNode? currentNode = node;
while (currentNode != null && currentNode is! SimpleIdentifier) {
var firstChild = _firstChild(currentNode);
if (firstChild is AstNode) {
@@ -1338,18 +1330,19 @@
currentNode = null;
}
}
- if (currentNode is SimpleIdentifier && currentNode.inDeclarationContext()) {
- return null;
+ if (currentNode is SimpleIdentifier &&
+ !currentNode.inDeclarationContext()) {
+ return currentNode;
}
- return currentNode;
+ return null;
}
/// Return the element kind of the element associated with the left-most
/// identifier that is a child of the [node].
- ElementKind _leftMostKind(AstNode node) {
+ ElementKind? _leftMostKind(AstNode node) {
if (node is InstanceCreationExpression) {
return featureComputer
- .computeElementKind(node.constructorName.staticElement);
+ .computeElementKind(node.constructorName.staticElement!);
}
var element = _leftMostElement(node);
if (element == null) {
@@ -1358,17 +1351,17 @@
if (element is ClassElement) {
var parent = node.parent;
if (parent is Annotation && parent.arguments != null) {
- element = parent.element;
+ element = parent.element!;
}
}
return featureComputer.computeElementKind(element);
}
/// Return the left-most token that is a child of the [node].
- Token _leftMostToken(AstNode node) {
- SyntacticEntity entity = node;
+ Token? _leftMostToken(AstNode node) {
+ SyntacticEntity? entity = node;
while (entity is AstNode) {
- entity = _firstChild(entity as AstNode);
+ entity = _firstChild(entity);
}
if (entity is Token) {
return entity;
@@ -1378,7 +1371,7 @@
/// Record information about the given [node] occurring in the given
/// [context].
- void _recordDataForNode(String context, AstNode node,
+ void _recordDataForNode(String context, AstNode? node,
{List<Keyword> allowedKeywords = noKeywords}) {
_recordElementKind(context, node);
_recordKeyword(context, node, allowedKeywords: allowedKeywords);
@@ -1386,7 +1379,7 @@
/// Record the element kind of the element associated with the left-most
/// identifier that is a child of the [node] in the given [context].
- void _recordElementKind(String context, AstNode node) {
+ void _recordElementKind(String context, AstNode? node) {
if (node != null) {
var kind = _leftMostKind(node);
if (kind != null) {
@@ -1402,18 +1395,18 @@
/// If the left-most token of the [node] is a keyword, then record that it
/// occurred in the given [context].
- void _recordKeyword(String context, AstNode node,
+ void _recordKeyword(String context, AstNode? node,
{List<Keyword> allowedKeywords = noKeywords}) {
if (node != null) {
var token = _leftMostToken(node);
- if (token.isKeyword) {
- var keyword = token.type;
+ if (token != null && token.isKeyword) {
+ var keyword = token.keyword!;
if (keyword == Keyword.NEW) {
// We don't suggest `new`, so we don't care about the frequency with
// which it is used.
return;
- } else if (token.keyword.isBuiltInOrPseudo &&
- !allowedKeywords.contains(token.keyword)) {
+ } else if (keyword.isBuiltInOrPseudo &&
+ !allowedKeywords.contains(keyword)) {
// These keywords can be used as identifiers, so determine whether
// it is being used as a keyword or an identifier.
return;
@@ -1436,7 +1429,7 @@
/// Compute the metrics for the file(s) in the [rootPath].
/// If [corpus] is true, treat rootPath as a container of packages, creating
/// a new context collection for each subdirectory.
- Future<void> compute(String rootPath, {@required bool verbose}) async {
+ Future<void> compute(String rootPath, {required bool verbose}) async {
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1453,7 +1446,7 @@
/// output if [verbose] is `true`.
Future<void> _computeInContext(
ContextRoot root, RelevanceDataCollector collector,
- {@required bool verbose}) async {
+ {required bool verbose}) async {
// Create a new collection to avoid consuming large quantities of memory.
final collection = AnalysisContextCollection(
includedPaths: root.includedPaths.toList(),
@@ -1470,13 +1463,7 @@
//
// Check for errors that cause the file to be skipped.
//
- if (resolvedUnitResult == null) {
- print('File $filePath skipped because resolved unit was null.');
- if (verbose) {
- print('');
- }
- continue;
- } else if (resolvedUnitResult.state != ResultState.VALID) {
+ if (resolvedUnitResult.state != ResultState.VALID) {
print('File $filePath skipped because it could not be analyzed.');
if (verbose) {
print('');
@@ -1497,7 +1484,7 @@
}
collector.initializeFrom(resolvedUnitResult);
- resolvedUnitResult.unit.accept(collector);
+ resolvedUnitResult.unit!.accept(collector);
} catch (exception, stacktrace) {
print('Exception caught analyzing: "$filePath"');
print(exception);
@@ -1539,9 +1526,11 @@
''');
var byKind = data.byKind;
- var completionLocations = byKind.keys.toList()..sort();
- for (var completionLocation in completionLocations) {
- var counts = byKind[completionLocation];
+ var entries = byKind.entries.toList()
+ ..sort((first, second) => first.key.compareTo(second.key));
+ for (var entry in entries) {
+ var completionLocation = entry.key;
+ var counts = entry.value;
if (_hasElementKind(counts)) {
var totalCount = _totalCount(counts);
// TODO(brianwilkerson) If two element kinds have the same count they
@@ -1613,9 +1602,11 @@
''');
var byKind = data.byKind;
- var completionLocations = byKind.keys.toList()..sort();
- for (var completionLocation in completionLocations) {
- var counts = byKind[completionLocation];
+ var entries = byKind.entries.toList()
+ ..sort((first, second) => first.key.compareTo(second.key));
+ for (var entry in entries) {
+ var completionLocation = entry.key;
+ var counts = entry.value;
if (_hasKeyword(counts)) {
var totalCount = _totalCount(counts);
// TODO(brianwilkerson) If two keywords have the same count they ought to
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 53c5713..d692e51 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,6 +1,10 @@
-## 1.4.0-dev
+## 1.4.0
* Deprecated `TypeProvider.nonSubtypableClasses`.
Use `TypeProvider.isNonSubtypableClass` instead.
+* Added `sdkPath` to `AnalysisContextCollection` constructor.
+* Improved support for generalized type aliases.
+* The feature `nonfunction-type-aliases` is enabled by default in the
+ language version `2.13`.
## 1.3.0
* Added `Expression.inConstantContext` to API.
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
index 1f95fa7..fa03a7c 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context_collection.dart
@@ -17,10 +17,15 @@
///
/// If a [resourceProvider] is given, then it will be used to access the file
/// system, otherwise the default resource provider will be used.
- factory AnalysisContextCollection(
- {required List<String> includedPaths,
- List<String>? excludedPaths,
- ResourceProvider? resourceProvider}) = AnalysisContextCollectionImpl;
+ ///
+ /// If [sdkPath] is given, then Dart SDK at this path will be used, otherwise
+ /// the default Dart SDK will be used.
+ factory AnalysisContextCollection({
+ required List<String> includedPaths,
+ List<String>? excludedPaths,
+ ResourceProvider? resourceProvider,
+ String? sdkPath,
+ }) = AnalysisContextCollectionImpl;
/// Return all of the analysis contexts in this collection.
List<AnalysisContext> get contexts;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 6d4c820..10eb85c 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 1.4.0-dev
+version: 1.4.0
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -7,7 +7,7 @@
sdk: '>=2.12.0-0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^19.0.0
+ _fe_analyzer_shared: ^20.0.0
cli_util: ^0.3.0
collection: ^1.15.0
convert: ^3.0.0
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 3cad4cb..5abee00 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -235,6 +235,10 @@
static final Uri dart__js_helper =
new Uri(scheme: 'dart', path: '_js_helper');
+ /// The URI for 'dart:_late_helper'.
+ static final Uri dart__late_helper =
+ Uri(scheme: 'dart', path: '_late_helper');
+
/// The URI for 'dart:_rti'.
static final Uri dart__rti = new Uri(scheme: 'dart', path: '_rti');
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 0010e02..81237f8 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -92,6 +92,9 @@
/// The dart:_js_helper library.
LibraryEntity get jsHelperLibrary;
+ /// The dart:_late_helper library
+ LibraryEntity get lateHelperLibrary;
+
/// The dart:_interceptors library.
LibraryEntity get interceptorsLibrary;
@@ -440,7 +443,7 @@
FunctionEntity get defineProperty;
- FunctionEntity get throwLateInitializationError;
+ FunctionEntity get throwLateFieldADI;
bool isExtractTypeArguments(FunctionEntity member);
@@ -773,6 +776,11 @@
LibraryEntity get jsHelperLibrary =>
_jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
+ LibraryEntity _lateHelperLibrary;
+ @override
+ LibraryEntity get lateHelperLibrary =>
+ _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
+
LibraryEntity _interceptorsLibrary;
@override
LibraryEntity get interceptorsLibrary =>
@@ -1521,6 +1529,9 @@
ClassEntity _findHelperClass(String name) =>
_findClass(jsHelperLibrary, name);
+ FunctionEntity _findLateHelperFunction(String name) =>
+ _findLibraryMember(lateHelperLibrary, name);
+
ClassEntity _closureClass;
@override
ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
@@ -1787,8 +1798,8 @@
FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
@override
- FunctionEntity get throwLateInitializationError =>
- _findHelperFunction('throwLateInitializationError');
+ FunctionEntity get throwLateFieldADI =>
+ _findLateHelperFunction('throwLateFieldADI');
@override
bool isExtractTypeArguments(FunctionEntity member) {
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 327156c..3bd71af 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -407,7 +407,7 @@
BackendImpact get lazyField {
return _lazyField ??= new BackendImpact(staticUses: [
_commonElements.cyclicThrowHelper,
- _commonElements.throwLateInitializationError
+ _commonElements.throwLateFieldADI,
]);
}
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 2d30782..b85031c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -190,7 +190,7 @@
if (holder[name] === uninitializedSentinel) {
var value = initializer();
if (holder[name] !== uninitializedSentinel) {
- #throwLateInitializationError(name);
+ #throwLateFieldADI(name);
}
holder[name] = value;
}
@@ -766,8 +766,8 @@
'directAccessTestExpression': js.js(_directAccessTestExpression),
'cyclicThrow': _emitter
.staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
- 'throwLateInitializationError': _emitter.staticFunctionAccess(
- _closedWorld.commonElements.throwLateInitializationError),
+ 'throwLateFieldADI': _emitter
+ .staticFunctionAccess(_closedWorld.commonElements.throwLateFieldADI),
'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
'tearOffCode': new js.Block(buildTearOffCode(
_options, _emitter, _namer, _closedWorld.commonElements)),
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 5849d77..4d42c97 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -1359,6 +1359,7 @@
}
type ??= findIn(Uris.dart_core);
type ??= findIn(Uris.dart__js_helper);
+ type ??= findIn(Uris.dart__late_helper);
type ??= findIn(Uris.dart__interceptors);
type ??= findIn(Uris.dart__native_typed_data);
type ??= findIn(Uris.dart_collection);
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index a0ce422..d41438e 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -57,6 +57,27 @@
return allowedNativeTest(uri) || allowedDartLibrary();
}
+int _foldLateLowerings(List<int> lowerings) =>
+ lowerings.fold(LateLowering.none, (a, b) => a | b);
+
+/// Late lowerings which the frontend performs for dart2js.
+const List<int> _allEnabledLateLowerings = [
+ LateLowering.nullableInitializedNonFinalLocal,
+ LateLowering.nonNullableInitializedNonFinalLocal,
+ LateLowering.nullableInitializedFinalLocal,
+ LateLowering.nonNullableInitializedFinalLocal,
+ LateLowering.uninitializedNonFinalStaticField,
+ LateLowering.uninitializedFinalStaticField,
+ LateLowering.initializedNonFinalStaticField,
+ LateLowering.initializedFinalStaticField,
+ LateLowering.uninitializedNonFinalInstanceField,
+ LateLowering.uninitializedFinalInstanceField,
+ LateLowering.initializedNonFinalInstanceField,
+ LateLowering.initializedFinalInstanceField,
+];
+
+final int _enabledLateLowerings = _foldLateLowerings(_allEnabledLateLowerings);
+
/// A kernel [Target] to configure the Dart Front End for dart2js.
class Dart2jsTarget extends Target {
@override
@@ -72,7 +93,7 @@
bool get enableNoSuchMethodForwarders => true;
@override
- int get enabledLateLowerings => LateLowering.all;
+ final int enabledLateLowerings = _enabledLateLowerings;
@override
bool get supportsLateLoweringSentinel => true;
@@ -96,6 +117,7 @@
'dart:_foreign_helper',
'dart:_interceptors',
'dart:_js_helper',
+ 'dart:_late_helper',
'dart:js_util'
];
@@ -141,8 +163,7 @@
_nativeClasses)
.visitLibrary(library);
}
- lowering.transformLibraries(
- libraries, coreTypes, hierarchy, flags.enableNullSafety);
+ lowering.transformLibraries(libraries, coreTypes, hierarchy);
logger?.call("Lowering transformations performed");
}
@@ -219,6 +240,7 @@
'dart:_js_embedded_names',
'dart:_js_helper',
'dart:_js_names',
+ 'dart:_late_helper',
'dart:_native_typed_data',
'dart:async',
'dart:collection',
@@ -241,6 +263,7 @@
'dart:_js_embedded_names',
'dart:_js_helper',
'dart:_js_names',
+ 'dart:_late_helper',
'dart:_native_typed_data',
'dart:async',
'dart:collection',
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 6f2ba5f..a677ae9 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -942,6 +942,7 @@
}
type ??= findIn(Uris.dart_core);
type ??= findIn(Uris.dart__js_helper);
+ type ??= findIn(Uris.dart__late_helper);
type ??= findIn(Uris.dart__interceptors);
type ??= findIn(Uris.dart__native_typed_data);
type ??= findIn(Uris.dart_collection);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
new file mode 100644
index 0000000..cf5c62c
--- /dev/null
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2021, 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:kernel/ast.dart';
+import 'package:kernel/library_index.dart';
+import 'package:kernel/type_algebra.dart';
+
+bool _shouldLowerVariable(VariableDeclaration node) =>
+ node.initializer == null && node.isLate;
+
+class LateLowering {
+ final Class _cellClass;
+ final Constructor _cellConstructor;
+
+ final Procedure _readLocal;
+ List<TypeParameter> _readLocalTypeParameters;
+ FunctionType _readLocalTypeWithoutTypeParameters;
+
+ final Procedure _setValue;
+ final Procedure _setFinalLocalValue;
+
+ final Map<VariableDeclaration, VariableDeclaration> _cells = {};
+
+ Member _contextMember;
+
+ LateLowering(LibraryIndex index)
+ : _cellClass = index.getClass('dart:_late_helper', '_Cell'),
+ _cellConstructor = index.getMember('dart:_late_helper', '_Cell', ''),
+ _readLocal = index.getMember('dart:_late_helper', '_Cell', 'readLocal'),
+ _setValue = index.getMember('dart:_late_helper', '_Cell', 'set:value'),
+ _setFinalLocalValue = index.getMember(
+ 'dart:_late_helper', '_Cell', 'set:finalLocalValue') {
+ FunctionType _readLocalType = _readLocal.getterType;
+ _readLocalTypeParameters = _readLocalType.typeParameters;
+ _readLocalTypeWithoutTypeParameters = _readLocalType.withoutTypeParameters;
+ }
+
+ VariableDeclaration _variableCell(VariableDeclaration variable) {
+ assert(_shouldLowerVariable(variable));
+ return _cells.putIfAbsent(variable, () {
+ int fileOffset = variable.fileOffset;
+ return VariableDeclaration(variable.name,
+ initializer:
+ ConstructorInvocation(_cellConstructor, Arguments.empty())
+ ..fileOffset = fileOffset,
+ type: InterfaceType(
+ _cellClass, _contextMember.enclosingLibrary.nonNullable),
+ isFinal: true)
+ ..fileOffset = fileOffset;
+ });
+ }
+
+ VariableGet _variableCellAccess(
+ VariableDeclaration variable, int fileOffset) =>
+ VariableGet(_variableCell(variable))..fileOffset = fileOffset;
+
+ TreeNode transformVariableDeclaration(
+ VariableDeclaration node, Member contextMember) {
+ _contextMember = contextMember;
+
+ if (!_shouldLowerVariable(node)) return node;
+
+ // A [VariableDeclaration] being used as a statement must be a direct child
+ // of a [Block].
+ if (node.parent is! Block) return node;
+
+ return _variableCell(node);
+ }
+
+ TreeNode transformVariableGet(VariableGet node, Member contextMember) {
+ _contextMember = contextMember;
+
+ VariableDeclaration variable = node.variable;
+ if (!_shouldLowerVariable(variable)) return node;
+
+ int fileOffset = node.fileOffset;
+ VariableGet cell = _variableCellAccess(variable, fileOffset);
+ List<DartType> typeArguments = [node.promotedType ?? variable.type];
+ return InstanceInvocation(
+ InstanceAccessKind.Instance,
+ cell,
+ _readLocal.name,
+ Arguments(const [], types: typeArguments)..fileOffset = fileOffset,
+ interfaceTarget: _readLocal,
+ functionType:
+ Substitution.fromPairs(_readLocalTypeParameters, typeArguments)
+ .substituteType(_readLocalTypeWithoutTypeParameters))
+ ..fileOffset = fileOffset;
+ }
+
+ TreeNode transformVariableSet(VariableSet node, Member contextMember) {
+ _contextMember = contextMember;
+
+ VariableDeclaration variable = node.variable;
+ if (!_shouldLowerVariable(variable)) return node;
+
+ int fileOffset = node.fileOffset;
+ VariableGet cell = _variableCellAccess(variable, fileOffset);
+ if (variable.isFinal) {
+ return InstanceSet(InstanceAccessKind.Instance, cell,
+ _setFinalLocalValue.name, node.value,
+ interfaceTarget: _setFinalLocalValue)
+ ..fileOffset = fileOffset;
+ } else {
+ return InstanceSet(
+ InstanceAccessKind.Instance, cell, _setValue.name, node.value,
+ interfaceTarget: _setValue)
+ ..fileOffset = fileOffset;
+ }
+ }
+}
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index 72c4f15..915c5fb 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
@@ -5,52 +5,57 @@
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_environment.dart'
- show StaticTypeContext, TypeEnvironment;
import 'factory_specializer.dart';
+import 'late_lowering.dart';
/// dart2js-specific lowering transformations and optimizations combined into a
/// single transformation pass.
///
/// Each transformation is applied locally to AST nodes of certain types after
/// transforming children nodes.
-void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
- ClassHierarchy hierarchy, bool nullSafety) {
- final transformer = _Lowering(coreTypes, hierarchy, nullSafety);
+void transformLibraries(
+ List<Library> libraries, CoreTypes coreTypes, ClassHierarchy hierarchy) {
+ final transformer = _Lowering(coreTypes, hierarchy);
libraries.forEach(transformer.visitLibrary);
}
class _Lowering extends Transformer {
- final TypeEnvironment env;
- final bool nullSafety;
final FactorySpecializer factorySpecializer;
+ final LateLowering _lateLowering;
Member _currentMember;
- StaticTypeContext _cachedStaticTypeContext;
- _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
- : env = TypeEnvironment(coreTypes, hierarchy),
- factorySpecializer = FactorySpecializer(coreTypes, hierarchy);
-
- // ignore: unused_element
- StaticTypeContext get _staticTypeContext =>
- _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
+ _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy)
+ : factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
+ _lateLowering = LateLowering(coreTypes.index);
@override
- defaultMember(Member node) {
+ TreeNode defaultMember(Member node) {
_currentMember = node;
- _cachedStaticTypeContext = null;
-
- final result = super.defaultMember(node);
-
- _currentMember = null;
- _cachedStaticTypeContext = null;
- return result;
+ return super.defaultMember(node);
}
@override
- visitStaticInvocation(StaticInvocation node) {
+ TreeNode visitStaticInvocation(StaticInvocation node) {
node.transformChildren(this);
return factorySpecializer.transformStaticInvocation(node, _currentMember);
}
+
+ @override
+ TreeNode visitVariableDeclaration(VariableDeclaration node) {
+ node.transformChildren(this);
+ return _lateLowering.transformVariableDeclaration(node, _currentMember);
+ }
+
+ @override
+ TreeNode visitVariableGet(VariableGet node) {
+ node.transformChildren(this);
+ return _lateLowering.transformVariableGet(node, _currentMember);
+ }
+
+ @override
+ TreeNode visitVariableSet(VariableSet node) {
+ node.transformChildren(this);
+ return _lateLowering.transformVariableSet(node, _currentMember);
+ }
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 864f6a8..a729f53 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -463,7 +463,7 @@
closedWorld.commonElements.cyclicThrowHelper,
CallStructure.ONE_ARG));
registry.registerStaticUse(new StaticUse.staticInvoke(
- closedWorld.commonElements.throwLateInitializationError,
+ closedWorld.commonElements.throwLateFieldADI,
CallStructure.ONE_ARG));
}
if (targetElement.isInstanceMember) {
diff --git a/pkg/compiler/test/impact/data/invokes.dart b/pkg/compiler/test/impact/data/invokes.dart
index 6702f0c..a95e117 100644
--- a/pkg/compiler/test/impact/data/invokes.dart
+++ b/pkg/compiler/test/impact/data/invokes.dart
@@ -591,7 +591,7 @@
/*member: topLevelFieldLazy:
static=[
throwCyclicInit(1),
- throwLateInitializationError(1),
+ throwLateFieldADI(1),
topLevelFunction1(1)],
type=[inst:JSNull]
*/
@@ -608,7 +608,7 @@
/*member: topLevelFieldFinal:
static=[
throwCyclicInit(1),
- throwLateInitializationError(1),
+ throwLateFieldADI(1),
topLevelFunction1(1)],
type=[inst:JSNull]
*/
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index dcec2b1..cf0461a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5294,8 +5294,9 @@
// Inline `debugger()` with no arguments, as a statement if possible,
// otherwise as an immediately invoked function.
return isStatement
- ? js.statement('debugger;')
- : js.call('(() => { debugger; return true})()');
+ ? js_ast.DebuggerStatement()
+ : js.call(
+ '(() => { #; return true})()', [js_ast.DebuggerStatement()]);
}
// The signature of `debugger()` is:
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
new file mode 100644
index 0000000..4a82e37
--- /dev/null
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.9
+
+import 'dart:developer';
+
+void main() {
+ print('1');
+ /*sl:1*/ debugger();
+ print('2');
+ /*sl:2*/ debugger();
+ print('3');
+ foo(/*s:3*/ debugger());
+ print('4');
+ /*sl:4*/ debugger();
+ print('5');
+ foo(/*s:5*/ debugger());
+ print('6');
+ foo(/*s:6*/ debugger());
+}
+
+void foo(bool _) => null;
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 4e0e710..aa44eb0 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -786,6 +786,32 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
+ Message Function(Constant _constant, bool isNonNullableByDefault)>
+ templateConstEvalUnhandledException = const Template<
+ Message Function(Constant _constant, bool isNonNullableByDefault)>(
+ messageTemplate: r"""Unhandled exception: #constant""",
+ withArguments: _withArgumentsConstEvalUnhandledException);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
+ codeConstEvalUnhandledException = const Code<
+ Message Function(Constant _constant, bool isNonNullableByDefault)>(
+ "ConstEvalUnhandledException",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalUnhandledException(
+ Constant _constant, bool isNonNullableByDefault) {
+ TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+ List<Object> constantParts = labeler.labelConstant(_constant);
+ String constant = constantParts.join();
+ return new Message(codeConstEvalUnhandledException,
+ message: """Unhandled exception: ${constant}""" + labeler.originMessages,
+ arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
Message Function(
DartType _type,
String name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 5178dfa..97f21f3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -69,6 +69,7 @@
templateConstEvalInvalidSymbolName,
templateConstEvalKeyImplementsEqual,
templateConstEvalNonConstantVariableGet,
+ templateConstEvalUnhandledException,
templateConstEvalZeroDivisor;
import 'constant_int_folder.dart';
@@ -1003,6 +1004,24 @@
..fileOffset = node.fileOffset;
errorReporter.reportInvalidExpression(invalid);
return new UnevaluatedConstant(invalid);
+ } else if (result is _AbortDueToThrowConstant) {
+ final Message message = templateConstEvalUnhandledException
+ .withArguments(result.throwValue, isNonNullableByDefault);
+ final Uri uri = getFileUri(result.node);
+ final int fileOffset = getFileOffset(uri, result.node);
+ final LocatedMessage locatedMessageActualError =
+ message.withLocation(uri, fileOffset, noLength);
+ final List<LocatedMessage> contextMessages = <LocatedMessage>[
+ locatedMessageActualError
+ ];
+ {
+ final Uri uri = getFileUri(node);
+ final int fileOffset = getFileOffset(uri, node);
+ final LocatedMessage locatedMessage = messageConstEvalStartingPoint
+ .withLocation(uri, fileOffset, noLength);
+ errorReporter.report(locatedMessage, contextMessages);
+ }
+ return new UnevaluatedConstant(new InvalidExpression(message.message));
}
throw "Unexpected error constant";
}
@@ -2953,6 +2972,16 @@
}
@override
+ Constant visitThrow(Throw node) {
+ if (enableConstFunctions) {
+ final Constant value = _evaluateSubexpression(node.expression);
+ if (value is AbortConstant) return value;
+ return new _AbortDueToThrowConstant(node, value);
+ }
+ return defaultExpression(node);
+ }
+
+ @override
Constant visitInstantiation(Instantiation node) {
final Constant constant = _evaluateSubexpression(node.expression);
if (constant is AbortConstant) return constant;
@@ -3329,9 +3358,6 @@
@override
Constant visitThisExpression(ThisExpression node) => defaultExpression(node);
-
- @override
- Constant visitThrow(Throw node) => defaultExpression(node);
}
class StatementConstantEvaluator extends StatementVisitor<ExecutionStatus> {
@@ -3478,6 +3504,42 @@
}
@override
+ ExecutionStatus visitTryCatch(TryCatch node) {
+ final ExecutionStatus tryStatus = node.body.accept(this);
+ if (tryStatus is AbortStatus) {
+ final Constant error = tryStatus.error;
+ if (error is _AbortDueToThrowConstant) {
+ final Constant throwConstant = error.throwValue;
+ final DartType defaultType =
+ exprEvaluator.typeEnvironment.coreTypes.objectNonNullableRawType;
+ for (Catch catchClause in node.catches) {
+ if (exprEvaluator.isSubtype(throwConstant, catchClause.guard,
+ SubtypeCheckMode.withNullabilities) ||
+ catchClause.guard == defaultType) {
+ return exprEvaluator.withNewEnvironment(() {
+ if (catchClause.exception != null) {
+ exprEvaluator.env
+ .addVariableValue(catchClause.exception, throwConstant);
+ }
+ // TODO(kallentu): Store appropriate stack trace in environment.
+ return catchClause.body.accept(this);
+ });
+ }
+ }
+ }
+ }
+ return tryStatus;
+ }
+
+ @override
+ ExecutionStatus visitTryFinally(TryFinally node) {
+ final ExecutionStatus tryStatus = node.body.accept(this);
+ final ExecutionStatus finallyStatus = node.finalizer.accept(this);
+ if (finallyStatus is! ProceedStatus) return finallyStatus;
+ return tryStatus;
+ }
+
+ @override
ExecutionStatus visitVariableDeclaration(VariableDeclaration node) {
Constant value = evaluate(node.initializer);
if (value is AbortConstant) return new AbortStatus(value);
@@ -3852,6 +3914,63 @@
}
}
+class _AbortDueToThrowConstant extends AbortConstant {
+ final Throw node;
+ final Constant throwValue;
+
+ _AbortDueToThrowConstant(this.node, this.throwValue);
+
+ @override
+ R accept<R>(ConstantVisitor<R> v) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ R acceptReference<R>(Visitor<R> v) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ Expression asExpression() {
+ throw new UnimplementedError();
+ }
+
+ @override
+ DartType getType(StaticTypeContext context) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ String leakingDebugToString() {
+ throw new UnimplementedError();
+ }
+
+ @override
+ String toString() {
+ throw new UnimplementedError();
+ }
+
+ @override
+ String toStringInternal() {
+ throw new UnimplementedError();
+ }
+
+ @override
+ String toText(AstTextStrategy strategy) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ throw new UnimplementedError();
+ }
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ throw new UnimplementedError();
+ }
+}
+
abstract class ErrorReporter {
const ErrorReporter();
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 624830e..a8965ac 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -135,6 +135,8 @@
ConstEvalTruncateError/example: Fail
ConstEvalUnevaluated/analyzerCode: Fail
ConstEvalUnevaluated/example: Fail
+ConstEvalUnhandledException/analyzerCode: Fail
+ConstEvalUnhandledException/example: Fail
ConstEvalZeroDivisor/example: Fail
ConstFieldWithoutInitializer/example: Fail
ConstructorNotFound/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index b1ae496..0226a47 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -219,6 +219,9 @@
ConstEvalUnevaluated:
template: "Couldn't evaluate constant expression."
+ConstEvalUnhandledException:
+ template: "Unhandled exception: #constant"
+
NotConstantExpression:
template: "#string is not a constant expression."
analyzerCode: NOT_CONSTANT_EXPRESSION
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart
new file mode 100644
index 0000000..130be7d
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2021, 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.
+
+// Tests try-catch and try-finally with const functions.
+
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+const var2 = fn(1);
+int fn(dynamic error) {
+ try {
+ throw error;
+ } on String {
+ return 0;
+ } catch (e) {
+ return 1;
+ }
+}
+
+const var3 = fn1(10);
+const var4 = fn1("s");
+int fn1(dynamic error) {
+ try {
+ throw error;
+ } on int catch (e) {
+ return e;
+ } catch (e) {
+ return 1;
+ }
+}
+
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+int finallyReturn(dynamic error) {
+ try {
+ if (error != 1) throw error;
+ } on int catch (e) {
+ return e;
+ } catch (e) {
+ return 1;
+ } finally {
+ return 100;
+ }
+}
+
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyReturn1(int x) {
+ try {
+ if (x == 1) {
+ throw x;
+ } else {
+ return 0;
+ }
+ } finally {
+ return 100;
+ }
+}
+
+const var10 = finallyMutate();
+int finallyMutate() {
+ int x = 0;
+ try {
+ return x;
+ } finally {
+ x++;
+ }
+}
+
+const var11 = subtypeFn();
+int subtypeFn() {
+ try {
+ throw 2.5;
+ } on num catch (e) {
+ return 0;
+ }
+}
+
+const var12 = orderFn();
+String orderFn() {
+ String x = "st";
+ try {
+ x += "ri";
+ throw 2;
+ } catch (e) {
+ x += "n";
+ } finally {
+ return x + "g";
+ }
+}
+
+const var13 = notThrowStatement();
+int notThrowStatement() {
+ int count = 0;
+ try {
+ for (int i = 0; i < 1; throw 'a') {
+ count += i;
+ }
+ } catch (e) {
+ return 1;
+ }
+ return 0;
+}
+
+void main() {
+ Expect.equals(var1, 0);
+ Expect.equals(var2, 1);
+ Expect.equals(var3, 10);
+ Expect.equals(var4, 1);
+ Expect.equals(var5, 100);
+ Expect.equals(var6, 100);
+ Expect.equals(var7, 100);
+ Expect.equals(var8, 100);
+ Expect.equals(var9, 100);
+ Expect.equals(var10, 0);
+ Expect.equals(var11, 0);
+ Expect.equals(var12, "string");
+ Expect.equals(var13, 1);
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::String catch(no-exception-var) {
+ return 0;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method fn1(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method finallyReturn(dynamic error) → core::int {
+ try
+ try {
+ if(!error.{core::Object::==}(1))
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyReturn1(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyMutate() → core::int {
+ core::int x = 0;
+ try {
+ return x;
+ }
+ finally {
+ x = x.{core::num::+}(1);
+ }
+}
+static method subtypeFn() → core::int {
+ try {
+ throw 2.5;
+ }
+ on core::num catch(final core::num e) {
+ return 0;
+ }
+}
+static method orderFn() → core::String {
+ core::String x = "st";
+ try
+ try {
+ x = x.{core::String::+}("ri");
+ throw 2;
+ }
+ on core::Object catch(final core::Object e) {
+ x = x.{core::String::+}("n");
+ }
+ finally {
+ return x.{core::String::+}("g");
+ }
+}
+static method notThrowStatement() → core::int {
+ core::int count = 0;
+ try {
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ return 0;
+}
+static method main() → void {
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C3, 10);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C5, "string");
+ exp::Expect::equals(#C2, 1);
+}
+
+constants {
+ #C1 = 0
+ #C2 = 1
+ #C3 = 10
+ #C4 = 100
+ #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.strong.transformed.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::String catch(no-exception-var) {
+ return 0;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method fn1(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method finallyReturn(dynamic error) → core::int {
+ try
+ try {
+ if(!error.{core::Object::==}(1))
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyReturn1(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyMutate() → core::int {
+ core::int x = 0;
+ try {
+ return x;
+ }
+ finally {
+ x = x.{core::num::+}(1);
+ }
+}
+static method subtypeFn() → core::int {
+ try {
+ throw 2.5;
+ }
+ on core::num catch(final core::num e) {
+ return 0;
+ }
+}
+static method orderFn() → core::String {
+ core::String x = "st";
+ try
+ try {
+ x = x.{core::String::+}("ri");
+ throw 2;
+ }
+ on core::Object catch(final core::Object e) {
+ x = x.{core::String::+}("n");
+ }
+ finally {
+ return x.{core::String::+}("g");
+ }
+}
+static method notThrowStatement() → core::int {
+ core::int count = 0;
+ try {
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ return 0;
+}
+static method main() → void {
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C3, 10);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C5, "string");
+ exp::Expect::equals(#C2, 1);
+}
+
+constants {
+ #C1 = 0
+ #C2 = 1
+ #C3 = 10
+ #C4 = 100
+ #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect
new file mode 100644
index 0000000..f52793b
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+const var2 = fn(1);
+int fn(dynamic error) {}
+const var3 = fn1(10);
+const var4 = fn1("s");
+int fn1(dynamic error) {}
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+int finallyReturn(dynamic error) {}
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyReturn1(int x) {}
+const var10 = finallyMutate();
+int finallyMutate() {}
+const var11 = subtypeFn();
+int subtypeFn() {}
+const var12 = orderFn();
+String orderFn() {}
+const var13 = notThrowStatement();
+int notThrowStatement() {}
+void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f69f0de
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+import "package:expect/expect.dart";
+
+String orderFn() {}
+const var1 = fn("s");
+const var10 = finallyMutate();
+const var11 = subtypeFn();
+const var12 = orderFn();
+const var13 = notThrowStatement();
+const var2 = fn(1);
+const var3 = fn1(10);
+const var4 = fn1("s");
+const var5 = finallyReturn(10);
+const var6 = finallyReturn("s");
+const var7 = finallyReturn(1);
+const var8 = finallyReturn1(0);
+const var9 = finallyReturn1(1);
+int finallyMutate() {}
+int finallyReturn(dynamic error) {}
+int finallyReturn1(int x) {}
+int fn(dynamic error) {}
+int fn1(dynamic error) {}
+int notThrowStatement() {}
+int subtypeFn() {}
+void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::String catch(no-exception-var) {
+ return 0;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method fn1(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method finallyReturn(dynamic error) → core::int {
+ try
+ try {
+ if(!error.{core::Object::==}(1))
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyReturn1(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyMutate() → core::int {
+ core::int x = 0;
+ try {
+ return x;
+ }
+ finally {
+ x = x.{core::num::+}(1);
+ }
+}
+static method subtypeFn() → core::int {
+ try {
+ throw 2.5;
+ }
+ on core::num catch(final core::num e) {
+ return 0;
+ }
+}
+static method orderFn() → core::String {
+ core::String x = "st";
+ try
+ try {
+ x = x.{core::String::+}("ri");
+ throw 2;
+ }
+ on core::Object catch(final core::Object e) {
+ x = x.{core::String::+}("n");
+ }
+ finally {
+ return x.{core::String::+}("g");
+ }
+}
+static method notThrowStatement() → core::int {
+ core::int count = 0;
+ try {
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ return 0;
+}
+static method main() → void {
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C3, 10);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C5, "string");
+ exp::Expect::equals(#C2, 1);
+}
+
+constants {
+ #C1 = 0
+ #C2 = 1
+ #C3 = 10
+ #C4 = 100
+ #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect
new file mode 100644
index 0000000..36bf8ab
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = self::fn("s");
+static const field core::int var2 = self::fn(1);
+static const field core::int var3 = self::fn1(10);
+static const field core::int var4 = self::fn1("s");
+static const field core::int var5 = self::finallyReturn(10);
+static const field core::int var6 = self::finallyReturn("s");
+static const field core::int var7 = self::finallyReturn(1);
+static const field core::int var8 = self::finallyReturn1(0);
+static const field core::int var9 = self::finallyReturn1(1);
+static const field core::int var10 = self::finallyMutate();
+static const field core::int var11 = self::subtypeFn();
+static const field core::String var12 = self::orderFn();
+static const field core::int var13 = self::notThrowStatement();
+static method fn(dynamic error) → core::int
+ ;
+static method fn1(dynamic error) → core::int
+ ;
+static method finallyReturn(dynamic error) → core::int
+ ;
+static method finallyReturn1(core::int x) → core::int
+ ;
+static method finallyMutate() → core::int
+ ;
+static method subtypeFn() → core::int
+ ;
+static method orderFn() → core::String
+ ;
+static method notThrowStatement() → core::int
+ ;
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect
new file mode 100644
index 0000000..1d0bf2c
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally.dart.weak.transformed.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = #C1;
+static const field core::int var2 = #C2;
+static const field core::int var3 = #C3;
+static const field core::int var4 = #C2;
+static const field core::int var5 = #C4;
+static const field core::int var6 = #C4;
+static const field core::int var7 = #C4;
+static const field core::int var8 = #C4;
+static const field core::int var9 = #C4;
+static const field core::int var10 = #C1;
+static const field core::int var11 = #C1;
+static const field core::String var12 = #C5;
+static const field core::int var13 = #C2;
+static method fn(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::String catch(no-exception-var) {
+ return 0;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method fn1(dynamic error) → core::int {
+ try {
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+}
+static method finallyReturn(dynamic error) → core::int {
+ try
+ try {
+ if(!error.{core::Object::==}(1))
+ throw error;
+ }
+ on core::int catch(final core::int e) {
+ return e;
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyReturn1(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ return 100;
+ }
+}
+static method finallyMutate() → core::int {
+ core::int x = 0;
+ try {
+ return x;
+ }
+ finally {
+ x = x.{core::num::+}(1);
+ }
+}
+static method subtypeFn() → core::int {
+ try {
+ throw 2.5;
+ }
+ on core::num catch(final core::num e) {
+ return 0;
+ }
+}
+static method orderFn() → core::String {
+ core::String x = "st";
+ try
+ try {
+ x = x.{core::String::+}("ri");
+ throw 2;
+ }
+ on core::Object catch(final core::Object e) {
+ x = x.{core::String::+}("n");
+ }
+ finally {
+ return x.{core::String::+}("g");
+ }
+}
+static method notThrowStatement() → core::int {
+ core::int count = 0;
+ try {
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ }
+ on core::Object catch(final core::Object e) {
+ return 1;
+ }
+ return 0;
+}
+static method main() → void {
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C3, 10);
+ exp::Expect::equals(#C2, 1);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C4, 100);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C1, 0);
+ exp::Expect::equals(#C5, "string");
+ exp::Expect::equals(#C2, 1);
+}
+
+constants {
+ #C1 = 0
+ #C2 = 1
+ #C3 = 10
+ #C4 = 100
+ #C5 = "string"
+}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart
new file mode 100644
index 0000000..706483b
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2021, 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.
+
+// Tests erroneous try-catch and try-finally with const functions.
+
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+int finallyThrow(int x) {
+ try {
+ if (x == 1) {
+ throw x;
+ } else {
+ return 0;
+ }
+ } finally {
+ throw 2;
+ }
+}
+
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+int unhandledThrow(dynamic x) {
+ try {
+ throw x;
+ } on String catch (e) {
+ throw e;
+ }
+}
+
+const var5 = unhandledThrow2();
+int unhandledThrow2() {
+ int count = 0;
+ for (int i = 0; i < 1; throw 'a') {
+ count += i;
+ }
+ return 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+// throw x;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+// throw e;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+// for (int i = 0; i < 1; throw 'a') {
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ throw 2;
+ }
+}
+static method unhandledThrow(dynamic x) → core::int {
+ try {
+ throw x;
+ }
+ on core::String catch(final core::String e) {
+ throw e;
+ }
+}
+static method unhandledThrow2() → core::int {
+ core::int count = 0;
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.strong.transformed.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+// throw x;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+// throw e;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+// for (int i = 0; i < 1; throw 'a') {
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ throw 2;
+ }
+}
+static method unhandledThrow(dynamic x) → core::int {
+ try {
+ throw x;
+ }
+ on core::String catch(final core::String e) {
+ throw e;
+ }
+}
+static method unhandledThrow2() → core::int {
+ core::int count = 0;
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect
new file mode 100644
index 0000000..d2e07cc
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+int finallyThrow(int x) {}
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+int unhandledThrow(dynamic x) {}
+const var5 = unhandledThrow2();
+int unhandledThrow2() {}
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..73e5e70
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+const var2 = finallyThrow(1);
+const var3 = unhandledThrow(0);
+const var4 = unhandledThrow("string");
+const var5 = unhandledThrow2();
+int finallyThrow(int x) {}
+int unhandledThrow(dynamic x) {}
+int unhandledThrow2() {}
+main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+// throw x;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+// throw e;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+// for (int i = 0; i < 1; throw 'a') {
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ throw 2;
+ }
+}
+static method unhandledThrow(dynamic x) → core::int {
+ try {
+ throw x;
+ }
+ on core::String catch(final core::String e) {
+ throw e;
+ }
+}
+static method unhandledThrow2() → core::int {
+ core::int count = 0;
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect
new file mode 100644
index 0000000..62a0b0a
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = self::finallyThrow(0);
+static const field core::int var2 = self::finallyThrow(1);
+static const field core::int var3 = self::unhandledThrow(0);
+static const field core::int var4 = self::unhandledThrow("string");
+static const field core::int var5 = self::unhandledThrow2();
+static method finallyThrow(core::int x) → core::int
+ ;
+static method unhandledThrow(dynamic x) → core::int
+ ;
+static method unhandledThrow2() → core::int
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect
new file mode 100644
index 0000000..3126895
--- /dev/null
+++ b/pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart.weak.transformed.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:9:14: Error: Constant evaluation error:
+// const var1 = finallyThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:10:14: Error: Constant evaluation error:
+// const var2 = finallyThrow(1);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:19:5: Context: Unhandled exception: 2
+// throw 2;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:23:14: Error: Constant evaluation error:
+// const var3 = unhandledThrow(0);
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:27:5: Context: Unhandled exception: 0
+// throw x;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:24:14: Error: Constant evaluation error:
+// const var4 = unhandledThrow("string");
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:29:5: Context: Unhandled exception: "string"
+// throw e;
+// ^
+//
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:33:14: Error: Constant evaluation error:
+// const var5 = unhandledThrow2();
+// ^
+// pkg/front_end/testcases/const_functions/const_functions_try_catch_finally_error.dart:36:26: Context: Unhandled exception: "a"
+// for (int i = 0; i < 1; throw 'a') {
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static const field core::int var1 = invalid-expression "Unhandled exception: 2";
+static const field core::int var2 = invalid-expression "Unhandled exception: 2";
+static const field core::int var3 = invalid-expression "Unhandled exception: 0";
+static const field core::int var4 = invalid-expression "Unhandled exception: \"string\"";
+static const field core::int var5 = invalid-expression "Unhandled exception: \"a\"";
+static method finallyThrow(core::int x) → core::int {
+ try {
+ if(x.{core::num::==}(1)) {
+ throw x;
+ }
+ else {
+ return 0;
+ }
+ }
+ finally {
+ throw 2;
+ }
+}
+static method unhandledThrow(dynamic x) → core::int {
+ try {
+ throw x;
+ }
+ on core::String catch(final core::String e) {
+ throw e;
+ }
+}
+static method unhandledThrow2() → core::int {
+ core::int count = 0;
+ for (core::int i = 0; i.{core::num::<}(1); throw "a") {
+ count = count.{core::num::+}(i);
+ }
+ return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
index fe43261..e90385e 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
@@ -14,61 +14,39 @@
self::testNonNullableInitializedFinalLocal();
}
static method testNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
- function #x#set(core::int? #t2) → dynamic
- return #x = #t2;
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ late core::int? x;
+ x = 42;
+ core::print(x{core::int});
}
static method testNonNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x;
- function #x#get() → core::int
- return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
- function #x#set(core::int #t4) → dynamic
- return #x = #t4;
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ late core::int x;
+ x = 42;
+ core::print(x);
}
static method testNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
- function #x#set(core::int? #t6) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t6;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ late final core::int? x;
+ x = 42;
+ core::print(x{core::int});
}
static method testNonNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x;
- function #x#get() → core::int
- return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
- function #x#set(core::int #t8) → dynamic
- if(#x == null)
- return #x = #t8;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ late final core::int x;
+ x = 42;
+ core::print(x);
}
static method testNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
- function #x#set(core::int? #t10) → dynamic
- return #x = #t10;
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
core::print(#x#get(){() → core::int?});
#x#set(42){(core::int?) → dynamic};
core::print(#x#get(){() → core::int?});
lowered core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
- function #y#set(core::int? #t12) → dynamic
- return #y = #t12;
+ return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+ function #y#set(core::int? #t4) → dynamic
+ return #y = #t4;
core::print(#y#get(){() → core::int?});
#y#set(42){(core::int?) → dynamic};
core::print(#y#get(){() → core::int?});
@@ -76,9 +54,9 @@
static method testNonNullableInitializedNonFinalLocal() → void {
lowered core::int? #x;
function #x#get() → core::int
- return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
- function #x#set(core::int #t14) → dynamic
- return #x = #t14;
+ return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ function #x#set(core::int #t6) → dynamic
+ return #x = #t6;
core::print(#x#get(){() → core::int});
#x#set(42){(core::int) → dynamic};
core::print(#x#get(){() → core::int});
@@ -86,16 +64,16 @@
static method testNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
core::print(#x#get(){() → core::int?});
lowered final core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
core::print(#y#get(){() → core::int?});
}
static method testNonNullableInitializedFinalLocal() → void {
lowered final core::int? #x;
function #x#get() → core::int
- return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+ return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
core::print(#x#get(){() → core::int});
}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
index ac86677..54ef534 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
library /*isNonNullableByDefault*/;
import self as self;
+import "dart:_late_helper" as _la;
import "dart:core" as core;
import "dart:_internal" as _in;
@@ -14,61 +15,39 @@
self::testNonNullableInitializedFinalLocal();
}
static method testNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
- function #x#set(core::int? #t2) → dynamic
- return #x = #t2;
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::value} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNonNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x;
- function #x#get() → core::int
- return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
- function #x#set(core::int #t4) → dynamic
- return #x = #t4;
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::value} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
- function #x#set(core::int? #t6) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t6;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::finalLocalValue} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNonNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x;
- function #x#get() → core::int
- return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
- function #x#set(core::int #t8) → dynamic
- if(#x == null)
- return #x = #t8;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::finalLocalValue} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
- function #x#set(core::int? #t10) → dynamic
- return #x = #t10;
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
core::print(#x#get(){() → core::int?});
#x#set(42){(core::int?) → dynamic};
core::print(#x#get(){() → core::int?});
lowered core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
- function #y#set(core::int? #t12) → dynamic
- return #y = #t12;
+ return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+ function #y#set(core::int? #t4) → dynamic
+ return #y = #t4;
core::print(#y#get(){() → core::int?});
#y#set(42){(core::int?) → dynamic};
core::print(#y#get(){() → core::int?});
@@ -76,9 +55,9 @@
static method testNonNullableInitializedNonFinalLocal() → void {
lowered core::int? #x;
function #x#get() → core::int
- return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
- function #x#set(core::int #t14) → dynamic
- return #x = #t14;
+ return let final core::int? #t5 = #x in #t5 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ function #x#set(core::int #t6) → dynamic
+ return #x = #t6;
core::print(#x#get(){() → core::int});
#x#set(42){(core::int) → dynamic};
core::print(#x#get(){() → core::int});
@@ -86,17 +65,17 @@
static method testNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
core::print(#x#get(){() → core::int?});
lowered final core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
core::print(#y#get(){() → core::int?});
}
static method testNonNullableInitializedFinalLocal() → void {
lowered final core::int? #x;
function #x#get() → core::int
- return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+ return let final core::int? #t11 = #x in #t11 == null ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11{core::int};
core::print(#x#get(){() → core::int});
}
@@ -109,4 +88,4 @@
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
-Extra constant evaluation: evaluated: 168, effectively constant: 7
+Extra constant evaluation: evaluated: 130, effectively constant: 7
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
index 26979f0..0e44ebb 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
@@ -14,61 +14,39 @@
self::testNonNullableInitializedFinalLocal();
}
static method testNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
- function #x#set(core::int? #t2) → dynamic
- return #x = #t2;
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ late core::int? x;
+ x = 42;
+ core::print(x{core::int});
}
static method testNonNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int>();
- function #x#get() → core::int
- return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
- function #x#set(core::int #t4) → dynamic
- return #x = #t4;
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ late core::int x;
+ x = 42;
+ core::print(x);
}
static method testNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
- function #x#set(core::int? #t6) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t6;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ late final core::int? x;
+ x = 42;
+ core::print(x{core::int});
}
static method testNonNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int>();
- function #x#get() → core::int
- return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
- function #x#set(core::int #t8) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t8;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ late final core::int x;
+ x = 42;
+ core::print(x);
}
static method testNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
- function #x#set(core::int? #t10) → dynamic
- return #x = #t10;
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
core::print(#x#get(){() → core::int?});
#x#set(42){(core::int?) → dynamic};
core::print(#x#get(){() → core::int?});
lowered core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
- function #y#set(core::int? #t12) → dynamic
- return #y = #t12;
+ return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+ function #y#set(core::int? #t4) → dynamic
+ return #y = #t4;
core::print(#y#get(){() → core::int?});
#y#set(42){(core::int?) → dynamic};
core::print(#y#get(){() → core::int?});
@@ -76,9 +54,9 @@
static method testNonNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int>();
function #x#get() → core::int
- return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
- function #x#set(core::int #t14) → dynamic
- return #x = #t14;
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ function #x#set(core::int #t6) → dynamic
+ return #x = #t6;
core::print(#x#get(){() → core::int});
#x#set(42){(core::int) → dynamic};
core::print(#x#get(){() → core::int});
@@ -86,16 +64,16 @@
static method testNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
core::print(#x#get(){() → core::int?});
lowered final core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
core::print(#y#get(){() → core::int?});
}
static method testNonNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int>();
function #x#get() → core::int
- return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+ return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
core::print(#x#get(){() → core::int});
}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
index 640d4d4..0d8bf0e 100644
--- a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
library /*isNonNullableByDefault*/;
import self as self;
+import "dart:_late_helper" as _la;
import "dart:core" as core;
import "dart:_internal" as _in;
@@ -14,61 +15,39 @@
self::testNonNullableInitializedFinalLocal();
}
static method testNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
- function #x#set(core::int? #t2) → dynamic
- return #x = #t2;
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::value} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNonNullableUninitializedNonFinalLocal() → void {
- lowered core::int? #x = _in::createSentinel<core::int>();
- function #x#get() → core::int
- return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
- function #x#set(core::int #t4) → dynamic
- return #x = #t4;
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::value} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int?>();
- function #x#get() → core::int?
- return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
- function #x#set(core::int? #t6) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t6;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int?) → dynamic};
- core::print(#x#get(){() → core::int?});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::finalLocalValue} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNonNullableUninitializedFinalLocal() → void {
- lowered final core::int? #x = _in::createSentinel<core::int>();
- function #x#get() → core::int
- return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
- function #x#set(core::int #t8) → dynamic
- if(_in::isSentinel(#x))
- return #x = #t8;
- else
- throw new _in::LateError::localAI("x");
- #x#set(42){(core::int) → dynamic};
- core::print(#x#get(){() → core::int});
+ final _la::_Cell x = new _la::_Cell::•();
+ x.{_la::_Cell::finalLocalValue} = 42;
+ core::print(x.{_la::_Cell::readLocal}<core::int>(){() → core::int});
}
static method testNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
- function #x#set(core::int? #t10) → dynamic
- return #x = #t10;
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
core::print(#x#get(){() → core::int?});
#x#set(42){(core::int?) → dynamic};
core::print(#x#get(){() → core::int?});
lowered core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
- function #y#set(core::int? #t12) → dynamic
- return #y = #t12;
+ return let final core::int? #t3 = #y in _in::isSentinel(#t3) ?{core::int?} #y = null : #t3{core::int?};
+ function #y#set(core::int? #t4) → dynamic
+ return #y = #t4;
core::print(#y#get(){() → core::int?});
#y#set(42){(core::int?) → dynamic};
core::print(#y#get(){() → core::int?});
@@ -76,9 +55,9 @@
static method testNonNullableInitializedNonFinalLocal() → void {
lowered core::int? #x = _in::createSentinel<core::int>();
function #x#get() → core::int
- return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
- function #x#set(core::int #t14) → dynamic
- return #x = #t14;
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ function #x#set(core::int #t6) → dynamic
+ return #x = #t6;
core::print(#x#get(){() → core::int});
#x#set(42){(core::int) → dynamic};
core::print(#x#get(){() → core::int});
@@ -86,17 +65,17 @@
static method testNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int?>();
function #x#get() → core::int?
- return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int?} let final core::int? #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t8 : throw new _in::LateError::localADI("x") : #t7;
core::print(#x#get(){() → core::int?});
lowered final core::int? #y = _in::createSentinel<core::int?>();
function #y#get() → core::int?
- return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ return let final core::int? #t9 = #y in _in::isSentinel(#t9) ?{core::int?} let final core::int? #t10 = null in _in::isSentinel(#y) ?{core::int?} #y = #t10 : throw new _in::LateError::localADI("y") : #t9;
core::print(#y#get(){() → core::int?});
}
static method testNonNullableInitializedFinalLocal() → void {
lowered final core::int? #x = _in::createSentinel<core::int>();
function #x#get() → core::int
- return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+ return let final core::int #t11 = #x in _in::isSentinel(#t11) ?{core::int} let final core::int #t12 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t12 : throw new _in::LateError::localADI("x") : #t11;
core::print(#x#get(){() → core::int});
}
@@ -109,4 +88,4 @@
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
-Extra constant evaluation: evaluated: 172, effectively constant: 7
+Extra constant evaluation: evaluated: 132, effectively constant: 7
diff --git a/pkg/status_file/lib/expectation.dart b/pkg/status_file/lib/expectation.dart
index 6e94845..93979fb 100644
--- a/pkg/status_file/lib/expectation.dart
+++ b/pkg/status_file/lib/expectation.dart
@@ -91,6 +91,11 @@
static final Expectation nonUtf8Error =
new Expectation._('NonUtf8Output', group: fail);
+ /// The stdout or stderr produced by the test was too long and had to be
+ /// truncated by the test runner.
+ static final Expectation truncatedOutput =
+ new Expectation._('TruncatedOutput', group: fail);
+
/// The VM exited with the special exit code 252.
static final Expectation dartkCrash =
new Expectation._('DartkCrash', group: crash);
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 09134bb..5d8e490 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -53,6 +53,7 @@
if (hasTimedOut) return Expectation.timeout;
if (_didFail(testCase)) return Expectation.fail;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
return Expectation.pass;
}
@@ -64,6 +65,7 @@
if (hasTimedOut) return Expectation.timeout;
if (_didFail(testCase)) return Expectation.fail;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
return Expectation.pass;
}
@@ -117,6 +119,9 @@
bool get hasNonUtf8 => exitCode == nonUtfFakeExitCode;
+ /// Whether the command's output was too long and was truncated.
+ bool get truncatedOutput => exitCode == truncatedFakeExitCode;
+
/// Called when producing output for a test failure to describe this output.
void describe(TestCase testCase, Progress progress, OutputWriter output) {
output.subsection("exit code");
@@ -335,6 +340,7 @@
}
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// Multitests are handled specially.
if (testCase.hasRuntimeError) {
@@ -354,6 +360,7 @@
}
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
return _outcome;
}
@@ -622,6 +629,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
List<StaticError> errors;
try {
@@ -683,6 +691,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
List<StaticError> errors;
try {
@@ -791,6 +800,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (exitCode != 0) return Expectation.fail;
for (var line in decodeUtf8(stdout).split('\n')) {
@@ -807,6 +817,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (exitCode != 0) return Expectation.fail;
for (var line in decodeUtf8(stdout).split('\n')) {
@@ -836,6 +847,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (testCase.hasCompileError) {
if (testCase.hasSyntaxError) {
@@ -861,6 +873,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (hasSyntaxError) return Expectation.syntaxError;
if (exitCode != 0) return Expectation.syntaxError;
return Expectation.pass;
@@ -884,6 +897,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// Multitests are handled specially.
if (testCase.hasCompileError) {
@@ -924,6 +938,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// The actual outcome depends on the exitCode.
if (exitCode == _compileErrorExitCode) return Expectation.compileTimeError;
@@ -986,6 +1001,7 @@
: Expectation.timeout;
}
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// Handle dart2js specific crash detection
if (exitCode == _crashExitCode ||
@@ -1010,6 +1026,7 @@
: Expectation.timeout;
}
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// Handle dart2js specific crash detection
if (exitCode == _crashExitCode ||
@@ -1112,6 +1129,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// If it's a static error test, validate the exact errors.
if (testCase.testFile.isStaticErrorTest) {
@@ -1134,6 +1152,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// If it's a static error test, validate the exact errors.
if (testCase.testFile.isStaticErrorTest) {
@@ -1185,6 +1204,7 @@
if (hasCrashed) return Expectation.dartkCrash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// If the frontend had an uncaught exception, then we'll consider this a
// crash.
@@ -1227,6 +1247,7 @@
if (hasCrashed) return Expectation.dartkCrash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
// If the frontend had an uncaught exception, then we'll consider this a
// crash.
@@ -1267,6 +1288,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (testCase.hasRuntimeError) {
if (exitCode != 0) return Expectation.pass;
@@ -1284,6 +1306,7 @@
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
if (exitCode != 0) return Expectation.runtimeError;
var output = decodeUtf8(stdout);
@@ -1435,7 +1458,11 @@
void describe(TestCase testCase, Progress progress, OutputWriter output) {
// Handle static error test output specially. We don't want to show the raw
// stdout if we can give the user the parsed expectations instead.
- if (testCase.testFile.isStaticErrorTest && !hasCrashed && !hasTimedOut) {
+ if (testCase.testFile.isStaticErrorTest &&
+ !hasCrashed &&
+ !hasTimedOut &&
+ !hasNonUtf8 &&
+ !truncatedOutput) {
try {
_validateExpectedErrors(testCase, output);
} catch (_) {
@@ -1444,19 +1471,21 @@
super.describe(testCase, progress, output);
return;
}
- }
- // Don't show the "raw" output unless something strange happened or the
- // user explicitly requests all the output.
- if (hasTimedOut ||
- hasCrashed ||
- !testCase.testFile.isStaticErrorTest ||
- progress == Progress.verbose) {
+ // Always show the raw output when specifically requested.
+ if (progress == Progress.verbose) {
+ super.describe(testCase, progress, output);
+ }
+ } else {
+ // Something strange happened, so show the raw output.
super.describe(testCase, progress, output);
}
}
Expectation result(TestCase testCase) {
+ if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
+
// If it's a static error test, validate the exact errors.
if (testCase.testFile.isStaticErrorTest) {
return _validateExpectedErrors(testCase);
@@ -1466,6 +1495,9 @@
}
Expectation realResult(TestCase testCase) {
+ if (hasNonUtf8) return Expectation.nonUtf8Error;
+ if (truncatedOutput) return Expectation.truncatedOutput;
+
// If it's a static error test, validate the exact errors.
if (testCase.testFile.isStaticErrorTest) {
return _validateExpectedErrors(testCase);
diff --git a/pkg/test_runner/lib/src/output_log.dart b/pkg/test_runner/lib/src/output_log.dart
index 35b5b258..fa8caae 100644
--- a/pkg/test_runner/lib/src/output_log.dart
+++ b/pkg/test_runner/lib/src/output_log.dart
@@ -6,85 +6,61 @@
import 'dart:convert';
import 'dart:io';
-/// An OutputLog records the output from a test, but truncates it if
-/// it is longer than [_maxHead] characters, and just keeps the head and
-/// the last [_tailLength] characters of the output.
-class OutputLog implements StreamConsumer<List<int>> {
- static const _maxHead = 500 * 1024;
- static const _tailLength = 10 * 1024;
+const _nonUtf8Error = '[test.dart: This test output contains non-UTF8 data]';
+const _truncatedError =
+ '[test.dart: This test output was too long and was truncated here.';
- List<int> _head = [];
- List<int> _tail;
- List<int> complete;
- bool _dataDropped = false;
+/// Records the output from a test.
+class OutputLog implements StreamConsumer<List<int>> {
+ // TODO(45618): Reduce this if language_2/unsorted/disassemble_test is fixed
+ // to produce less output and any other large-output tests are fixed.
+ static const _maxLength = 10 * 1024 * 1024;
+
+ final List<int> _data = [];
StreamSubscription _subscription;
- bool _hasNonUtf8 = false;
- bool get hasNonUtf8 => _hasNonUtf8;
+ bool get hasNonUtf8 => _hasNonUtf8 ??= _checkUtf8();
+ bool _hasNonUtf8;
+
+ bool get wasTruncated => _wasTruncated;
+ bool _wasTruncated = false;
+
+ List<int> get bytes => _data;
void add(List<int> data) {
- if (complete != null) {
- throw StateError("Cannot add to OutputLog after calling toList");
+ if (_hasNonUtf8 != null) {
+ throw StateError("Cannot add to OutputLog after accessing bytes.");
}
- if (_tail == null) {
- _head.addAll(data);
- if (_head.length > _maxHead) {
- _tail = _head.sublist(_maxHead);
- _head.length = _maxHead;
- }
+
+ // Discard additional output after we've reached the limit.
+ if (_wasTruncated) return;
+
+ if (_data.length + data.length > _maxLength) {
+ _data.addAll(data.take(_maxLength - _data.length));
+ _data.addAll(utf8.encode(_truncatedError));
+ _wasTruncated = true;
} else {
- _tail.addAll(data);
- }
- if (_tail != null && _tail.length > 2 * _tailLength) {
- _tail = _truncatedTail();
- _dataDropped = true;
+ _data.addAll(data);
}
}
- List<int> _truncatedTail() => _tail.length > _tailLength
- ? _tail.sublist(_tail.length - _tailLength)
- : _tail;
+ void clear() {
+ _data.clear();
+ }
- void _checkUtf8(List<int> data) {
+ bool _checkUtf8() {
try {
- utf8.decode(data, allowMalformed: false);
+ utf8.decode(_data, allowMalformed: false);
+ return false;
} on FormatException {
- _hasNonUtf8 = true;
- var malformed = utf8.decode(data, allowMalformed: true);
- data
- ..clear()
- ..addAll(utf8.encode(malformed))
- ..addAll("""
-*****************************************************************************
-test.dart: The output of this test contained non-UTF8 formatted data.
-*****************************************************************************
-"""
- .codeUnits);
+ var malformed = utf8.decode(_data, allowMalformed: true);
+ _data.clear();
+ _data.addAll(utf8.encode(malformed));
+ _data.addAll(utf8.encode(_nonUtf8Error));
+ return true;
}
}
- List<int> toList() {
- if (complete == null) {
- complete = _head;
- if (_dataDropped) {
- complete.addAll("""
-*****************************************************************************
-test.dart: Data was removed due to excessive length. If you need the limit to
-be increased, please contact dart-engprod or file an issue.
-*****************************************************************************
-"""
- .codeUnits);
- complete.addAll(_truncatedTail());
- } else if (_tail != null) {
- complete.addAll(_tail);
- }
- _head = null;
- _tail = null;
- _checkUtf8(complete);
- }
- return complete;
- }
-
@override
Future addStream(Stream<List<int>> stream) {
_subscription = stream.listen(add);
@@ -92,14 +68,9 @@
}
@override
- Future close() {
- toList();
- return _subscription?.cancel();
- }
+ Future close() => _subscription?.cancel();
- Future cancel() {
- return _subscription?.cancel();
- }
+ Future cancel() => _subscription?.cancel();
}
/// An [OutputLog] that tees the output to a file as well.
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index 7b29ea8..ff3e1f1 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -1082,11 +1082,19 @@
if (outcome == "CRASH") exitCode = unhandledCompilerExceptionExitCode;
if (outcome == "PARSE_FAIL") exitCode = parseFailExitCode;
if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
+
+ // Fail if the output was too long or incorrectly formatted.
+ if (_testStdout.hasNonUtf8 || _testStderr.hasNonUtf8) {
+ exitCode = nonUtfFakeExitCode;
+ } else if (_testStdout.wasTruncated || _testStderr.wasTruncated) {
+ exitCode = truncatedFakeExitCode;
+ }
+
var output = _command.createOutput(
exitCode,
outcome == "TIMEOUT",
- _testStdout.toList(),
- _testStderr.toList(),
+ _testStdout.bytes,
+ _testStderr.bytes,
DateTime.now().difference(_startTime),
false);
assert(_completer != null);
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 159b636..9316d76 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -20,7 +20,8 @@
const _slowTimeoutMultiplier = 4;
const _extraSlowTimeoutMultiplier = 8;
-const nonUtfFakeExitCode = 0xFFFD;
+const nonUtfFakeExitCode = 0xfffd;
+const truncatedFakeExitCode = 0xfffc;
/// Some IO tests use these variables and get confused if the host environment
/// variables are inherited so they are excluded.
@@ -220,25 +221,24 @@
/// are no pointers to it, so it should be available to be garbage collected as
/// soon as it is done.
class RunningProcess {
- ProcessCommand command;
- int timeout;
+ final ProcessCommand command;
+ final int timeout;
bool timedOut = false;
DateTime startTime;
int pid;
- OutputLog stdout;
- OutputLog stderr = OutputLog();
- List<String> diagnostics = <String>[];
+ final OutputLog _stdout;
+ final OutputLog _stderr = OutputLog();
+ final List<String> diagnostics = [];
bool compilationSkipped = false;
Completer<CommandOutput> completer;
- TestConfiguration configuration;
+ final TestConfiguration configuration;
RunningProcess(this.command, this.timeout,
- {this.configuration, io.File outputFile}) {
- stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
- }
+ {this.configuration, io.File outputFile})
+ : _stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
Future<CommandOutput> run() {
- completer = Completer<CommandOutput>();
+ completer = Completer();
startTime = DateTime.now();
_runCommand();
return completer.future;
@@ -255,8 +255,8 @@
environment: processEnvironment,
workingDirectory: command.workingDirectory);
processFuture.then<dynamic>((io.Process process) {
- var stdoutFuture = process.stdout.pipe(stdout);
- var stderrFuture = process.stderr.pipe(stderr);
+ var stdoutFuture = process.stdout.pipe(_stdout);
+ var stderrFuture = process.stderr.pipe(_stderr);
pid = process.pid;
// Close stdin so that tests that try to block on input will fail.
@@ -329,15 +329,15 @@
onTimeout: () async {
DebugLogger.warning(
"$maxStdioDelayPassedMessage (command: $command)");
- await stdout.cancel();
- await stderr.cancel();
+ await _stdout.cancel();
+ await _stderr.cancel();
return null;
}).then((_) {
- if (stdout is FileOutputLog) {
+ if (_stdout is FileOutputLog) {
// Prevent logging data that has already been written to a file
- // and is unlikely too add value in the logs because the command
+ // and is unlikely to add value in the logs because the command
// succeeded.
- stdout.complete = <int>[];
+ _stdout.clear();
}
_commandComplete(exitCode);
});
@@ -359,15 +359,16 @@
}
CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) {
- var stdoutData = stdout.toList();
- var stderrData = stderr.toList();
- if (stdout.hasNonUtf8 || stderr.hasNonUtf8) {
- // If the output contained non-utf8 formatted data, then make the exit
- // code non-zero if it isn't already.
- if (exitCode == 0) {
- exitCode = nonUtfFakeExitCode;
- }
+ var stdoutData = _stdout.bytes;
+ var stderrData = _stderr.bytes;
+
+ // Fail if the output was too long or incorrectly formatted.
+ if (_stdout.hasNonUtf8 || _stderr.hasNonUtf8) {
+ exitCode = nonUtfFakeExitCode;
+ } else if (_stdout.wasTruncated || _stderr.wasTruncated) {
+ exitCode = truncatedFakeExitCode;
}
+
var commandOutput = command.createOutput(
exitCode,
timedOut,
diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart
index 389350a..8ea87ad 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory/lib/src/elements/instance_ref.dart
@@ -162,6 +162,7 @@
]
];
case M.InstanceKind.plainInstance:
+ case M.InstanceKind.receivePort:
return [
new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
..classes = ['emphasize']
diff --git a/runtime/observatory/tests/service/developer_server_control_test.dart b/runtime/observatory/tests/service/developer_server_control_test.dart
index f599dc3..18498f2 100644
--- a/runtime/observatory/tests/service/developer_server_control_test.dart
+++ b/runtime/observatory/tests/service/developer_server_control_test.dart
@@ -11,6 +11,7 @@
int? majorVersion;
int? minorVersion;
Uri? serverUri;
+Uri? wsServerUri;
Future<Null> testeeBefore() async {
print('testee before');
@@ -20,8 +21,8 @@
ServiceProtocolInfo info = await Service.getInfo();
majorVersion = info.majorVersion;
minorVersion = info.minorVersion;
- serverUri = info.serverUri;
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
{
// Now, start the web server and store the URI which is expected to be
// non NULL in the top level variable.
@@ -30,7 +31,11 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNotNull(info.serverUri);
+ Expect.isNotNull(info.serverWebSocketUri);
serverUri = info.serverUri;
+ wsServerUri = info.serverWebSocketUri;
+ Expect.equals(wsServerUri!.scheme, 'ws');
+ Expect.isTrue(wsServerUri!.path.endsWith('ws'));
}
{
// Now try starting the web server again, this should just return the
@@ -39,6 +44,7 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.equals(info.serverUri, serverUri);
+ Expect.equals(info.serverWebSocketUri, wsServerUri);
}
{
// Try turning off the web server, this should turn off the server and
@@ -47,6 +53,7 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
}
{
// Try turning off the web server again, this should be a nop
@@ -55,16 +62,17 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
}
{
// Start the web server again for the test below.
ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
majorVersion = info.majorVersion;
minorVersion = info.minorVersion;
- serverUri = info.serverUri;
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
- Expect.equals(info.serverUri, serverUri);
+ Expect.isNotNull(info.serverUri);
+ Expect.isNotNull(info.serverWebSocketUri);
}
}
diff --git a/runtime/observatory_2/lib/src/elements/instance_ref.dart b/runtime/observatory_2/lib/src/elements/instance_ref.dart
index 1895783..f1b37ea 100644
--- a/runtime/observatory_2/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory_2/lib/src/elements/instance_ref.dart
@@ -264,6 +264,7 @@
return members;
}
case M.InstanceKind.plainInstance:
+ case M.InstanceKind.receivePort:
return _loadedInstance.fields
.map<Element>((f) => new DivElement()
..children = <Element>[
diff --git a/runtime/observatory_2/tests/service_2/developer_server_control_test.dart b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
index 62889e4..c4a81392 100644
--- a/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
+++ b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
@@ -11,6 +11,7 @@
int majorVersion;
int minorVersion;
Uri serverUri;
+Uri wsServerUri;
Future<Null> testeeBefore() async {
print('testee before');
@@ -20,8 +21,8 @@
ServiceProtocolInfo info = await Service.getInfo();
majorVersion = info.majorVersion;
minorVersion = info.minorVersion;
- serverUri = info.serverUri;
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
{
// Now, start the web server and store the URI which is expected to be
// non NULL in the top level variable.
@@ -31,6 +32,9 @@
Expect.equals(info.minorVersion, minorVersion);
Expect.isNotNull(info.serverUri);
serverUri = info.serverUri;
+ wsServerUri = info.serverWebSocketUri;
+ Expect.equals(wsServerUri.scheme, 'ws');
+ Expect.isTrue(wsServerUri.path.endsWith('ws'));
}
{
// Now try starting the web server again, this should just return the
@@ -39,6 +43,7 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.equals(info.serverUri, serverUri);
+ Expect.equals(info.serverWebSocketUri, wsServerUri);
}
{
// Try turning off the web server, this should turn off the server and
@@ -47,6 +52,7 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
}
{
// Try turning off the web server again, this should be a nop
@@ -55,16 +61,17 @@
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
Expect.isNull(info.serverUri);
+ Expect.isNull(info.serverWebSocketUri);
}
{
// Start the web server again for the test below.
ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
majorVersion = info.majorVersion;
minorVersion = info.minorVersion;
- serverUri = info.serverUri;
Expect.equals(info.majorVersion, majorVersion);
Expect.equals(info.minorVersion, minorVersion);
- Expect.equals(info.serverUri, serverUri);
+ Expect.isNotNull(info.serverUri);
+ Expect.isNotNull(info.serverWebSocketUri);
}
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index d4bfbe0..436bad9 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -377,10 +377,12 @@
[ $builder_tag == crossword || $builder_tag == crossword_ast ]
dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
+dart/gen_snapshot_include_resolved_urls_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot.
dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
dart/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
dart/split_aot_kernel_generation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
dart_2/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
+dart_2/gen_snapshot_include_resolved_urls_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot.
dart_2/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
dart_2/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
dart_2/split_aot_kernel_generation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index e779915..537bfe0 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2415,6 +2415,15 @@
objects_.Add(weak);
}
+ void RetraceEphemerons(Serializer* s) {
+ for (intptr_t i = 0; i < objects_.length(); i++) {
+ WeakSerializationReferencePtr weak = objects_[i];
+ if (!s->HasRef(weak->untag()->target())) {
+ s->Push(weak->untag()->replacement());
+ }
+ }
+ }
+
intptr_t FinalizeWeak(Serializer* s) { return objects_.length(); }
void WriteAlloc(Serializer* s) {
@@ -5029,7 +5038,15 @@
void Trace(Serializer* s, ObjectPtr object) {
WeakPropertyPtr property = WeakProperty::RawCast(object);
objects_.Add(property);
- PushFromTo(property);
+ }
+
+ void RetraceEphemerons(Serializer* s) {
+ for (intptr_t i = 0; i < objects_.length(); i++) {
+ WeakPropertyPtr property = objects_[i];
+ if (s->HasRef(property->untag()->key())) {
+ s->Push(property->untag()->value());
+ }
+ }
}
void WriteAlloc(Serializer* s) {
@@ -5047,7 +5064,14 @@
for (intptr_t i = 0; i < count; i++) {
WeakPropertyPtr property = objects_[i];
AutoTraceObject(property);
- WriteFromTo(property);
+ if (s->HasRef(property->untag()->key())) {
+ s->WriteOffsetRef(property->untag()->key(), WeakProperty::key_offset());
+ s->WriteOffsetRef(property->untag()->value(),
+ WeakProperty::value_offset());
+ } else {
+ s->WriteOffsetRef(Object::null(), WeakProperty::key_offset());
+ s->WriteOffsetRef(Object::null(), WeakProperty::value_offset());
+ }
}
}
@@ -6759,7 +6783,24 @@
roots->PushRoots(this);
while (stack_.length() > 0) {
- Trace(stack_.RemoveLast());
+ // Strong references.
+ while (stack_.length() > 0) {
+ Trace(stack_.RemoveLast());
+ }
+
+ // Ephemeron references.
+#if defined(DART_PRECOMPILER)
+ if (auto const cluster =
+ reinterpret_cast<WeakSerializationReferenceSerializationCluster*>(
+ clusters_by_cid_[kWeakSerializationReferenceCid])) {
+ cluster->RetraceEphemerons(this);
+ }
+#endif
+ if (auto const cluster =
+ reinterpret_cast<WeakPropertySerializationCluster*>(
+ clusters_by_cid_[kWeakPropertyCid])) {
+ cluster->RetraceEphemerons(this);
+ }
}
GrowableArray<SerializationCluster*> canonical_clusters;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 9b15447..5b0fc05 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -6092,6 +6092,20 @@
return this;
}
+Representation LoadIndexedInstr::RepresentationOfArrayElement(
+ intptr_t array_cid) {
+ switch (array_cid) {
+ case kImmutableArrayCid:
+ case kTypeArgumentsCid:
+ return kTagged;
+ case kExternalOneByteStringCid:
+ case kExternalTwoByteStringCid:
+ return kUnboxedIntPtr;
+ default:
+ return StoreIndexedInstr::RepresentationOfArrayElement(array_cid);
+ }
+}
+
StoreIndexedInstr::StoreIndexedInstr(Value* array,
Value* index,
Value* value,
@@ -6133,6 +6147,64 @@
return this;
}
+Representation StoreIndexedInstr::RepresentationOfArrayElement(
+ intptr_t array_cid) {
+ switch (array_cid) {
+ case kArrayCid:
+ return kTagged;
+ case kOneByteStringCid:
+ case kTwoByteStringCid:
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ return kUnboxedIntPtr;
+ case kTypedDataInt32ArrayCid:
+ return kUnboxedInt32;
+ case kTypedDataUint32ArrayCid:
+ return kUnboxedUint32;
+ case kTypedDataInt64ArrayCid:
+ case kTypedDataUint64ArrayCid:
+ return kUnboxedInt64;
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid:
+ return kUnboxedDouble;
+ case kTypedDataInt32x4ArrayCid:
+ return kUnboxedInt32x4;
+ case kTypedDataFloat32x4ArrayCid:
+ return kUnboxedFloat32x4;
+ case kTypedDataFloat64x2ArrayCid:
+ return kUnboxedFloat64x2;
+ default:
+ UNREACHABLE();
+ return kTagged;
+ }
+}
+
+Representation StoreIndexedInstr::RequiredInputRepresentation(
+ intptr_t idx) const {
+ // Array can be a Dart object or a pointer to external data.
+ if (idx == 0) return kNoRepresentation; // Flexible input representation.
+ if (idx == 1) {
+ if (index_unboxed_) {
+#if defined(TARGET_ARCH_X64)
+ return kUnboxedInt64;
+#else
+ // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32 on 32-bit
+ // architectures.
+ return kNoRepresentation; // Index can be any unboxed representation.
+#endif
+ } else {
+ return kTagged; // Index is a smi.
+ }
+ }
+ ASSERT(idx == 2);
+ return RepresentationOfArrayElement(class_id());
+}
+
bool Utf8ScanInstr::IsScanFlagsUnboxed() const {
return FlowGraphCompiler::IsUnboxedField(scan_flags_field_.field());
}
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index fc05085..b4d5f3a 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5661,7 +5661,13 @@
return GetDeoptId() != DeoptId::kNone;
}
- virtual Representation representation() const;
+ // Representation of LoadIndexed from arrays with given cid.
+ static Representation RepresentationOfArrayElement(intptr_t array_cid);
+
+ Representation representation() const {
+ return RepresentationOfArrayElement(class_id());
+ }
+
virtual void InferRange(RangeAnalysis* analysis, Range* range);
virtual bool HasUnknownSideEffects() const { return false; }
@@ -5957,6 +5963,9 @@
virtual bool ComputeCanDeoptimize() const { return false; }
+ // Representation of value passed to StoreIndexed for arrays with given cid.
+ static Representation RepresentationOfArrayElement(intptr_t array_cid);
+
virtual Representation RequiredInputRepresentation(intptr_t idx) const;
bool IsExternal() const {
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index c8b681f..93540db 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1753,46 +1753,6 @@
__ StoreToOffset(value, obj, instr->offset_from_tagged());
}
-Representation LoadIndexedInstr::representation() const {
- switch (class_id_) {
- case kArrayCid:
- case kImmutableArrayCid:
- case kTypeArgumentsCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNREACHABLE();
- return kTagged;
- }
-}
-
static bool CanBeImmediateIndex(Value* value,
intptr_t cid,
bool is_external,
@@ -2061,54 +2021,6 @@
}
}
-Representation StoreIndexedInstr::RequiredInputRepresentation(
- intptr_t idx) const {
- // Array can be a Dart object or a pointer to external data.
- if (idx == 0) return kNoRepresentation; // Flexible input representation.
- if (idx == 1) {
- if (index_unboxed_) {
- // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32.
- return kNoRepresentation;
- } else {
- return kTagged; // Index is a smi.
- }
- }
- ASSERT(idx == 2);
- switch (class_id_) {
- case kArrayCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNREACHABLE();
- return kTagged;
- }
-}
-
LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const bool directly_addressable =
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 3bab356..a0ee87a 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1660,46 +1660,6 @@
__ StoreToOffset(value, obj, instr->offset_from_tagged());
}
-Representation LoadIndexedInstr::representation() const {
- switch (class_id_) {
- case kArrayCid:
- case kImmutableArrayCid:
- case kTypeArgumentsCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNIMPLEMENTED();
- return kTagged;
- }
-}
-
static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) {
ConstantInstr* constant = value->definition()->AsConstant();
if ((constant == NULL) || !constant->value().IsSmi()) {
@@ -1891,53 +1851,6 @@
__ SmiTag(result);
}
-Representation StoreIndexedInstr::RequiredInputRepresentation(
- intptr_t idx) const {
- // Array can be a Dart object or a pointer to external data.
- if (idx == 0) return kNoRepresentation; // Flexible input representation.
- if (idx == 1) {
- if (index_unboxed_) {
- return kNoRepresentation; // Index can be any unboxed representation.
- } else {
- return kTagged; // Index is a smi.
- }
- }
- ASSERT(idx == 2);
- switch (class_id_) {
- case kArrayCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNREACHABLE();
- return kTagged;
- }
-}
-
LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 8c6fe6d..a308aaa 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1433,46 +1433,6 @@
__ movl(compiler::Address(obj, instr->offset_from_tagged()), value);
}
-Representation LoadIndexedInstr::representation() const {
- switch (class_id_) {
- case kArrayCid:
- case kImmutableArrayCid:
- case kTypeArgumentsCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNIMPLEMENTED();
- return kTagged;
- }
-}
-
LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -1627,54 +1587,6 @@
}
}
-Representation StoreIndexedInstr::RequiredInputRepresentation(
- intptr_t idx) const {
- // Array can be a Dart object or a pointer to external data.
- if (idx == 0) return kNoRepresentation; // Flexible input representation.
- if (idx == 1) {
- if (index_unboxed_) {
- // TODO(dartbug.com/39432): kUnboxedInt32 || kUnboxedUint32.
- return kNoRepresentation;
- } else {
- return kTagged; // Index is a smi.
- }
- }
- ASSERT(idx == 2);
- switch (class_id_) {
- case kArrayCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNIMPLEMENTED();
- return kTagged;
- }
-}
-
LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index da435ce3..9eaa60c 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1683,46 +1683,6 @@
const Register result_;
};
-Representation LoadIndexedInstr::representation() const {
- switch (class_id_) {
- case kArrayCid:
- case kImmutableArrayCid:
- case kTypeArgumentsCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNIMPLEMENTED();
- return kTagged;
- }
-}
-
LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -1933,52 +1893,6 @@
}
}
-Representation StoreIndexedInstr::RequiredInputRepresentation(
- intptr_t idx) const {
- if (idx == 0) return kNoRepresentation;
- if (idx == 1) {
- if (index_unboxed_) {
- return kUnboxedInt64;
- } else {
- return kTagged; // Index is a smi.
- }
- }
- ASSERT(idx == 2);
- switch (class_id_) {
- case kArrayCid:
- return kTagged;
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kTypedDataInt8ArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kTypedDataUint16ArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return kUnboxedIntPtr;
- case kTypedDataInt32ArrayCid:
- return kUnboxedInt32;
- case kTypedDataUint32ArrayCid:
- return kUnboxedUint32;
- case kTypedDataInt64ArrayCid:
- case kTypedDataUint64ArrayCid:
- return kUnboxedInt64;
- case kTypedDataFloat32ArrayCid:
- case kTypedDataFloat64ArrayCid:
- return kUnboxedDouble;
- case kTypedDataFloat32x4ArrayCid:
- return kUnboxedFloat32x4;
- case kTypedDataInt32x4ArrayCid:
- return kUnboxedInt32x4;
- case kTypedDataFloat64x2ArrayCid:
- return kUnboxedFloat64x2;
- default:
- UNIMPLEMENTED();
- return kTagged;
- }
-}
-
LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 3;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 012a80e..ed3fba1 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1302,8 +1302,6 @@
compiler::ffi::RecognizedMethodAlignment(kind);
const classid_t typed_data_cid =
compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
- const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
- zone_, ffi_type_arg_cid);
ASSERT(function.NumParameters() == 2);
LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
@@ -1324,59 +1322,45 @@
body += LoadIndexed(typed_data_cid, /*index_scale=*/1,
/*index_unboxed=*/true, alignment);
if (kind == MethodRecognizer::kFfiLoadFloat ||
- kind == MethodRecognizer::kFfiLoadFloatUnaligned ||
- kind == MethodRecognizer::kFfiLoadDouble ||
- kind == MethodRecognizer::kFfiLoadDoubleUnaligned) {
- if (kind == MethodRecognizer::kFfiLoadFloat ||
- kind == MethodRecognizer::kFfiLoadFloatUnaligned) {
- body += FloatToDouble();
- }
- body += Box(kUnboxedDouble);
- } else if (kind == MethodRecognizer::kFfiLoadInt8 ||
- kind == MethodRecognizer::kFfiLoadInt16 ||
- kind == MethodRecognizer::kFfiLoadUint8 ||
- kind == MethodRecognizer::kFfiLoadUint16) {
- // LoadIndexed instruction with 8-bit and 16-bit elements
- // results in value with kUnboxedIntPtr representation
- // (see LoadIndexedInstr::representation).
- // Avoid any unnecessary (and potentially deoptimizing) int
- // conversions by using the correct representation at the first place.
- body += Box(kUnboxedIntPtr);
- } else {
- body += Box(native_rep.AsRepresentationOverApprox(zone_));
- if (kind == MethodRecognizer::kFfiLoadPointer) {
- const auto class_table = thread_->isolate_group()->class_table();
- ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
- const auto& pointer_class =
- Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
+ kind == MethodRecognizer::kFfiLoadFloatUnaligned) {
+ body += FloatToDouble();
+ }
+ // Avoid any unnecessary (and potentially deoptimizing) int
+ // conversions by using the representation returned from LoadIndexed.
+ body +=
+ Box(LoadIndexedInstr::RepresentationOfArrayElement(typed_data_cid));
+ if (kind == MethodRecognizer::kFfiLoadPointer) {
+ const auto class_table = thread_->isolate_group()->class_table();
+ ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
+ const auto& pointer_class =
+ Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
- // We find the reified type to use for the pointer allocation.
- //
- // Call sites to this recognized method are guaranteed to pass a
- // Pointer<Pointer<X>> as RawParameterVariable(0). This function
- // will return a Pointer<X> object - for which we inspect the
- // reified type on the argument.
- //
- // The following is safe to do, as (1) we are guaranteed to have a
- // Pointer<Pointer<X>> as argument, and (2) the bound on the pointer
- // type parameter guarantees X is an interface type.
- ASSERT(function.NumTypeParameters() == 1);
- LocalVariable* address = MakeTemporary();
- body += LoadLocal(parsed_function_->RawParameterVariable(0));
- body += LoadNativeField(
- Slot::GetTypeArgumentsSlotFor(thread_, pointer_class));
- body += LoadNativeField(Slot::GetTypeArgumentsIndexSlot(
- thread_, Pointer::kNativeTypeArgPos));
- body += LoadNativeField(Slot::Type_arguments());
- body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
- LocalVariable* pointer = MakeTemporary();
- body += LoadLocal(pointer);
- body += LoadLocal(address);
- body += UnboxTruncate(kUnboxedFfiIntPtr);
- body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
- body += StoreUntagged(compiler::target::Pointer::data_field_offset());
- body += DropTempsPreserveTop(1); // Drop [address] keep [pointer].
- }
+ // We find the reified type to use for the pointer allocation.
+ //
+ // Call sites to this recognized method are guaranteed to pass a
+ // Pointer<Pointer<X>> as RawParameterVariable(0). This function
+ // will return a Pointer<X> object - for which we inspect the
+ // reified type on the argument.
+ //
+ // The following is safe to do, as (1) we are guaranteed to have a
+ // Pointer<Pointer<X>> as argument, and (2) the bound on the pointer
+ // type parameter guarantees X is an interface type.
+ ASSERT(function.NumTypeParameters() == 1);
+ LocalVariable* address = MakeTemporary();
+ body += LoadLocal(parsed_function_->RawParameterVariable(0));
+ body += LoadNativeField(
+ Slot::GetTypeArgumentsSlotFor(thread_, pointer_class));
+ body += LoadNativeField(Slot::GetTypeArgumentsIndexSlot(
+ thread_, Pointer::kNativeTypeArgPos));
+ body += LoadNativeField(Slot::Type_arguments());
+ body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
+ LocalVariable* pointer = MakeTemporary();
+ body += LoadLocal(pointer);
+ body += LoadLocal(address);
+ body += UnboxTruncate(kUnboxedFfiIntPtr);
+ body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
+ body += StoreUntagged(compiler::target::Pointer::data_field_offset());
+ body += DropTempsPreserveTop(1); // Drop [address] keep [pointer].
}
body += DropTempsPreserveTop(1); // Drop [arg_offset].
} break;
@@ -1400,8 +1384,6 @@
compiler::ffi::RecognizedMethodAlignment(kind);
const classid_t typed_data_cid =
compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
- const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
- zone_, ffi_type_arg_cid);
LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
LocalVariable* arg_offset = parsed_function_->RawParameterVariable(1);
@@ -1463,27 +1445,15 @@
// This can only be Pointer, so it is always safe to LoadUntagged.
body += LoadUntagged(compiler::target::Pointer::data_field_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
- } else if (kind == MethodRecognizer::kFfiStoreFloat ||
- kind == MethodRecognizer::kFfiStoreFloatUnaligned ||
- kind == MethodRecognizer::kFfiStoreDouble ||
- kind == MethodRecognizer::kFfiStoreDoubleUnaligned) {
- body += UnboxTruncate(kUnboxedDouble);
+ } else {
+ // Avoid any unnecessary (and potentially deoptimizing) int
+ // conversions by using the representation consumed by StoreIndexed.
+ body += UnboxTruncate(
+ StoreIndexedInstr::RepresentationOfArrayElement(typed_data_cid));
if (kind == MethodRecognizer::kFfiStoreFloat ||
kind == MethodRecognizer::kFfiStoreFloatUnaligned) {
body += DoubleToFloat();
}
- } else if (kind == MethodRecognizer::kFfiStoreInt8 ||
- kind == MethodRecognizer::kFfiStoreInt16 ||
- kind == MethodRecognizer::kFfiStoreUint8 ||
- kind == MethodRecognizer::kFfiStoreUint16) {
- // StoreIndexed instruction with 8-bit and 16-bit elements
- // takes value with kUnboxedIntPtr representation
- // (see StoreIndexedInstr::RequiredInputRepresentation).
- // Avoid any unnecessary (and potentially deoptimizing) int
- // conversions by using the correct representation at the first place.
- body += UnboxTruncate(kUnboxedIntPtr);
- } else {
- body += UnboxTruncate(native_rep.AsRepresentationOverApprox(zone_));
}
body += StoreIndexedTypedData(typed_data_cid, /*index_scale=*/1,
/*index_unboxed=*/true, alignment);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 4c5578f..8e91315 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -41,6 +41,7 @@
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/profiler_service.h"
+#include "vm/raw_object_fields.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/service_event.h"
@@ -2127,6 +2128,7 @@
ObjectGraph graph(thread);
Array& path = Array::Handle(Array::New(limit * 2));
intptr_t length = graph.InboundReferences(target, path);
+ OffsetsTable offsets_table(thread->zone());
JSONObject jsobj(js);
jsobj.AddProperty("type", "InboundReferences");
{
@@ -2147,17 +2149,35 @@
intptr_t element_index =
slot_offset.Value() - (Array::element_offset(0) >> kWordSizeLog2);
jselement.AddProperty("parentListIndex", element_index);
- } else if (source.IsInstance()) {
- source_class = source.clazz();
- parent_field_map = source_class.OffsetToFieldMap();
- intptr_t offset = slot_offset.Value();
- if (offset > 0 && offset < parent_field_map.Length()) {
- field ^= parent_field_map.At(offset);
- jselement.AddProperty("parentField", field);
- }
} else {
- intptr_t element_index = slot_offset.Value();
- jselement.AddProperty("_parentWordOffset", element_index);
+ if (source.IsInstance()) {
+ source_class = source.clazz();
+ parent_field_map = source_class.OffsetToFieldMap();
+ intptr_t offset = slot_offset.Value();
+ if (offset > 0 && offset < parent_field_map.Length()) {
+ field ^= parent_field_map.At(offset);
+ if (!field.IsNull()) {
+ jselement.AddProperty("parentField", field);
+ continue;
+ }
+ }
+ }
+ const char* field_name = offsets_table.FieldNameForOffset(
+ source.GetClassId(), slot_offset.Value() * kWordSize);
+ if (field_name != nullptr) {
+ jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+ // TODO(vm-service): Adjust RPC type to allow returning a field name
+ // without a field object, or reify the fields described by
+ // raw_object_fields.cc
+ // jselement.AddProperty("_parentFieldName", field_name);
+ } else if (source.IsContext()) {
+ intptr_t element_index =
+ slot_offset.Value() -
+ (Context::variable_offset(0) >> kWordSizeLog2);
+ jselement.AddProperty("parentListIndex", element_index);
+ } else {
+ jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+ }
}
}
}
@@ -2236,6 +2256,7 @@
WeakProperty& wp = WeakProperty::Handle();
String& name = String::Handle();
limit = Utils::Minimum(limit, length);
+ OffsetsTable offsets_table(thread->zone());
for (intptr_t i = 0; i < limit; ++i) {
JSONObject jselement(&elements);
element = path.At(i * 2);
@@ -2266,23 +2287,32 @@
wp ^= static_cast<WeakPropertyPtr>(element.ptr());
element = wp.key();
jselement.AddProperty("parentMapKey", element);
- } else if (element.IsInstance()) {
- element_class = element.clazz();
- element_field_map = element_class.OffsetToFieldMap();
- OS::PrintErr("Class: %s Map: %s\n", element_class.ToCString(),
- element_field_map.ToCString());
- intptr_t offset = slot_offset.Value();
- if (offset > 0 && offset < element_field_map.Length()) {
- field ^= element_field_map.At(offset);
- ASSERT(!field.IsNull());
- // TODO(bkonyi): check for mapping between C++ name and Dart name (V8
- // snapshot writer?)
- name ^= field.name();
- jselement.AddProperty("parentField", name.ToCString());
- }
} else {
- intptr_t element_index = slot_offset.Value();
- jselement.AddProperty("_parentWordOffset", element_index);
+ if (element.IsInstance()) {
+ element_class = element.clazz();
+ element_field_map = element_class.OffsetToFieldMap();
+ intptr_t offset = slot_offset.Value();
+ if ((offset > 0) && (offset < element_field_map.Length())) {
+ field ^= element_field_map.At(offset);
+ if (!field.IsNull()) {
+ name ^= field.name();
+ jselement.AddProperty("parentField", name.ToCString());
+ continue;
+ }
+ }
+ }
+ const char* field_name = offsets_table.FieldNameForOffset(
+ element.GetClassId(), slot_offset.Value() * kWordSize);
+ if (field_name != nullptr) {
+ jselement.AddProperty("parentField", field_name);
+ } else if (element.IsContext()) {
+ intptr_t element_index =
+ slot_offset.Value() -
+ (Context::variable_offset(0) >> kWordSizeLog2);
+ jselement.AddProperty("parentListIndex", element_index);
+ } else {
+ jselement.AddProperty("_parentWordOffset", slot_offset.Value());
+ }
}
}
}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 98cf5e8..a5e1837 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -48,7 +48,6 @@
import 'dart:_internal'
show
EfficientLengthIterable,
- LateError,
MappedIterable,
IterableElementError,
SubListIterable;
@@ -3025,9 +3024,6 @@
const kRequiredSentinel = const _Required();
bool isRequired(Object? value) => identical(kRequiredSentinel, value);
-/// Called by generated code to throw a LateInitializationError.
-void throwLateInitializationError(String name) => throw LateError(name);
-
/// Checks that [f] is a function that supports interop.
@pragma('dart2js:tryInline')
bool isJSFunction(Function f) => JS('bool', 'typeof(#) == "function"', f);
diff --git a/sdk/lib/_internal/js_runtime/lib/late_helper.dart b/sdk/lib/_internal/js_runtime/lib/late_helper.dart
new file mode 100644
index 0000000..e6136e8
--- /dev/null
+++ b/sdk/lib/_internal/js_runtime/lib/late_helper.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2021, 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.
+
+library _late_helper;
+
+import 'dart:_internal' show LateError;
+
+void throwLateFieldADI(String fieldName) => throw LateError.fieldADI(fieldName);
+
+/// A boxed variable used for lowering `late` variables when they are local or
+/// uninitialized statics.
+///
+/// The [LateError]s produced have empty variable names.
+class _Cell {
+ Object? _value;
+
+ _Cell() {
+ // `this` is a unique sentinel.
+ _value = this;
+ }
+
+ @pragma('dart2js:tryInline')
+ @pragma('dart2js:as:trust')
+ T readLocal<T>() => _readLocal() as T;
+
+ @pragma('dart2js:tryInline')
+ @pragma('dart2js:as:trust')
+ T readField<T>() => _readField() as T;
+
+ Object? _readLocal() {
+ if (identical(_value, this)) throw LateError.localNI('');
+ return _value;
+ }
+
+ Object? _readField() {
+ if (identical(_value, this)) throw LateError.fieldNI('');
+ return _value;
+ }
+
+ void set value(Object? v) {
+ _value = v;
+ }
+
+ void set finalLocalValue(Object? v) {
+ // TODO(fishythefish): Throw [LateError.localADI] if this occurs during
+ // recursive initialization.
+ if (!identical(_value, this)) throw LateError.localAI('');
+ _value = v;
+ }
+
+ void set finalFieldValue(Object? v) {
+ // TODO(fishythefish): Throw [LateError.fieldADI] if this occurs during
+ // recursive initialization.
+ if (!identical(_value, this)) throw LateError.fieldAI('');
+ _value = v;
+ }
+}
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 84d68ad..8e56fe9 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -149,6 +149,8 @@
dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
"_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
categories: "", documented: false, platforms: DART2JS_PLATFORM),
+ "_late_helper": const LibraryInfo("_internal/js_runtime/lib/late_helper.dart",
+ categories: "", documented: false, platforms: DART2JS_PLATFORM),
"_rti": const LibraryInfo("_internal/js_runtime/lib/rti.dart",
categories: "", documented: false, platforms: DART2JS_PLATFORM),
"_interceptors": const LibraryInfo(
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 6fd58c3..8715d25 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -17,10 +17,30 @@
/// not support the service protocol, this is 0.
final int minorVersion = _getServiceMinorVersion();
- /// The Uri to access the service. If the web server is not running, this
- /// will be null.
+ /// The Uri to connect to the debugger client hosted by the service. If the
+ /// web server is not running, this will be null.
final Uri? serverUri;
+ /// The Uri to connect to the service via web socket. If the web server is
+ /// not running, this will be null.
+ Uri? get serverWebSocketUri {
+ Uri? uri = serverUri;
+ if (uri != null) {
+ final pathSegments = <String>[];
+ if (uri.pathSegments.isNotEmpty) {
+ pathSegments.addAll(uri.pathSegments.where(
+ // Strip out the empty string that appears at the end of path segments.
+ // Empty string elements will result in an extra '/' being added to the
+ // URI.
+ (s) => s.isNotEmpty,
+ ));
+ }
+ pathSegments.add('ws');
+ uri = uri.replace(scheme: 'ws', pathSegments: pathSegments);
+ }
+ return uri;
+ }
+
ServiceProtocolInfo(this.serverUri);
String toString() {
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 8f584e2..a595503 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -242,6 +242,9 @@
"_js_helper": {
"uri": "_internal/js_runtime/lib/js_helper.dart"
},
+ "_late_helper": {
+ "uri": "_internal/js_runtime/lib/late_helper.dart"
+ },
"_rti": {
"uri": "_internal/js_runtime/lib/rti.dart"
},
@@ -338,6 +341,9 @@
"_js_helper": {
"uri": "_internal/js_runtime/lib/js_helper.dart"
},
+ "_late_helper": {
+ "uri": "_internal/js_runtime/lib/late_helper.dart"
+ },
"_rti": {
"uri": "_internal/js_runtime/lib/rti.dart"
},
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 89e3640..87beca8 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -240,6 +240,9 @@
_js_helper:
uri: "_internal/js_runtime/lib/js_helper.dart"
+ _late_helper:
+ uri: "_internal/js_runtime/lib/late_helper.dart"
+
_rti:
uri: "_internal/js_runtime/lib/rti.dart"
@@ -334,6 +337,9 @@
_js_helper:
uri: "_internal/js_runtime/lib/js_helper.dart"
+ _late_helper:
+ uri: "_internal/js_runtime/lib/late_helper.dart"
+
_rti:
uri: "_internal/js_runtime/lib/rti.dart"
diff --git a/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart b/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart
new file mode 100644
index 0000000..09ce941
--- /dev/null
+++ b/tests/language/const_functions/const_functions_try_catch_finally_error_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2021, 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.
+
+// Tests erroneous try-catch and try-finally with const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = finallyThrow(0);
+// ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+const var2 = finallyThrow(1);
+// ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int finallyThrow(int x) {
+ try {
+ if (x == 1) {
+ throw x;
+ } else {
+ return 0;
+ }
+ } finally {
+ throw 2;
+ }
+}
+
+const var3 = unhandledThrow(0);
+// ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+const var4 = unhandledThrow("string");
+// ^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int unhandledThrow(dynamic x) {
+ try {
+ throw x;
+ } on String catch (e) {
+ throw e;
+ }
+}
+
+const var5 = unhandledThrow2();
+// ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int unhandledThrow2() {
+ int count = 0;
+ for (int i = 0; i < 1; throw 'a') {
+ count += i;
+ }
+ return 0;
+}
diff --git a/tests/language/const_functions/const_functions_try_catch_finally_test.dart b/tests/language/const_functions/const_functions_try_catch_finally_test.dart
new file mode 100644
index 0000000..5c56167
--- /dev/null
+++ b/tests/language/const_functions/const_functions_try_catch_finally_test.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2021, 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.
+
+// Tests try-catch and try-finally with const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = fn("s");
+// ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var2 = fn(1);
+// ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn(dynamic error) {
+ try {
+ throw error;
+ } on String {
+ return 0;
+ } catch (e) {
+ return 1;
+ }
+}
+
+const var3 = fn1(10);
+// ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var4 = fn1("s");
+// ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn1(dynamic error) {
+ try {
+ throw error;
+ } on int catch (e) {
+ return e;
+ } catch (e) {
+ return 1;
+ }
+}
+
+const var5 = finallyReturn(10);
+// ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var6 = finallyReturn("s");
+// ^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var7 = finallyReturn(1);
+// ^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyReturn(dynamic error) {
+ try {
+ if (error != 1) throw error;
+ } on int catch (e) {
+ return e;
+ } catch (e) {
+ return 1;
+ } finally {
+ return 100;
+ }
+}
+
+const var8 = finallyReturn1(0);
+// ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+const var9 = finallyReturn1(1);
+// ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyReturn1(int x) {
+ try {
+ if (x == 1) {
+ throw x;
+ } else {
+ return 0;
+ }
+ } finally {
+ return 100;
+ }
+}
+
+const var10 = finallyMutate();
+// ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int finallyMutate() {
+ int x = 0;
+ try {
+ return x;
+ } finally {
+ x++;
+ }
+}
+
+const var11 = subtypeFn();
+// ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int subtypeFn() {
+ try {
+ throw 2.5;
+ } on num catch (e) {
+ return 0;
+ }
+}
+
+const var12 = orderFn();
+// ^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+String orderFn() {
+ String x = "st";
+ try {
+ x += "ri";
+ throw 2;
+ } catch (e) {
+ x += "n";
+ } finally {
+ return x + "g";
+ }
+}
+
+const var13 = notThrowStatement();
+// ^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int notThrowStatement() {
+ int count = 0;
+ try {
+ for (int i = 0; i < 1; throw 'a') {
+ count += i;
+ }
+ } catch (e) {
+ return 1;
+ }
+ return 0;
+}
+
+void main() {
+ Expect.equals(var1, 0);
+ Expect.equals(var2, 1);
+ Expect.equals(var3, 10);
+ Expect.equals(var4, 1);
+ Expect.equals(var5, 100);
+ Expect.equals(var6, 100);
+ Expect.equals(var7, 100);
+ Expect.equals(var8, 100);
+ Expect.equals(var9, 100);
+ Expect.equals(var10, 0);
+ Expect.equals(var11, 0);
+ Expect.equals(var12, "string");
+ Expect.equals(var13, 1);
+}
diff --git a/tests/language/nnbd/late/chained_assignment_test.dart b/tests/language/nnbd/late/chained_assignment_test.dart
new file mode 100644
index 0000000..1ca1c65
--- /dev/null
+++ b/tests/language/nnbd/late/chained_assignment_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2021, 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:expect/expect.dart';
+
+class Foo {
+ int x = 0;
+
+ int _y = 0;
+ int get y => _y;
+ void set y(int y) => _y = y;
+
+ static late int z;
+ late int w;
+}
+
+void main() {
+ final foo = Foo();
+ int a = 0;
+ late int b;
+ late int c;
+ late int d;
+
+ b = a = 1;
+ Expect.equals(a, 1);
+ Expect.equals(b, 1);
+
+ a = b = 2;
+ Expect.equals(a, 2);
+ Expect.equals(b, 2);
+
+ b = foo.x = 3;
+ Expect.equals(foo.x, 3);
+ Expect.equals(b, 3);
+
+ foo.x = b = 4;
+ Expect.equals(foo.x, 4);
+ Expect.equals(b, 4);
+
+ b = foo.y = 5;
+ Expect.equals(foo.y, 5);
+ Expect.equals(b, 5);
+
+ foo.y = b = 6;
+ Expect.equals(foo.y, 6);
+ Expect.equals(b, 6);
+
+ b = c = 7;
+ Expect.equals(b, 7);
+ Expect.equals(c, 7);
+
+ d = b = 8;
+ Expect.equals(b, 8);
+ Expect.equals(d, 8);
+
+ Foo.z = a = 9;
+ Expect.equals(a, 9);
+ Expect.equals(Foo.z, 9);
+
+ a = Foo.z = 10;
+ Expect.equals(a, 10);
+ Expect.equals(Foo.z, 10);
+
+ Foo.z = foo.x = 11;
+ Expect.equals(foo.x, 11);
+ Expect.equals(Foo.z, 11);
+
+ foo.x = Foo.z = 12;
+ Expect.equals(foo.x, 12);
+ Expect.equals(Foo.z, 12);
+
+ Foo.z = foo.y = 13;
+ Expect.equals(foo.y, 13);
+ Expect.equals(Foo.z, 13);
+
+ foo.y = Foo.z = 14;
+ Expect.equals(foo.y, 14);
+ Expect.equals(Foo.z, 14);
+
+ foo.w = a = 15;
+ Expect.equals(a, 15);
+ Expect.equals(foo.w, 15);
+
+ a = foo.w = 16;
+ Expect.equals(a, 16);
+ Expect.equals(foo.w, 16);
+
+ foo.w = foo.x = 17;
+ Expect.equals(foo.x, 17);
+ Expect.equals(foo.w, 17);
+
+ foo.x = foo.w = 18;
+ Expect.equals(foo.x, 18);
+ Expect.equals(foo.w, 18);
+
+ foo.w = foo.y = 19;
+ Expect.equals(foo.y, 19);
+ Expect.equals(foo.w, 19);
+
+ foo.y = foo.w = 20;
+ Expect.equals(foo.y, 20);
+ Expect.equals(foo.w, 20);
+}
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 914a376..9b5f403 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -118,4 +118,4 @@
optimize/deopt_inlined_function_lazy_test: Skip
[ $mode == debug && ($hot_reload || $hot_reload_rollback) ]
-regress/regress41983_test: Pass, Slow
+regress/regress41983_test: Pass, Slow
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index 3a74f75..78626b7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 216
+PRERELEASE 217
PRERELEASE_PATCH 0
\ No newline at end of file