Version 2.13.0-160.0.dev
Merge commit 'b047c6e1886b21b7f4ccdcbf91fa6e00839afe3d' into 'dev'
diff --git a/DEPS b/DEPS
index 225447d..a2adf45 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
# hashes. It requires access to the dart-build-access group, which EngProd
# has.
- "co19_rev": "1abf208ef6428aac8fee6f3175d65b1c59cd15c8",
+ "co19_rev": "ae818220b12ec9c2470519db2c7167cbe4745e12",
"co19_2_rev": "cf6eed0535e45413672bb5bb6e65df9f59846372",
# The internal benchmarks to use. See go/dart-benchmarks-internal
@@ -654,8 +654,6 @@
}
}
-# TODO(iposva): Move the necessary tools so that hooks can be run
-# without the runtime being available.
hooks = [
{
"name": "firefox_jsshell",
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
index cae9a5f..d7fbe42 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
@@ -782,6 +782,7 @@
class _CheckPromoted extends Statement {
final Var variable;
final String? expectedTypeStr;
+ final StackTrace _creationTrace = StackTrace.current;
_CheckPromoted(this.variable, this.expectedTypeStr) : super._();
@@ -800,11 +801,7 @@
void _visit(
Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
var promotedType = flow.promotedType(variable);
- if (expectedTypeStr == null) {
- expect(promotedType, isNull);
- } else {
- expect(promotedType?.type, expectedTypeStr);
- }
+ expect(promotedType?.type, expectedTypeStr, reason: '$_creationTrace');
}
}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart
new file mode 100644
index 0000000..1f92f0d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart
@@ -0,0 +1,91 @@
+// 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.
+
+// This test contains a test case for each condition that can lead to the front
+// end's `ArgumentTypeNotAssignableNullability` error, for which we wish to
+// report "why not promoted" context information.
+
+class C1 {
+ int? bad;
+ f(int i) {}
+}
+
+required_unnamed(C1 c) {
+ if (c.bad == null) return;
+ c.f(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: int?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: int?))*/ bad);
+}
+
+class C2 {
+ int? bad;
+ f([int i = 0]) {}
+}
+
+optional_unnamed(C2 c) {
+ if (c.bad == null) return;
+ c.f(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C2.bad, type: int?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C2.bad, type: int?))*/ bad);
+}
+
+class C3 {
+ int? bad;
+ f({required int i}) {}
+}
+
+required_named(C3 c) {
+ if (c.bad == null) return;
+ c.f(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C3.bad, type: int?))*/ i:
+ c. /*cfe.notPromoted(propertyNotPromoted(target: member:C3.bad, type: int?))*/ bad);
+}
+
+class C4 {
+ int? bad;
+ f({int i = 0}) {}
+}
+
+optional_named(C4 c) {
+ if (c.bad == null) return;
+ c.f(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C4.bad, type: int?))*/ i:
+ c. /*cfe.notPromoted(propertyNotPromoted(target: member:C4.bad, type: int?))*/ bad);
+}
+
+class C5 {
+ List<int>? bad;
+ f<T>(List<T> x) {}
+}
+
+type_inferred(C5 c) {
+ if (c.bad == null) return;
+ c.f(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C5.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C5.bad, type: List<int>?))*/ bad);
+}
+
+class C6 {
+ int? bad;
+ C6(int i);
+}
+
+C6 constructor_with_implicit_new(C6 c) {
+ if (c.bad == null) return;
+ return C6(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C6.bad, type: int?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C6.bad, type: int?))*/ bad);
+}
+
+class C7 {
+ int? bad;
+ C7(int i);
+}
+
+C7 constructor_with_explicit_new(C7 c) {
+ if (c.bad == null) return;
+ return new C7(
+ /*analyzer.notPromoted(propertyNotPromoted(target: member:C7.bad, type: int?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C7.bad, type: int?))*/ bad);
+}
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index b0164f2..9f4fee7 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -15,7 +15,6 @@
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 5f512c5..245abf6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analysis_server/src/provisional/completion/completion_core.dart'
- show AbortCompletion, CompletionRequest;
import 'package:analysis_server/src/provisional/completion/completion_core.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/completion_core.dart';
diff --git a/pkg/analysis_server/test/integration/server/bazel_changes_test.dart b/pkg/analysis_server/test/integration/server/bazel_changes_test.dart
index a70cd13..edca9a7 100644
--- a/pkg/analysis_server/test/integration/server/bazel_changes_test.dart
+++ b/pkg/analysis_server/test/integration/server/bazel_changes_test.dart
@@ -132,7 +132,7 @@
// error again.
await resetCompleterAndErrors();
writeFile(generatedFilePath, 'different_fun() {}');
- writeFile(commandLogPath, 'Build completed successfully');
+ writeFile(commandLogPath, 'Build completed');
await processedNotification.future;
expect(errors, isNotEmpty);
@@ -140,7 +140,7 @@
// Now delete the file completely.
await resetCompleterAndErrors();
File(generatedFilePath).deleteSync();
- writeFile(commandLogPath, 'Build completed successfully');
+ writeFile(commandLogPath, 'Build did NOT complete successfully');
await processedNotification.future;
expect(errors, isNotEmpty);
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index ed9332f..9996e7f 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -27,6 +27,7 @@
linter:
rules:
- always_use_package_imports
+ - avoid_dynamic_calls
- avoid_unused_constructor_parameters
- await_only_futures
- empty_statements
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0703381..3cec775 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 132;
+ static const int DATA_VERSION = 133;
/// The length of the list returned by [_computeDeclaredVariablesSignature].
static const int _declaredVariablesSignatureLength = 4;
diff --git a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
index f2e5968..ae49c26 100644
--- a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
@@ -179,6 +179,14 @@
if (leftOperand is int && rightOperand is int) {
return leftOperand >> rightOperand;
}
+ } else if (node.operator.type == TokenType.GT_GT_GT) {
+ if (leftOperand is int && rightOperand is int) {
+ // TODO(srawlins): Replace with native VM implementation once stable.
+ return rightOperand >= 64
+ ? 0
+ : (leftOperand >> rightOperand) &
+ ((1 << (64 - rightOperand)) - 1);
+ }
} else if (node.operator.type == TokenType.LT) {
// numeric or {@code null}
if (leftOperand is num && rightOperand is num) {
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index ca4a5a1..6bb7701 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -2063,21 +2063,13 @@
var rightValue = rightOperand.value;
if (rightValue == null) {
return UNKNOWN_VALUE;
- } else if (rightValue.bitLength > 31) {
- return UNKNOWN_VALUE;
- }
- if (rightValue >= 0) {
- // TODO(brianwilkerson) After the analyzer package has a minimum SDK
- // constraint that includes support for the real operator, consider
- // changing the line below to
- // return new IntState(value >>> rightValue);
- int divisor = 1 << rightValue;
- if (divisor == 0) {
- // The `rightValue` is large enough to cause all of the non-zero bits
- // in the left operand to be shifted out of the value.
- return IntState(0);
- }
- return IntState(value! ~/ divisor);
+ } else if (rightValue >= 64) {
+ return IntState(0);
+ } else if (rightValue >= 0) {
+ // TODO(srawlins): Replace with real operator once stable, like:
+ // return new IntState(value >>> rightValue);
+ return IntState(
+ (value! >> rightValue) & ((1 << (64 - rightValue)) - 1));
}
}
throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 39fe163..2ffd93d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -28,11 +29,12 @@
bool get _genericMetadataIsEnabled =>
_definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
- void resolve(AnnotationImpl node) {
+ void resolve(AnnotationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
AstNode parent = node.parent;
node.typeArguments?.accept(_resolver);
- _resolve(node);
+ _resolve(node, whyNotPromotedInfo);
var elementAnnotationImpl =
node.elementAnnotation as ElementAnnotationImpl?;
@@ -48,6 +50,7 @@
AnnotationImpl node,
ClassElement classElement,
SimpleIdentifierImpl? getterName,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
ExecutableElement? getter;
if (getterName != null) {
@@ -63,7 +66,7 @@
node.element = getter;
if (getterName != null && getter is PropertyAccessorElement) {
- _propertyAccessorElement(node, getterName, getter);
+ _propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
_resolveAnnotationElementGetter(node, getter);
} else if (getter is! ConstructorElement) {
_errorReporter.reportErrorForNode(
@@ -72,7 +75,7 @@
);
}
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
}
void _constructorInvocation(
@@ -80,6 +83,7 @@
ClassElement classElement,
SimpleIdentifierImpl? constructorName,
ArgumentList argumentList,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
ConstructorElement? constructorElement;
if (constructorName != null) {
@@ -99,7 +103,8 @@
CompileTimeErrorCode.INVALID_ANNOTATION,
node,
);
- argumentList.accept(_resolver);
+ _resolver.visitArgumentList(argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
return;
}
@@ -109,7 +114,8 @@
if (typeParameters.isEmpty) {
_resolveConstructorInvocationArguments(node);
InferenceContext.setType(argumentList, constructorElement.type);
- argumentList.accept(_resolver);
+ _resolver.visitArgumentList(argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
return;
}
@@ -127,7 +133,8 @@
_resolveConstructorInvocationArguments(node);
InferenceContext.setType(argumentList, constructorElement.type);
- argumentList.accept(_resolver);
+ _resolver.visitArgumentList(argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
if (!_genericMetadataIsEnabled) {
@@ -156,7 +163,8 @@
return;
}
- argumentList.accept(_resolver);
+ _resolver.visitArgumentList(argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
var constructorRawType = _resolver.typeAnalyzer
.constructorToGenericFunctionType(constructorElement);
@@ -186,6 +194,7 @@
AnnotationImpl node,
ExtensionElement extensionElement,
SimpleIdentifierImpl? getterName,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
ExecutableElement? getter;
if (getterName != null) {
@@ -197,7 +206,7 @@
node.element = getter;
if (getterName != null && getter is PropertyAccessorElement) {
- _propertyAccessorElement(node, getterName, getter);
+ _propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
_resolveAnnotationElementGetter(node, getter);
} else {
_errorReporter.reportErrorForNode(
@@ -206,23 +215,25 @@
);
}
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
}
void _propertyAccessorElement(
AnnotationImpl node,
SimpleIdentifierImpl name,
PropertyAccessorElement element,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
element = _resolver.toLegacyElement(element);
name.staticElement = element;
node.element = element;
_resolveAnnotationElementGetter(node, element);
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
}
- void _resolve(AnnotationImpl node) {
+ void _resolve(AnnotationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
SimpleIdentifierImpl name1;
SimpleIdentifierImpl? name2;
SimpleIdentifierImpl? name3;
@@ -246,23 +257,24 @@
node,
[name1.name],
);
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
return;
}
// Class(args) or Class.CONST
if (element1 is ClassElement) {
if (argumentList != null) {
- _constructorInvocation(node, element1, name2, argumentList);
+ _constructorInvocation(
+ node, element1, name2, argumentList, whyNotPromotedInfo);
} else {
- _classGetter(node, element1, name2);
+ _classGetter(node, element1, name2, whyNotPromotedInfo);
}
return;
}
// Extension.CONST
if (element1 is ExtensionElement) {
- _extensionGetter(node, element1, name2);
+ _extensionGetter(node, element1, name2, whyNotPromotedInfo);
return;
}
@@ -274,20 +286,21 @@
// prefix.Class(args) or prefix.Class.CONST
if (element2 is ClassElement) {
if (argumentList != null) {
- _constructorInvocation(node, element2, name3, argumentList);
+ _constructorInvocation(
+ node, element2, name3, argumentList, whyNotPromotedInfo);
} else {
- _classGetter(node, element2, name3);
+ _classGetter(node, element2, name3, whyNotPromotedInfo);
}
return;
}
// prefix.Extension.CONST
if (element2 is ExtensionElement) {
- _extensionGetter(node, element2, name3);
+ _extensionGetter(node, element2, name3, whyNotPromotedInfo);
return;
}
// prefix.CONST
if (element2 is PropertyAccessorElement) {
- _propertyAccessorElement(node, name2, element2);
+ _propertyAccessorElement(node, name2, element2, whyNotPromotedInfo);
return;
}
// undefined
@@ -297,7 +310,7 @@
node,
[name2.name],
);
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
return;
}
}
@@ -305,7 +318,7 @@
// CONST
if (element1 is PropertyAccessorElement) {
- _propertyAccessorElement(node, name1, element1);
+ _propertyAccessorElement(node, name1, element1, whyNotPromotedInfo);
return;
}
@@ -319,7 +332,7 @@
node,
);
- node.arguments?.accept(_resolver);
+ _visitArguments(node, whyNotPromotedInfo);
}
void _resolveAnnotationElementGetter(
@@ -379,4 +392,13 @@
}
}
}
+
+ void _visitArguments(AnnotationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ var arguments = node.arguments;
+ if (arguments != null) {
+ _resolver.visitArgumentList(arguments,
+ whyNotPromotedInfo: whyNotPromotedInfo);
+ }
+ }
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 6617ab2..a515061 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -35,11 +36,12 @@
NullableDereferenceVerifier get _nullableDereferenceVerifier =>
_resolver.nullableDereferenceVerifier;
- void resolve(FunctionExpressionInvocationImpl node) {
+ void resolve(FunctionExpressionInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var function = node.function;
if (function is ExtensionOverrideImpl) {
- _resolveReceiverExtensionOverride(node, function);
+ _resolveReceiverExtensionOverride(node, function, whyNotPromotedInfo);
return;
}
@@ -49,12 +51,13 @@
// `_nullableDereferenceVerifier.expression` because
// `_resolveReceiverInterfaceType` calls `TypePropertyResolver.resolve`,
// which does the necessary null checking.
- _resolveReceiverInterfaceType(node, function, receiverType);
+ _resolveReceiverInterfaceType(
+ node, function, receiverType, whyNotPromotedInfo);
return;
}
if (_checkForUseOfVoidResult(function, receiverType)) {
- _unresolved(node, DynamicTypeImpl.instance);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
return;
}
@@ -62,18 +65,18 @@
errorCode: CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE);
if (receiverType is FunctionType) {
- _resolve(node, receiverType);
+ _resolve(node, receiverType, whyNotPromotedInfo);
return;
}
if (identical(receiverType, NeverTypeImpl.instance)) {
_errorReporter.reportErrorForNode(
HintCode.RECEIVER_OF_TYPE_NEVER, function);
- _unresolved(node, NeverTypeImpl.instance);
+ _unresolved(node, NeverTypeImpl.instance, whyNotPromotedInfo);
return;
}
- _unresolved(node, DynamicTypeImpl.instance);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
}
/// Check for situations where the result of a method or function is used,
@@ -100,10 +103,12 @@
return true;
}
- void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType) {
+ void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
_inferenceHelper.resolveFunctionExpressionInvocation(
node: node,
rawType: rawType,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
var returnType = _inferenceHelper.computeInvokeReturnType(
@@ -112,13 +117,16 @@
_inferenceHelper.recordStaticType(node, returnType);
}
- void _resolveArguments(FunctionExpressionInvocationImpl node) {
- node.argumentList.accept(_resolver);
+ void _resolveArguments(FunctionExpressionInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ _resolver.visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
void _resolveReceiverExtensionOverride(
FunctionExpressionInvocationImpl node,
ExtensionOverride function,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
var result = _extensionResolver.getOverrideMember(
function,
@@ -133,7 +141,7 @@
function,
[function.extensionName.name],
);
- return _unresolved(node, DynamicTypeImpl.instance);
+ return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
}
if (callElement.isStatic) {
@@ -144,13 +152,14 @@
}
var rawType = callElement.type;
- _resolve(node, rawType);
+ _resolve(node, rawType, whyNotPromotedInfo);
}
void _resolveReceiverInterfaceType(
FunctionExpressionInvocationImpl node,
Expression function,
InterfaceType receiverType,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
var result = _typePropertyResolver.resolve(
receiver: function,
@@ -168,7 +177,7 @@
function,
);
}
- _unresolved(node, DynamicTypeImpl.instance);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
return;
}
@@ -177,18 +186,19 @@
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
function,
);
- _unresolved(node, DynamicTypeImpl.instance);
+ _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
return;
}
node.staticElement = callElement;
var rawType = callElement.type;
- _resolve(node, rawType);
+ _resolve(node, rawType, whyNotPromotedInfo);
}
- void _unresolved(FunctionExpressionInvocationImpl node, DartType type) {
+ void _unresolved(FunctionExpressionInvocationImpl node, DartType type,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
_setExplicitTypeArgumentTypes(node);
- _resolveArguments(node);
+ _resolveArguments(node, whyNotPromotedInfo);
node.staticInvokeType = DynamicTypeImpl.instance;
node.staticType = type;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 461b264..865c8dd 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -207,6 +208,8 @@
void resolveFunctionExpressionInvocation({
required FunctionExpressionInvocationImpl node,
required FunctionType rawType,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
_resolveInvocation(
rawType: rawType,
@@ -215,6 +218,7 @@
contextType: InferenceContext.getContext(node),
isConst: false,
errorNode: node.function,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
node.typeArgumentTypes = _typeArgumentTypes;
@@ -229,6 +233,8 @@
void resolveMethodInvocation({
required MethodInvocationImpl node,
required FunctionType rawType,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
_resolveInvocation(
rawType: rawType,
@@ -237,6 +243,7 @@
contextType: InferenceContext.getContext(node),
isConst: false,
errorNode: node.function,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
node.typeArgumentTypes = _typeArgumentTypes;
@@ -325,9 +332,11 @@
return false;
}
- void _resolveArguments(ArgumentList argumentList) {
+ void _resolveArguments(ArgumentList argumentList,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
_resolver.visitArgumentList(argumentList,
- isIdentical: _isCallToIdentical(argumentList.parent));
+ isIdentical: _isCallToIdentical(argumentList.parent),
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
void _resolveInvocation({
@@ -337,12 +346,15 @@
required ArgumentListImpl argumentList,
required bool isConst,
required AstNode errorNode,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
if (typeArgumentList != null) {
_resolveInvocationWithTypeArguments(
rawType: rawType,
typeArgumentList: typeArgumentList,
argumentList: argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
} else {
_resolveInvocationWithoutTypeArguments(
@@ -351,6 +363,7 @@
argumentList: argumentList,
isConst: isConst,
errorNode: errorNode,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
_setCorrespondingParameters(argumentList, _invokeType!);
@@ -362,12 +375,14 @@
required ArgumentList argumentList,
required bool isConst,
required AstNode errorNode,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
var typeParameters = rawType.typeFormals;
if (typeParameters.isEmpty) {
InferenceContext.setType(argumentList, rawType);
- _resolveArguments(argumentList);
+ _resolveArguments(argumentList, whyNotPromotedInfo);
_typeArgumentTypes = const <DartType>[];
_invokeType = rawType;
@@ -384,7 +399,7 @@
var downwardsInvokeType = rawType.instantiate(downwardsTypeArguments);
InferenceContext.setType(argumentList, downwardsInvokeType);
- _resolveArguments(argumentList);
+ _resolveArguments(argumentList, whyNotPromotedInfo);
_typeArgumentTypes = _inferUpwards(
rawType: rawType,
@@ -401,6 +416,8 @@
required FunctionType rawType,
required TypeArgumentList typeArgumentList,
required ArgumentList argumentList,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
var typeParameters = rawType.typeFormals;
@@ -428,7 +445,7 @@
var invokeType = rawType.instantiate(typeArguments);
InferenceContext.setType(argumentList, invokeType);
- _resolveArguments(argumentList);
+ _resolveArguments(argumentList, whyNotPromotedInfo);
_typeArgumentTypes = typeArguments;
_invokeType = invokeType;
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index c2d6338..7310f7e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
@@ -80,7 +81,8 @@
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
- void resolve(MethodInvocationImpl node) {
+ void resolve(MethodInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
_invocation = node;
var nameNode = node.methodName;
@@ -90,14 +92,15 @@
var receiver = node.realTarget;
if (receiver == null) {
- _resolveReceiverNull(node, nameNode, name);
+ _resolveReceiverNull(node, nameNode, name, whyNotPromotedInfo);
return;
}
if (receiver is SimpleIdentifierImpl) {
var receiverElement = receiver.staticElement;
if (receiverElement is PrefixElement) {
- _resolveReceiverPrefix(node, receiverElement, nameNode, name);
+ _resolveReceiverPrefix(
+ node, receiverElement, nameNode, name, whyNotPromotedInfo);
return;
}
}
@@ -105,32 +108,34 @@
if (receiver is IdentifierImpl) {
var receiverElement = receiver.staticElement;
if (receiverElement is ExtensionElement) {
- _resolveExtensionMember(
- node, receiver, receiverElement, nameNode, name);
+ _resolveExtensionMember(node, receiver, receiverElement, nameNode, name,
+ whyNotPromotedInfo);
return;
}
}
if (receiver is SuperExpressionImpl) {
- _resolveReceiverSuper(node, receiver, nameNode, name);
+ _resolveReceiverSuper(node, receiver, nameNode, name, whyNotPromotedInfo);
return;
}
if (receiver is ExtensionOverrideImpl) {
- _resolveExtensionOverride(node, receiver, nameNode, name);
+ _resolveExtensionOverride(
+ node, receiver, nameNode, name, whyNotPromotedInfo);
return;
}
if (receiver is IdentifierImpl) {
var element = receiver.staticElement;
if (element is ClassElement) {
- _resolveReceiverTypeLiteral(node, element, nameNode, name);
+ _resolveReceiverTypeLiteral(
+ node, element, nameNode, name, whyNotPromotedInfo);
return;
} else if (element is TypeAliasElement) {
var aliasedType = element.aliasedType;
if (aliasedType is InterfaceType) {
_resolveReceiverTypeLiteral(
- node, aliasedType.element, nameNode, name);
+ node, aliasedType.element, nameNode, name, whyNotPromotedInfo);
return;
}
}
@@ -139,17 +144,17 @@
DartType receiverType = receiver.typeOrThrow;
if (_typeSystem.isDynamicBounded(receiverType)) {
- _resolveReceiverDynamicBounded(node);
+ _resolveReceiverDynamicBounded(node, whyNotPromotedInfo);
return;
}
if (receiverType is NeverTypeImpl) {
- _resolveReceiverNever(node, receiver, receiverType);
+ _resolveReceiverNever(node, receiver, receiverType, whyNotPromotedInfo);
return;
}
if (receiverType is VoidType) {
- _reportUseOfVoidType(node, receiver);
+ _reportUseOfVoidType(node, receiver, whyNotPromotedInfo);
return;
}
@@ -160,7 +165,7 @@
if (_typeSystem.isFunctionBounded(receiverType)) {
_resolveReceiverFunctionBounded(
- node, receiver, receiverType, nameNode, name);
+ node, receiver, receiverType, nameNode, name, whyNotPromotedInfo);
return;
}
@@ -171,6 +176,7 @@
nameNode: nameNode,
name: name,
receiverErrorNode: receiver,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
@@ -210,8 +216,10 @@
}
}
- void _reportInvocationOfNonFunction(MethodInvocationImpl node) {
- _setDynamicResolution(node, setNameTypeToDynamic: false);
+ void _reportInvocationOfNonFunction(MethodInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ _setDynamicResolution(node,
+ setNameTypeToDynamic: false, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION,
node.methodName,
@@ -242,8 +250,10 @@
MethodInvocationImpl node, {
required String? prefix,
required String name,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
return;
@@ -257,8 +267,11 @@
}
void _reportUndefinedMethod(
- MethodInvocationImpl node, String name, ClassElement typeReference) {
- _setDynamicResolution(node);
+ MethodInvocationImpl node,
+ String name,
+ ClassElement typeReference,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_METHOD,
node.methodName,
@@ -266,8 +279,9 @@
);
}
- void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode) {
- _setDynamicResolution(node);
+ void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.USE_OF_VOID_RESULT,
errorNode,
@@ -276,17 +290,20 @@
/// [InvocationExpression.staticInvokeType] has been set for the [node].
/// Use it to set context for arguments, and resolve them.
- void _resolveArguments(MethodInvocationImpl node) {
+ void _resolveArguments(MethodInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
// TODO(scheglov) This is bad, don't write raw type, carry it
_inferenceHelper.inferArgumentTypesForInvocation(
node,
node.methodName.staticType,
);
- node.argumentList.accept(_resolver);
+ _resolver.visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
- void _resolveArguments_finishInference(MethodInvocationImpl node) {
- _resolveArguments(node);
+ void _resolveArguments_finishInference(MethodInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ _resolveArguments(node, whyNotPromotedInfo);
// TODO(scheglov) This is bad, don't put / get raw FunctionType this way.
_inferenceHelper.inferGenericInvocationExpression(
@@ -318,8 +335,13 @@
return null;
}
- void _resolveExtensionMember(MethodInvocationImpl node, Identifier receiver,
- ExtensionElement extension, SimpleIdentifierImpl nameNode, String name) {
+ void _resolveExtensionMember(
+ MethodInvocationImpl node,
+ Identifier receiver,
+ ExtensionElement extension,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var getter = extension.getGetter(name);
if (getter != null) {
getter = _resolver.toLegacyElement(getter);
@@ -334,11 +356,11 @@
method = _resolver.toLegacyElement(method);
nameNode.staticElement = method;
_reportStaticAccessToInstanceMember(method, nameNode);
- _setResolution(node, method.type);
+ _setResolution(node, method.type, whyNotPromotedInfo);
return;
}
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
nameNode,
@@ -346,13 +368,17 @@
);
}
- void _resolveExtensionOverride(MethodInvocationImpl node,
- ExtensionOverride override, SimpleIdentifierImpl nameNode, String name) {
+ void _resolveExtensionOverride(
+ MethodInvocationImpl node,
+ ExtensionOverride override,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var result = _extensionResolver.getOverrideMember(override, name);
var member = _resolver.toLegacyElement(result.getter);
if (member == null) {
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
nameNode,
@@ -382,10 +408,11 @@
return _rewriteAsFunctionExpressionInvocation(node, member.returnType);
}
- _setResolution(node, member.type);
+ _setResolution(node, member.type, whyNotPromotedInfo);
}
- void _resolveReceiverDynamicBounded(MethodInvocationImpl node) {
+ void _resolveReceiverDynamicBounded(MethodInvocationImpl node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var nameNode = node.methodName;
var objectElement = _typeSystem.typeProvider.objectElement;
@@ -411,7 +438,8 @@
}
_setExplicitTypeArgumentTypes();
- node.argumentList.accept(_resolver);
+ _resolver.visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
void _resolveReceiverFunctionBounded(
@@ -420,9 +448,10 @@
DartType receiverType,
SimpleIdentifierImpl nameNode,
String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
if (name == FunctionElement.CALL_METHOD_NAME) {
- _setResolution(node, receiverType);
+ _setResolution(node, receiverType, whyNotPromotedInfo);
// TODO(scheglov) Replace this with using FunctionType directly.
// Here was erase resolution that _setResolution() sets.
nameNode.staticElement = null;
@@ -437,6 +466,7 @@
nameNode: nameNode,
name: name,
receiverErrorNode: nameNode,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
@@ -444,6 +474,7 @@
MethodInvocationImpl node,
Expression receiver,
DartType receiverType,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
_setExplicitTypeArgumentTypes();
@@ -457,9 +488,10 @@
_setResolution(
node,
objectMember.type,
+ whyNotPromotedInfo,
);
} else {
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.nullableDereferenceVerifier.report(receiver, receiverType,
errorCode: CompileTimeErrorCode
.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE);
@@ -472,7 +504,7 @@
node.staticInvokeType = _dynamicType;
node.staticType = NeverTypeImpl.instance;
- _resolveArguments(node);
+ _resolveArguments(node, whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
HintCode.RECEIVER_OF_TYPE_NEVER,
@@ -486,13 +518,16 @@
node.staticInvokeType = _dynamicType;
node.staticType = _dynamicType;
- _resolveArguments(node);
+ _resolveArguments(node, whyNotPromotedInfo);
return;
}
}
void _resolveReceiverNull(
- MethodInvocationImpl node, SimpleIdentifierImpl nameNode, String name) {
+ MethodInvocationImpl node,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var element = nameScope.lookup(name).getter;
if (element != null) {
element = _resolver.toLegacyElement(element);
@@ -505,7 +540,7 @@
return _rewriteAsFunctionExpressionInvocation(node, element.returnType);
}
if (element is ExecutableElement) {
- return _setResolution(node, element.type);
+ return _setResolution(node, element.type, whyNotPromotedInfo);
}
if (element is VariableElement) {
_resolver.checkReadOfNotAssignedLocalVariable(nameNode, element);
@@ -514,10 +549,10 @@
}
// TODO(scheglov) This is a questionable distinction.
if (element is PrefixElement) {
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
return _reportPrefixIdentifierNotFollowedByDot(nameNode);
}
- return _reportInvocationOfNonFunction(node);
+ return _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
}
DartType receiverType;
@@ -530,6 +565,7 @@
node,
prefix: null,
name: node.methodName.name,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
@@ -540,11 +576,16 @@
nameNode: nameNode,
name: name,
receiverErrorNode: nameNode,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
- void _resolveReceiverPrefix(MethodInvocationImpl node, PrefixElement prefix,
- SimpleIdentifierImpl nameNode, String name) {
+ void _resolveReceiverPrefix(
+ MethodInvocationImpl node,
+ PrefixElement prefix,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
// Note: prefix?.bar is reported as an error in ElementResolver.
if (name == FunctionElement.LOAD_LIBRARY_NAME) {
@@ -555,7 +596,8 @@
element = _resolver.toLegacyElement(element);
if (element is ExecutableElement) {
nameNode.staticElement = element;
- return _setResolution(node, (element as ExecutableElement).type);
+ return _setResolution(
+ node, (element as ExecutableElement).type, whyNotPromotedInfo);
}
}
}
@@ -574,21 +616,26 @@
}
if (element is ExecutableElement) {
- return _setResolution(node, element.type);
+ return _setResolution(node, element.type, whyNotPromotedInfo);
}
_reportUndefinedFunction(
node,
prefix: prefix.name,
name: name,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
- void _resolveReceiverSuper(MethodInvocationImpl node,
- SuperExpression receiver, SimpleIdentifierImpl nameNode, String name) {
+ void _resolveReceiverSuper(
+ MethodInvocationImpl node,
+ SuperExpression receiver,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
var enclosingClass = _resolver.enclosingClass;
if (SuperContext.of(receiver) != SuperContext.valid) {
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
return;
}
@@ -605,7 +652,7 @@
if (target is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
}
- _setResolution(node, target.type);
+ _setResolution(node, target.type, whyNotPromotedInfo);
return;
}
@@ -615,7 +662,7 @@
target = _inheritance.getInherited2(enclosingClass, _currentName!);
if (target != null) {
nameNode.staticElement = target;
- _setResolution(node, target.type);
+ _setResolution(node, target.type, whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
@@ -625,7 +672,7 @@
}
// Nothing help, there is no target at all.
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_SUPER_METHOD,
nameNode,
@@ -639,6 +686,8 @@
required SimpleIdentifierImpl nameNode,
required String name,
required Expression receiverErrorNode,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo,
}) {
var result = _resolver.typePropertyResolver.resolve(
receiver: receiver,
@@ -663,10 +712,10 @@
if (target is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
}
- return _setResolution(node, target.type);
+ return _setResolution(node, target.type, whyNotPromotedInfo);
}
- _setDynamicResolution(node);
+ _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
if (!result.needsGetterError) {
return;
@@ -688,8 +737,12 @@
}
}
- void _resolveReceiverTypeLiteral(MethodInvocationImpl node,
- ClassElement receiver, SimpleIdentifierImpl nameNode, String name) {
+ void _resolveReceiverTypeLiteral(
+ MethodInvocationImpl node,
+ ClassElement receiver,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
if (node.isCascaded) {
receiver = _typeType.element;
}
@@ -703,14 +756,14 @@
return _rewriteAsFunctionExpressionInvocation(
node, element.returnType);
}
- _setResolution(node, element.type);
+ _setResolution(node, element.type, whyNotPromotedInfo);
} else {
- _reportInvocationOfNonFunction(node);
+ _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
}
return;
}
- _reportUndefinedMethod(node, name, receiver);
+ _reportUndefinedMethod(node, name, receiver, whyNotPromotedInfo);
}
/// If the given [type] is a type parameter, replace with its bound.
@@ -770,14 +823,16 @@
}
void _setDynamicResolution(MethodInvocationImpl node,
- {bool setNameTypeToDynamic = true}) {
+ {bool setNameTypeToDynamic = true,
+ required List<Map<DartType, NonPromotionReason> Function()>
+ whyNotPromotedInfo}) {
if (setNameTypeToDynamic) {
node.methodName.staticType = _dynamicType;
}
node.staticInvokeType = _dynamicType;
node.staticType = _dynamicType;
_setExplicitTypeArgumentTypes();
- _resolveArguments_finishInference(node);
+ _resolveArguments_finishInference(node, whyNotPromotedInfo);
}
/// Set explicitly specified type argument types, or empty if not specified.
@@ -796,26 +851,29 @@
}
}
- void _setResolution(MethodInvocationImpl node, DartType type) {
+ void _setResolution(MethodInvocationImpl node, DartType type,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
// TODO(scheglov) We need this for StaticTypeAnalyzer to run inference.
// But it seems weird. Do we need to know the raw type of a function?!
node.methodName.staticType = type;
if (type == _dynamicType || _isCoreFunction(type)) {
- _setDynamicResolution(node, setNameTypeToDynamic: false);
+ _setDynamicResolution(node,
+ setNameTypeToDynamic: false, whyNotPromotedInfo: whyNotPromotedInfo);
return;
}
if (type is FunctionType) {
- _inferenceHelper.resolveMethodInvocation(node: node, rawType: type);
+ _inferenceHelper.resolveMethodInvocation(
+ node: node, rawType: type, whyNotPromotedInfo: whyNotPromotedInfo);
return;
}
if (type is VoidType) {
- return _reportUseOfVoidType(node, node.methodName);
+ return _reportUseOfVoidType(node, node.methodName, whyNotPromotedInfo);
}
- _reportInvocationOfNonFunction(node);
+ _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
}
/// Resolver visitor is separated from the elements resolver, which calls
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 921c948..423b5df 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -394,8 +395,12 @@
}
@override
- void visitMethodInvocation(MethodInvocation node) {
- _methodInvocationResolver.resolve(node as MethodInvocationImpl);
+ void visitMethodInvocation(MethodInvocation node,
+ {List<Map<DartType, NonPromotionReason> Function()>?
+ whyNotPromotedInfo}) {
+ whyNotPromotedInfo ??= [];
+ _methodInvocationResolver.resolve(
+ node as MethodInvocationImpl, whyNotPromotedInfo);
}
@override
diff --git a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
index 92b0652..7ffc94c 100644
--- a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
+++ b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
@@ -2,9 +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.
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
@@ -28,7 +31,8 @@
Expression expression,
DartType? expectedStaticType,
DartType actualStaticType,
- ErrorCode errorCode) {
+ ErrorCode errorCode,
+ {Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo}) {
// Warning case: test static type information
if (expectedStaticType != null) {
if (!expectedStaticType.isVoid && checkForUseOfVoidResult(expression)) {
@@ -36,7 +40,8 @@
}
checkForAssignableExpressionAtType(
- expression, actualStaticType, expectedStaticType, errorCode);
+ expression, actualStaticType, expectedStaticType, errorCode,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
}
@@ -48,11 +53,13 @@
///
/// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
void checkForArgumentTypeNotAssignableForArgument(Expression argument,
- {bool promoteParameterToNullable = false}) {
+ {bool promoteParameterToNullable = false,
+ Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo}) {
checkForArgumentTypeNotAssignableForArgument2(
argument: argument,
parameter: argument.staticParameterElement,
promoteParameterToNullable: promoteParameterToNullable,
+ whyNotPromotedInfo: whyNotPromotedInfo,
);
}
@@ -60,21 +67,26 @@
required Expression argument,
required ParameterElement? parameter,
required bool promoteParameterToNullable,
+ Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo,
}) {
var staticParameterType = parameter?.type;
if (promoteParameterToNullable && staticParameterType != null) {
staticParameterType =
typeSystem.makeNullable(staticParameterType as TypeImpl);
}
- _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
- staticParameterType, CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
+ _checkForArgumentTypeNotAssignableWithExpectedTypes(
+ argument,
+ staticParameterType,
+ CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+ whyNotPromotedInfo);
}
bool checkForAssignableExpressionAtType(
Expression expression,
DartType actualStaticType,
DartType expectedStaticType,
- ErrorCode errorCode) {
+ ErrorCode errorCode,
+ {Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo}) {
if (!typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
AstNode getErrorNode(AstNode node) {
if (node is CascadeExpression) {
@@ -90,6 +102,8 @@
errorCode,
getErrorNode(expression),
[actualStaticType, expectedStaticType],
+ computeWhyNotPromotedMessages(
+ expression, expression, whyNotPromotedInfo?.call()),
);
return false;
}
@@ -118,6 +132,22 @@
return true;
}
+ /// Computes the appropriate set of context messages to report along with an
+ /// error that may have occurred because [expression] was not type promoted.
+ ///
+ /// If [expression] is `null`, it means the expression that was not type
+ /// promoted was an implicit `this`.
+ ///
+ /// [errorEntity] is the entity whose location will be associated with the
+ /// error. This is needed for test instrumentation.
+ ///
+ /// [whyNotPromoted] should be the non-promotion details returned by the flow
+ /// analysis engine.
+ List<DiagnosticMessage> computeWhyNotPromotedMessages(
+ Expression? expression,
+ SyntacticEntity errorEntity,
+ Map<DartType, NonPromotionReason>? whyNotPromoted);
+
/// Verify that the given [expression] can be assigned to its corresponding
/// parameters.
///
@@ -131,8 +161,10 @@
void _checkForArgumentTypeNotAssignableWithExpectedTypes(
Expression expression,
DartType? expectedStaticType,
- ErrorCode errorCode) {
+ ErrorCode errorCode,
+ Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo) {
checkForArgumentTypeNotAssignable(
- expression, expectedStaticType, expression.typeOrThrow, errorCode);
+ expression, expectedStaticType, expression.typeOrThrow, errorCode,
+ whyNotPromotedInfo: whyNotPromotedInfo);
}
}
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4dd8078..55a6019 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4,6 +4,7 @@
import 'dart:collection';
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
@@ -13,6 +14,7 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
@@ -309,6 +311,14 @@
_featureSet?.isEnabled(Feature.non_nullable) ?? false;
@override
+ List<DiagnosticMessage> computeWhyNotPromotedMessages(
+ Expression? expression,
+ SyntacticEntity errorEntity,
+ Map<DartType, NonPromotionReason>? whyNotPromoted) {
+ return [];
+ }
+
+ @override
void visitAnnotation(Annotation node) {
_checkForInvalidAnnotationFromDeferredLibrary(node);
_checkForMissingJSLibAnnotation(node);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7027e52..dff2a86 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -427,9 +427,13 @@
/// [BestPracticesVerifier.checkForArgumentTypesNotAssignableInList].
///
/// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
- void checkForArgumentTypesNotAssignableInList(ArgumentList argumentList) {
- for (Expression argument in argumentList.arguments) {
- checkForArgumentTypeNotAssignableForArgument(argument);
+ void checkForArgumentTypesNotAssignableInList(ArgumentList argumentList,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+ var arguments = argumentList.arguments;
+ for (int i = 0; i < arguments.length; i++) {
+ checkForArgumentTypeNotAssignableForArgument(arguments[i],
+ whyNotPromotedInfo:
+ flowAnalysis?.flow == null ? null : whyNotPromotedInfo[i]);
}
}
@@ -527,21 +531,14 @@
nullSafetyDeadCodeVerifier.visitNode(node);
}
- /// Computes the appropriate set of context messages to report along with an
- /// error that may have occurred because [expression] was not type promoted.
- ///
- /// If [expression] is `null`, it means the expression that was not type
- /// promoted was an implicit `this`.
- ///
- /// [errorEntity] is the entity whose location will be associated with the
- /// error. This is needed for test instrumentation.
- ///
- /// [whyNotPromoted] should be the non-promotion details returned by the flow
- /// analysis engine.
+ @override
List<DiagnosticMessage> computeWhyNotPromotedMessages(
Expression? expression,
SyntacticEntity errorEntity,
Map<DartType, NonPromotionReason>? whyNotPromoted) {
+ if (expression is NamedExpression) {
+ expression = expression.expression;
+ }
List<DiagnosticMessage> messages = [];
if (whyNotPromoted != null) {
for (var entry in whyNotPromoted.entries) {
@@ -885,21 +882,25 @@
@override
void visitAnnotation(covariant AnnotationImpl node) {
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
AstNode parent = node.parent;
if (identical(parent, _enclosingClassDeclaration) ||
identical(parent, _enclosingFunctionTypeAlias) ||
identical(parent, _enclosingMixinDeclaration)) {
return;
}
- AnnotationResolver(this).resolve(node);
+ AnnotationResolver(this).resolve(node, whyNotPromotedInfo);
var arguments = node.arguments;
if (arguments != null) {
- checkForArgumentTypesNotAssignableInList(arguments);
+ checkForArgumentTypesNotAssignableInList(arguments, whyNotPromotedInfo);
}
}
@override
- void visitArgumentList(ArgumentList node, {bool isIdentical = false}) {
+ void visitArgumentList(ArgumentList node,
+ {bool isIdentical = false,
+ List<Map<DartType, NonPromotionReason> Function()>? whyNotPromotedInfo}) {
+ whyNotPromotedInfo ??= [];
var callerType = InferenceContext.getContext(node);
NodeList<Expression> arguments = node.arguments;
if (callerType is FunctionType) {
@@ -958,17 +959,20 @@
}
checkUnreachableNode(node);
int length = arguments.length;
+ var flow = flowAnalysis?.flow;
for (var i = 0; i < length; i++) {
if (isIdentical && length > 1 && i == 1) {
var firstArg = arguments[0];
- flowAnalysis?.flow
- ?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
+ flow?.equalityOp_rightBegin(firstArg, firstArg.typeOrThrow);
}
arguments[i].accept(this);
+ if (flow != null) {
+ whyNotPromotedInfo.add(flow.whyNotPromoted(arguments[i]));
+ }
}
if (isIdentical && length > 1) {
var secondArg = arguments[1];
- flowAnalysis?.flow?.equalityOp_end(
+ flow?.equalityOp_end(
node.parent as Expression, secondArg, secondArg.typeOrThrow);
}
node.accept(elementResolver);
@@ -1427,11 +1431,13 @@
@override
void visitExtensionOverride(ExtensionOverride node) {
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
node.extensionName.accept(this);
node.typeArguments?.accept(this);
ExtensionMemberResolver(this).setOverrideReceiverContextType(node);
- node.argumentList.accept(this);
+ visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
node.accept(elementResolver);
node.accept(typeAnalyzer);
@@ -1548,11 +1554,13 @@
@override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
node.function.accept(this);
- _functionExpressionInvocationResolver
- .resolve(node as FunctionExpressionInvocationImpl);
+ _functionExpressionInvocationResolver.resolve(
+ node as FunctionExpressionInvocationImpl, whyNotPromotedInfo);
nullShortingTermination(node);
- checkForArgumentTypesNotAssignableInList(node.argumentList);
+ checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedInfo);
}
@override
@@ -1694,12 +1702,15 @@
@override
void visitInstanceCreationExpression(
covariant InstanceCreationExpressionImpl node) {
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
node.constructorName.accept(this);
_inferArgumentTypesForInstanceCreate(node);
- node.argumentList.accept(this);
+ visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
node.accept(elementResolver);
node.accept(typeAnalyzer);
- checkForArgumentTypesNotAssignableInList(node.argumentList);
+ checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedInfo);
}
@override
@@ -1764,6 +1775,7 @@
@override
void visitMethodInvocation(covariant MethodInvocationImpl node) {
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
var target = node.target;
target?.accept(this);
@@ -1782,16 +1794,19 @@
}
node.typeArguments?.accept(this);
- node.accept(elementResolver);
+ elementResolver.visitMethodInvocation(node,
+ whyNotPromotedInfo: whyNotPromotedInfo);
var functionRewrite = MethodInvocationResolver.getRewriteResult(node);
if (functionRewrite != null) {
nullShortingTermination(node, discardType: true);
- _resolveRewrittenFunctionExpressionInvocation(functionRewrite);
+ _resolveRewrittenFunctionExpressionInvocation(
+ functionRewrite, whyNotPromotedInfo);
} else {
nullShortingTermination(node);
}
- checkForArgumentTypesNotAssignableInList(node.argumentList);
+ checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedInfo);
}
@override
@@ -1904,11 +1919,14 @@
// because it needs to be visited in the context of the constructor
// invocation.
//
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
node.accept(elementResolver);
InferenceContext.setType(node.argumentList, node.staticElement?.type);
- node.argumentList.accept(this);
+ visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
node.accept(typeAnalyzer);
- checkForArgumentTypesNotAssignableInList(node.argumentList);
+ checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedInfo);
}
@override
@@ -1962,11 +1980,14 @@
// because it needs to be visited in the context of the constructor
// invocation.
//
+ var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
node.accept(elementResolver);
InferenceContext.setType(node.argumentList, node.staticElement?.type);
- node.argumentList.accept(this);
+ visitArgumentList(node.argumentList,
+ whyNotPromotedInfo: whyNotPromotedInfo);
node.accept(typeAnalyzer);
- checkForArgumentTypesNotAssignableInList(node.argumentList);
+ checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedInfo);
}
@override
@@ -2271,6 +2292,7 @@
/// as for method invocations.
void _resolveRewrittenFunctionExpressionInvocation(
FunctionExpressionInvocation node,
+ List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
) {
var function = node.function;
@@ -2287,8 +2309,8 @@
}
}
- _functionExpressionInvocationResolver
- .resolve(node as FunctionExpressionInvocationImpl);
+ _functionExpressionInvocationResolver.resolve(
+ node as FunctionExpressionInvocationImpl, whyNotPromotedInfo);
nullShortingTermination(node);
}
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index c7846a4..077b56b 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -5,7 +5,6 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
diff --git a/pkg/analyzer/lib/src/workspace/bazel_watcher.dart b/pkg/analyzer/lib/src/workspace/bazel_watcher.dart
index 5d76920..1109c63 100644
--- a/pkg/analyzer/lib/src/workspace/bazel_watcher.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel_watcher.dart
@@ -435,9 +435,13 @@
/// Determines how often do we check for `command.log` changes.
static const _pollInterval = Duration(seconds: 1);
- /// To confirm that a build finished, we check for this message in the
+ /// To confirm that a build finished, we check for these messages in the
/// `command.log`.
- static const _buildCompletedMsg = 'Build completed successfully';
+ static const _buildCompletedMsgs = [
+ 'Build completed successfully',
+ 'Build completed',
+ 'Build did NOT complete successfully',
+ ];
final _controller = StreamController<WatchEvent>.broadcast();
final ResourceProvider _provider;
@@ -459,7 +463,7 @@
bool _buildFinished(String contents) {
// Only look at the last 100 characters.
var offset = max(0, contents.length - 100);
- return contents.contains(_buildCompletedMsg, offset);
+ return _buildCompletedMsgs.any((msg) => contents.contains(msg, offset));
}
Future<String?> _getCommandLogPath() async {
diff --git a/pkg/analyzer/tool/summary/stats.dart b/pkg/analyzer/tool/summary/stats.dart
index 86c0677..d03b7db 100644
--- a/pkg/analyzer/tool/summary/stats.dart
+++ b/pkg/analyzer/tool/summary/stats.dart
@@ -66,6 +66,9 @@
value == false ||
value == '' ||
value is List && value.isEmpty ||
+ // TODO(srawlins): Remove this and enumerate each enum which may
+ // be encountered.
+ // ignore: avoid_dynamic_calls
reflect(value).type.isEnum && (value as dynamic).index == 0) {
return;
}
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index ce57087..233f053 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -146,6 +146,9 @@
CompoundName.from(List<jsAst.Name> parts) : this(<_NamerName>[...parts]);
@override
+ bool get isFinalized => _parts.every((name) => name.isFinalized);
+
+ @override
String get name {
if (_cachedName == null) {
_cachedName = _parts.map((jsAst.Name name) => name.name).join();
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index d9d65cc..122a716 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -2,6 +2,7 @@
// 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 'dart:collection';
import '../../deferred_load.dart' show OutputUnit;
import '../../js/js.dart' as js;
import '../../js/size_estimator.dart';
@@ -283,6 +284,7 @@
class _Partition {
int size = 0;
List<PreFragment> fragments = [];
+ bool isClosed = false;
void add(PreFragment that) {
size += that.size;
@@ -377,6 +379,38 @@
});
}
+ /// Given a list of [PreFragments], returns a list of lists of [PreFragments]
+ /// where each list represents a component in the graph.
+ List<List<PreFragment>> separateComponents(
+ List<PreFragment> preDeferredFragments) {
+ List<List<PreFragment>> components = [];
+ Set<PreFragment> visited = {};
+
+ // Starting from each 'root' in the graph, use bfs to find a component.
+ for (var preFragment in preDeferredFragments) {
+ if (preFragment.predecessors.isEmpty && visited.add(preFragment)) {
+ List<PreFragment> component = [];
+ var queue = Queue<PreFragment>();
+ queue.add(preFragment);
+ while (queue.isNotEmpty) {
+ var preFragment = queue.removeFirst();
+ component.add(preFragment);
+ preFragment.predecessors.where(visited.add).forEach(queue.add);
+ preFragment.successors.where(visited.add).forEach(queue.add);
+ }
+
+ // Sort the fragments in the component so they will be in a canonical
+ // order.
+ component.sort((a, b) {
+ return a.fragments.single.outputUnit
+ .compareTo(b.fragments.single.outputUnit);
+ });
+ components.add(component);
+ }
+ }
+ return components;
+ }
+
/// A trivial greedy merge that uses the sorted order of the output units to
/// merge contiguous runs of fragments without creating cycles.
/// ie, if our sorted output units look like:
@@ -386,28 +420,26 @@
/// fragment size of 5. Our final partitions would look like:
/// {a}, {b}, {c}+{a, b}, {b, c}+{a, b, c}.
List<PreFragment> mergeFragments(List<PreFragment> preDeferredFragments) {
- // Sort PreFragments by their initial OutputUnit so they are in canonical
- // order.
- preDeferredFragments.sort((a, b) {
- return a.fragments.single.outputUnit
- .compareTo(b.fragments.single.outputUnit);
- });
+ var components = separateComponents(preDeferredFragments);
int desiredNumberOfFragment = _options.mergeFragmentsThreshold;
-
int idealFragmentSize = (totalSize / desiredNumberOfFragment).ceil();
List<_Partition> partitions = [];
void add(PreFragment next) {
// Create a new partition if the current one grows too large, otherwise
// just add to the most recent partition.
if (partitions.isEmpty ||
+ partitions.last.isClosed ||
partitions.last.size + next.size > idealFragmentSize) {
partitions.add(_Partition());
}
partitions.last.add(next);
}
- // Greedily group fragments into partitions.
- preDeferredFragments.forEach(add);
+ // Greedily group fragments into partitions, but only within each component.
+ for (var component in components) {
+ component.forEach(add);
+ partitions.last.isClosed = true;
+ }
// Reduce fragments by merging fragments with fewer imports into fragments
// with more imports.
diff --git a/pkg/compiler/test/deferred_loading/data/components/libA.dart b/pkg/compiler/test/deferred_loading/data/components/libA.dart
new file mode 100644
index 0000000..156d3fc
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libA.dart
@@ -0,0 +1,8 @@
+// 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.
+
+/*member: component:member_unit=1{libA}*/
+String component() {
+ return 'libA';
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/libB.dart b/pkg/compiler/test/deferred_loading/data/components/libB.dart
new file mode 100644
index 0000000..87b10d5
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libB.dart
@@ -0,0 +1,10 @@
+// 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 "libBCDE.dart";
+
+/*member: component:member_unit=2{libB}*/
+String component() {
+ return componentBCDE();
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/libBCDE.dart b/pkg/compiler/test/deferred_loading/data/components/libBCDE.dart
new file mode 100644
index 0000000..77a74fe
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libBCDE.dart
@@ -0,0 +1,9 @@
+// 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.
+
+@pragma('dart2js:noInline')
+/*member: componentBCDE:member_unit=3{libB, libC, libD, libE}*/
+String componentBCDE() {
+ return 'libBCDE';
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/libC.dart b/pkg/compiler/test/deferred_loading/data/components/libC.dart
new file mode 100644
index 0000000..d13a2f5
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libC.dart
@@ -0,0 +1,10 @@
+// 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 "libBCDE.dart";
+
+/*member: component:member_unit=4{libC}*/
+String component() {
+ return componentBCDE();
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/libD.dart b/pkg/compiler/test/deferred_loading/data/components/libD.dart
new file mode 100644
index 0000000..c20123e
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libD.dart
@@ -0,0 +1,10 @@
+// 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 "libBCDE.dart";
+
+/*member: component:member_unit=5{libD}*/
+String component() {
+ return componentBCDE();
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/libE.dart b/pkg/compiler/test/deferred_loading/data/components/libE.dart
new file mode 100644
index 0000000..fd8e3c2
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/libE.dart
@@ -0,0 +1,10 @@
+// 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 "libBCDE.dart";
+
+/*member: component:member_unit=6{libE}*/
+String component() {
+ return componentBCDE();
+}
diff --git a/pkg/compiler/test/deferred_loading/data/components/main.dart b/pkg/compiler/test/deferred_loading/data/components/main.dart
new file mode 100644
index 0000000..e918bf6
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/data/components/main.dart
@@ -0,0 +1,69 @@
+// 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.
+
+/*spec.library:
+ output_units=[
+ f1: {units: [1{libA}], usedBy: [], needs: []},
+ f2: {units: [3{libB, libC, libD, libE}], usedBy: [], needs: []},
+ f3: {units: [2{libB}], usedBy: [], needs: []},
+ f4: {units: [4{libC}], usedBy: [], needs: []},
+ f5: {units: [5{libD}], usedBy: [], needs: []},
+ f6: {units: [6{libE}], usedBy: [], needs: []}],
+ steps=[
+ libA=(f1),
+ libB=(f2, f3),
+ libC=(f2, f4),
+ libD=(f2, f5),
+ libE=(f2, f6)]
+*/
+
+/*two-frag.library:
+ output_units=[
+ f1: {units: [1{libA}], usedBy: [], needs: []},
+ f2: {units: [3{libB, libC, libD, libE}, 6{libE}], usedBy: [], needs: [3]},
+ f3: {units: [5{libD}, 4{libC}, 2{libB}], usedBy: [2], needs: []}],
+ steps=[
+ libA=(f1),
+ libB=(f2, f3),
+ libC=(f2, f3),
+ libD=(f2, f3),
+ libE=(f2)]
+*/
+
+/*three-frag.library:
+ output_units=[
+ f1: {units: [1{libA}], usedBy: [], needs: []},
+ f2: {units: [3{libB, libC, libD, libE}], usedBy: [], needs: [3, 4]},
+ f3: {units: [4{libC}, 2{libB}], usedBy: [2], needs: []},
+ f4: {units: [6{libE}, 5{libD}], usedBy: [2], needs: []}],
+ steps=[
+ libA=(f1),
+ libB=(f2, f3),
+ libC=(f2, f3),
+ libD=(f2, f4),
+ libE=(f2, f4)]
+*/
+
+// @dart = 2.7
+
+import 'libA.dart' deferred as libA;
+import 'libB.dart' deferred as libB;
+import 'libC.dart' deferred as libC;
+import 'libD.dart' deferred as libD;
+import 'libE.dart' deferred as libE;
+
+/*member: main:member_unit=main{}*/
+main() async {
+ await libA.loadLibrary();
+ await libB.loadLibrary();
+ await libC.loadLibrary();
+ await libD.loadLibrary();
+ await libE.loadLibrary();
+
+ print(libA.component());
+ print(libB.component());
+ print(libC.component());
+ print(libD.component());
+ print(libE.component());
+}
diff --git a/pkg/dart_internal/lib/extract_type_arguments.dart b/pkg/dart_internal/lib/extract_type_arguments.dart
index 4275e70..6a02827 100644
--- a/pkg/dart_internal/lib/extract_type_arguments.dart
+++ b/pkg/dart_internal/lib/extract_type_arguments.dart
@@ -9,7 +9,6 @@
//
// Only this exact special file is allowed to import "dart:_internal" without
// causing a compile error.
-// ignore: import_internal_library
import 'dart:_internal' as internal;
/// Given an [Iterable], invokes [extract], passing the [iterable]'s type
diff --git a/runtime/platform/BUILD.gn b/runtime/platform/BUILD.gn
index c727eea..f339a1e 100644
--- a/runtime/platform/BUILD.gn
+++ b/runtime/platform/BUILD.gn
@@ -18,11 +18,20 @@
if (is_fuchsia) {
if (using_fuchsia_gn_sdk) {
- extra_deps += [ "$fuchsia_sdk_root/pkg/sys_cpp" ]
+ extra_deps += [
+ "$fuchsia_sdk_root/pkg/sys_cpp",
+ "$fuchsia_sdk_root/pkg/sys_inspect_cpp",
+ ]
} else if (using_fuchsia_sdk) {
- extra_deps += [ "$fuchsia_sdk_root/pkg:sys_cpp" ]
+ extra_deps += [
+ "$fuchsia_sdk_root/pkg:sys_cpp",
+ "$fuchsia_sdk_root/pkg:sys_inspect_cpp",
+ ]
} else {
- extra_deps += [ "//sdk/lib/sys/cpp" ]
+ extra_deps += [
+ "//sdk/lib/sys/cpp",
+ "//sdk/lib/sys/inspect/cpp",
+ ]
}
}
}
diff --git a/runtime/platform/utils_fuchsia.cc b/runtime/platform/utils_fuchsia.cc
index cfa17e6..a6d9f37 100644
--- a/runtime/platform/utils_fuchsia.cc
+++ b/runtime/platform/utils_fuchsia.cc
@@ -6,8 +6,10 @@
#if defined(HOST_OS_FUCHSIA)
#include <memory>
+#include <utility>
#include "lib/sys/cpp/component_context.h"
+#include "lib/sys/inspect/cpp/component.h"
#include "platform/utils.h"
#include "platform/utils_fuchsia.h"
@@ -57,6 +59,23 @@
return context.get();
}
+std::unique_ptr<inspect::Node> vm_node;
+void SetDartVmNode(std::unique_ptr<inspect::Node> node) {
+ vm_node = std::move(node);
+}
+
+std::unique_ptr<inspect::Node> TakeDartVmNode() {
+ // TODO(fxbug.dev/69558) Remove the creation of the node_ from this call
+ // after the runners have been migrated to injecting this object.
+ if (vm_node == nullptr) {
+ static std::unique_ptr<sys::ComponentInspector> component_inspector =
+ std::make_unique<sys::ComponentInspector>(dart::ComponentContext());
+ inspect::Node& root = component_inspector->inspector()->GetRoot();
+ vm_node = std::make_unique<inspect::Node>(root.CreateChild("vm"));
+ }
+ return std::move(vm_node);
+}
+
} // namespace dart
#endif // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/platform/utils_fuchsia.h b/runtime/platform/utils_fuchsia.h
index 4b2064e..b88328a 100644
--- a/runtime/platform/utils_fuchsia.h
+++ b/runtime/platform/utils_fuchsia.h
@@ -6,6 +6,7 @@
#define RUNTIME_PLATFORM_UTILS_FUCHSIA_H_
#include <endian.h>
+#include <memory>
namespace sys {
@@ -14,6 +15,13 @@
} // namespace sys
+namespace inspect {
+
+// From Fuchsia SDK.
+class Node;
+
+} // namespace inspect
+
namespace dart {
inline uint16_t Utils::HostToBigEndian16(uint16_t value) {
@@ -57,6 +65,18 @@
// call sys::ComponentContext::Create().
sys::ComponentContext* ComponentContext();
+// Sets the inspect node set to be used in the dart vm
+//
+// This method will take ownership of the node
+void SetDartVmNode(std::unique_ptr<inspect::Node> node);
+
+// Returns the inspect node set in SetDartVmNode().
+//
+// The caller should take ownership of the returned node because
+// the value will be set to null after this call.
+// This call may return null if no node is provided.
+std::unique_ptr<inspect::Node> TakeDartVmNode();
+
} // namespace dart
#endif // RUNTIME_PLATFORM_UTILS_FUCHSIA_H_
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 674bdd5..46c4303 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -80,23 +80,21 @@
// Under normal operation, all metric values below should be zero.
class InspectMetrics {
public:
- // Does not take ownership of inspector.
- explicit InspectMetrics(inspect::Inspector* inspector)
- : inspector_(inspector),
- root_(inspector_->GetRoot()),
- metrics_(root_.CreateChild("os")),
- dst_status_(metrics_.CreateInt("dst_status", kUninitialized)),
- tz_data_status_(metrics_.CreateInt("tz_data_status", kUninitialized)),
+ // Takes ownership of the vm_node.
+ explicit InspectMetrics(std::unique_ptr<inspect::Node> vm_node)
+ : vm_node_(std::move(vm_node)),
+ dst_status_(vm_node_->CreateInt("dst_status", kUninitialized)),
+ tz_data_status_(vm_node_->CreateInt("tz_data_status", kUninitialized)),
tz_data_close_status_(
- metrics_.CreateInt("tz_data_close_status", kUninitialized)),
+ vm_node_->CreateInt("tz_data_close_status", kUninitialized)),
get_profile_status_(
- metrics_.CreateInt("get_profile_status", kUninitialized)),
+ vm_node_->CreateInt("get_profile_status", kUninitialized)),
profiles_timezone_content_status_(
- metrics_.CreateInt("timezone_content_status", kOk)),
- num_get_profile_calls_(metrics_.CreateInt("num_get_profile_calls", 0)),
- num_on_change_calls_(metrics_.CreateInt("num_on_change_calls", 0)),
+ vm_node_->CreateInt("timezone_content_status", kOk)),
+ num_get_profile_calls_(vm_node_->CreateInt("num_get_profile_calls", 0)),
+ num_on_change_calls_(vm_node_->CreateInt("num_on_change_calls", 0)),
num_intl_provider_errors_(
- metrics_.CreateInt("num_intl_provider_errors", 0)) {}
+ vm_node_->CreateInt("num_intl_provider_errors", 0)) {}
// Registers a single call to GetProfile callback.
void RegisterGetProfileCall() { num_get_profile_calls_.Add(1); }
@@ -131,14 +129,8 @@
}
private:
- // The inspector that all metrics are being reported into.
- inspect::Inspector* inspector_;
-
- // References inspector_ state.
- inspect::Node& root_;
-
// The OS metrics node.
- inspect::Node metrics_;
+ std::unique_ptr<inspect::Node> vm_node_;
// The status of the last GetTimeZoneOffset call.
inspect::IntProperty dst_status_;
@@ -305,7 +297,6 @@
std::set<const std::string> timezone_names;
// Initialized on OS:Init(), deinitialized on OS::Cleanup.
-std::unique_ptr<sys::ComponentInspector> component_inspector;
std::shared_ptr<InspectMetrics> metrics;
std::shared_ptr<TimezoneName> timezone_name;
async_loop_t* message_loop = nullptr;
@@ -603,9 +594,11 @@
async_loop_start_thread(message_loop, "Fuchsia async loop", nullptr);
}
- sys::ComponentContext* context = dart::ComponentContext();
- component_inspector = std::make_unique<sys::ComponentInspector>(context);
- metrics = std::make_shared<InspectMetrics>(component_inspector->inspector());
+ auto vm_node = dart::TakeDartVmNode();
+
+ // TODO(fxbug.dev/69558) allow vm_node to be null and not crash
+ ASSERT(vm_node != nullptr);
+ metrics = std::make_shared<InspectMetrics>(std::move(vm_node));
InitializeTZData();
auto services = sys::ServiceDirectory::CreateFromNamespace();
@@ -620,7 +613,6 @@
}
timezone_name.reset();
metrics.reset();
- component_inspector.reset();
if (message_loop != nullptr) {
// Check message_loop is still the default dispatcher before clearing it.
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 906a9ee..609f66e 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -86,8 +86,6 @@
//
// Locking notes:
// The following locks are used by the timeline system:
-// - |Timeline::recorder_lock_| This lock is held whenever Timeline::recorder()
-// is accessed or modified.
// - |TimelineEventRecorder::lock_| This lock is held whenever a
// |TimelineEventBlock| is being requested or reclaimed.
// - |Thread::timeline_block_lock_| This lock is held whenever a |Thread|'s
@@ -96,10 +94,9 @@
// |Thread|s.
//
// Locks must always be taken in the following order:
-// |Timeline::recorder_lock_|
-// |Thread::thread_list_lock_|
-// |Thread::timeline_block_lock_|
-// |TimelineEventRecorder::lock_|
+// |Thread::thread_list_lock_|
+// |Thread::timeline_block_lock_|
+// |TimelineEventRecorder::lock_|
//
static TimelineEventRecorder* CreateTimelineRecorder() {
@@ -208,10 +205,6 @@
}
void Timeline::Init() {
- if (recorder_lock_ == nullptr) {
- recorder_lock_ = new Mutex();
- }
- MutexLocker ml(recorder_lock_);
ASSERT(recorder_ == NULL);
recorder_ = CreateTimelineRecorder();
ASSERT(recorder_ != NULL);
@@ -224,31 +217,25 @@
}
void Timeline::Cleanup() {
- ASSERT(recorder_lock_ != nullptr);
- TimelineEventRecorder* temp = recorder_;
- {
- MutexLocker ml(recorder_lock_);
- ASSERT(recorder_ != NULL);
+ ASSERT(recorder_ != NULL);
#ifndef PRODUCT
- if (FLAG_timeline_dir != NULL) {
- recorder_->WriteTo(FLAG_timeline_dir);
- }
+ if (FLAG_timeline_dir != NULL) {
+ recorder_->WriteTo(FLAG_timeline_dir);
+ }
#endif
- // Disable global streams.
+// Disable global streams.
#define TIMELINE_STREAM_DISABLE(name, fuchsia_name) \
Timeline::stream_##name##_.set_enabled(false);
- TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
#undef TIMELINE_STREAM_DISABLE
- recorder_ = NULL;
- if (enabled_streams_ != NULL) {
- FreeEnabledByDefaultTimelineStreams(enabled_streams_);
- enabled_streams_ = NULL;
- }
+ delete recorder_;
+ recorder_ = NULL;
+ if (enabled_streams_ != NULL) {
+ FreeEnabledByDefaultTimelineStreams(enabled_streams_);
+ enabled_streams_ = NULL;
}
- // We need to release the recorder lock to finish cleanup.
- delete temp;
}
TimelineEventRecorder* Timeline::recorder() {
@@ -256,29 +243,23 @@
}
void Timeline::ReclaimCachedBlocksFromThreads() {
- ASSERT(recorder_lock_ != nullptr);
- MutexLocker ml(recorder_lock_);
- ReclaimCachedBlocksFromThreadsLocked();
-}
-
-void Timeline::ReclaimCachedBlocksFromThreadsLocked() {
- ASSERT(recorder_lock_->IsOwnedByCurrentThread());
TimelineEventRecorder* recorder = Timeline::recorder();
+ if (recorder == NULL) {
+ return;
+ }
+
// Iterate over threads.
OSThreadIterator it;
while (it.HasNext()) {
OSThread* thread = it.Next();
- // TODO(johnmccutchan): Consider dropping the timeline_block_lock here
- // if we can do it everywhere. This would simplify the lock ordering
- // requirements.
-
MutexLocker ml(thread->timeline_block_lock());
// Grab block and clear it.
TimelineEventBlock* block = thread->timeline_block();
thread->set_timeline_block(NULL);
- if (recorder != nullptr) {
- recorder->FinishBlock(block);
- }
+ // TODO(johnmccutchan): Consider dropping the timeline_block_lock here
+ // if we can do it everywhere. This would simplify the lock ordering
+ // requirements.
+ recorder->FinishBlock(block);
}
}
@@ -293,8 +274,6 @@
}
void Timeline::PrintFlagsToJSON(JSONStream* js) {
- ASSERT(recorder_lock_ != nullptr);
- MutexLocker ml(recorder_lock_);
JSONObject obj(js);
obj.AddProperty("type", "TimelineFlags");
TimelineEventRecorder* recorder = Timeline::recorder();
@@ -322,13 +301,11 @@
#endif
void Timeline::Clear() {
- ASSERT(recorder_lock_ != nullptr);
- MutexLocker ml(recorder_lock_);
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder == NULL) {
return;
}
- ReclaimCachedBlocksFromThreadsLocked();
+ ReclaimCachedBlocksFromThreads();
recorder->Clear();
}
@@ -413,7 +390,6 @@
TimelineEventRecorder* Timeline::recorder_ = NULL;
MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
-Mutex* Timeline::recorder_lock_ = nullptr;
#define TIMELINE_STREAM_DEFINE(name, fuchsia_name) \
TimelineStream Timeline::stream_##name##_(#name, fuchsia_name, false);
@@ -580,8 +556,6 @@
}
void TimelineEvent::Complete() {
- ASSERT(Timeline::recorder_lock() != nullptr);
- MutexLocker ml(Timeline::recorder_lock());
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder != NULL) {
recorder->CompleteEvent(this);
@@ -801,10 +775,6 @@
}
TimelineEvent* TimelineStream::StartEvent() {
- if (Timeline::recorder_lock() == nullptr) {
- return nullptr;
- }
- MutexLocker ml(Timeline::recorder_lock());
TimelineEventRecorder* recorder = Timeline::recorder();
if (!enabled() || (recorder == NULL)) {
return NULL;
@@ -1167,7 +1137,6 @@
}
TimelineEventFixedBufferRecorder::~TimelineEventFixedBufferRecorder() {
- MutexLocker ml(&lock_);
// Delete all blocks.
for (intptr_t i = 0; i < num_blocks_; i++) {
blocks_[i].Reset();
@@ -1365,9 +1334,14 @@
: head_(nullptr), tail_(nullptr), block_index_(0) {}
TimelineEventEndlessRecorder::~TimelineEventEndlessRecorder() {
- // Ensures block state is cleared for each thread.
- Timeline::ReclaimCachedBlocksFromThreads();
- Clear();
+ TimelineEventBlock* current = head_;
+ head_ = tail_ = nullptr;
+
+ while (current != nullptr) {
+ TimelineEventBlock* next = current->next();
+ delete current;
+ current = next;
+ }
}
#ifndef PRODUCT
@@ -1450,7 +1424,6 @@
#endif
void TimelineEventEndlessRecorder::Clear() {
- MutexLocker ml(&lock_);
TimelineEventBlock* current = head_;
while (current != NULL) {
TimelineEventBlock* next = current->next();
@@ -1458,8 +1431,9 @@
current = next;
}
head_ = NULL;
- tail_ = NULL;
block_index_ = 0;
+ OSThread* thread = OSThread::Current();
+ thread->set_timeline_block(NULL);
}
TimelineEventBlock::TimelineEventBlock(intptr_t block_index)
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index a1eb5d6..38e739a 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -23,7 +23,7 @@
#if defined(__MAC_10_14) || defined (__IPHONE_12_0)
#define HOST_OS_SUPPORTS_SIGNPOST 1
#endif
-// signpost.h exists in macOS 10.14, iOS 12 or above
+//signpost.h exists in macOS 10.14, iOS 12 or above
#if defined(HOST_OS_SUPPORTS_SIGNPOST)
#include <os/signpost.h>
#else
@@ -123,18 +123,15 @@
class Timeline : public AllStatic {
public:
- // Initialize timeline system.
+ // Initialize timeline system. Not thread safe.
static void Init();
- // Cleanup timeline system.
+ // Cleanup timeline system. Not thread safe.
static void Cleanup();
- // Access the global recorder. recorder_lock() must be held when accessing
- // the returned |TimelineEventRecorder|.
+ // Access the global recorder. Not thread safe.
static TimelineEventRecorder* recorder();
- static Mutex* recorder_lock() { return recorder_lock_; }
-
// Reclaim all |TimelineEventBlocks|s that are cached by threads.
static void ReclaimCachedBlocksFromThreads();
@@ -161,13 +158,8 @@
#undef TIMELINE_STREAM_FLAGS
private:
- // Reclaims all |TimelineEventBlocks|s that are cached by threads, assuming
- // that lock_ is held.
- static void ReclaimCachedBlocksFromThreadsLocked();
-
static TimelineEventRecorder* recorder_;
static MallocGrowableArray<char*>* enabled_streams_;
- static Mutex* recorder_lock_;
#define TIMELINE_STREAM_DECLARE(name, fuchsia_name) \
static TimelineStream stream_##name##_;
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
index ac1ce05..70d162e 100644
--- a/runtime/vm/timeline_test.cc
+++ b/runtime/vm/timeline_test.cc
@@ -90,6 +90,11 @@
event->Complete();
}
+ static void Clear(TimelineEventRecorder* recorder) {
+ ASSERT(recorder != NULL);
+ recorder->Clear();
+ }
+
static void FinishBlock(TimelineEventBlock* block) { block->Finish(); }
};
@@ -453,6 +458,7 @@
EXPECT(!it.HasNext());
}
+ TimelineTestHelper::Clear(recorder);
delete recorder;
}
@@ -489,6 +495,7 @@
const char* beta = strstr(js.ToCString(), "Beta");
EXPECT(alpha < beta);
+ TimelineTestHelper::Clear(recorder);
delete recorder;
}
@@ -513,8 +520,8 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
EXPECT_EQ(10, pauses.MaxExclusiveTime("a"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
+
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
TimelineTestHelper::FakeDuration(recorder, "b", 0, 10);
@@ -532,9 +539,7 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(10, pauses.MaxExclusiveTime("b"));
}
-
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
@@ -553,8 +558,7 @@
EXPECT_EQ(7, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(7, pauses.MaxExclusiveTime("b"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
@@ -582,8 +586,7 @@
EXPECT_EQ(1, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(1, pauses.MaxExclusiveTime("b"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
@@ -613,8 +616,7 @@
EXPECT_EQ(5, pauses.MaxInclusiveTime("d"));
EXPECT_EQ(5, pauses.MaxExclusiveTime("d"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
@@ -649,8 +651,7 @@
EXPECT_EQ(2, pauses.MaxInclusiveTime("e"));
EXPECT_EQ(2, pauses.MaxExclusiveTime("e"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
@@ -666,6 +667,8 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
EXPECT_EQ(8, pauses.MaxExclusiveTime("a"));
}
+ TimelineTestHelper::Clear(recorder);
+
delete recorder;
}
@@ -692,8 +695,7 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
EXPECT_EQ(10, pauses.MaxExclusiveTime("a"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -715,8 +717,7 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(10, pauses.MaxExclusiveTime("b"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -738,8 +739,7 @@
EXPECT_EQ(7, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(7, pauses.MaxExclusiveTime("b"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -772,8 +772,7 @@
EXPECT_EQ(1, pauses.MaxInclusiveTime("b"));
EXPECT_EQ(1, pauses.MaxExclusiveTime("b"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -807,8 +806,7 @@
EXPECT_EQ(5, pauses.MaxInclusiveTime("d"));
EXPECT_EQ(5, pauses.MaxExclusiveTime("d"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -848,8 +846,7 @@
EXPECT_EQ(2, pauses.MaxInclusiveTime("e"));
EXPECT_EQ(2, pauses.MaxExclusiveTime("e"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -867,8 +864,7 @@
EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
EXPECT_EQ(8, pauses.MaxExclusiveTime("a"));
}
- delete recorder;
- recorder = new TimelineEventEndlessRecorder();
+ TimelineTestHelper::Clear(recorder);
// Test case.
TimelineTestHelper::FakeBegin(recorder, "a", 0);
@@ -882,6 +878,8 @@
pauses.CalculatePauseTimesForThread(tid);
EXPECT(pauses.has_error());
}
+ TimelineTestHelper::Clear(recorder);
+
delete recorder;
}
diff --git a/tools/VERSION b/tools/VERSION
index 5bfccf5..2c67925 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 159
+PRERELEASE 160
PRERELEASE_PATCH 0
\ No newline at end of file