Version 2.13.0-85.0.dev
Merge commit 'e74b2391ed16034b0901f56bcf412c8d6ae8ae70' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
index acc5edc..bea98e1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -131,11 +131,11 @@
return message.compareTo(message);
}
- FormattedMessage withFormatting(String formatted, int line, int column,
- Severity severity, List<FormattedMessage> relatedInformation,
+ FormattedMessage withFormatting(PlainAndColorizedString formatted, int line,
+ int column, Severity severity, List<FormattedMessage> relatedInformation,
{List<Uri>? involvedFiles}) {
- return new FormattedMessage(
- this, formatted, line, column, severity, relatedInformation,
+ return new FormattedMessage(this, formatted.plain, formatted.colorized,
+ line, column, severity, relatedInformation,
involvedFiles: involvedFiles);
}
@@ -162,10 +162,20 @@
'messageObject=$messageObject)';
}
+class PlainAndColorizedString {
+ final String plain;
+ final String colorized;
+
+ const PlainAndColorizedString(this.plain, this.colorized);
+ const PlainAndColorizedString.plainOnly(this.plain) : this.colorized = plain;
+}
+
class FormattedMessage implements DiagnosticMessage {
final LocatedMessage locatedMessage;
- final String formatted;
+ final String formattedPlain;
+
+ final String formattedColorized;
final int line;
@@ -178,8 +188,14 @@
final List<Uri>? involvedFiles;
- const FormattedMessage(this.locatedMessage, this.formatted, this.line,
- this.column, this.severity, this.relatedInformation,
+ const FormattedMessage(
+ this.locatedMessage,
+ this.formattedPlain,
+ this.formattedColorized,
+ this.line,
+ this.column,
+ this.severity,
+ this.relatedInformation,
{this.involvedFiles});
Code<dynamic> get code => locatedMessage.code;
@@ -200,18 +216,22 @@
@override
Iterable<String> get ansiFormatted sync* {
- yield formatted;
+ yield formattedColorized;
if (relatedInformation != null) {
for (FormattedMessage m in relatedInformation!) {
- yield m.formatted;
+ yield m.formattedColorized;
}
}
}
@override
- Iterable<String> get plainTextFormatted {
- // TODO(ahe): Implement this correctly.
- return ansiFormatted;
+ Iterable<String> get plainTextFormatted sync* {
+ yield formattedPlain;
+ if (relatedInformation != null) {
+ for (FormattedMessage m in relatedInformation!) {
+ yield m.formattedPlain;
+ }
+ }
}
Map<String, Object?> toJson() {
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index a9d5604..f129216 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -230,7 +230,7 @@
final VariableUseKind kind;
final ir.Member member;
final ir.LocalFunction localFunction;
- final ir.MethodInvocation invocation;
+ final ir.Expression invocation;
final ir.Instantiation instantiation;
const VariableUse._simple(this.kind)
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 7a06792..1fa89f1 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -934,6 +934,11 @@
}
@override
+ EvaluationComplexity visitStaticTearOff(ir.StaticTearOff node) {
+ return _evaluateImplicitConstant(node);
+ }
+
+ @override
EvaluationComplexity visitStaticSet(ir.StaticSet node) {
node.value = _handleExpression(node.value);
return const EvaluationComplexity.lazy();
@@ -1029,6 +1034,108 @@
if (receiverComplexity.combine(complexity).isConstant &&
interfaceTarget is ir.Procedure &&
interfaceTarget.kind == ir.ProcedureKind.Operator) {
+ // Only operator invocations can be part of constant expressions so we
+ // only try to compute an implicit constant when the receiver and all
+ // arguments are constant - and are used in an operator call.
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitInstanceInvocation(ir.InstanceInvocation node) {
+ node.receiver = _handleExpression(node.receiver);
+ EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
+ if (node.arguments.types.isNotEmpty) {
+ ir.TreeNode receiver = node.receiver;
+ assert(
+ !(receiver is ir.VariableGet &&
+ receiver.variable.parent is ir.LocalFunction),
+ "Unexpected local function invocation ${node} "
+ "(${node.runtimeType}).");
+ VariableUse usage = new VariableUse.instanceTypeArgument(node);
+ visitNodesInContext(node.arguments.types, usage);
+ }
+ EvaluationComplexity complexity = visitArguments(node.arguments);
+ ir.Member interfaceTarget = node.interfaceTarget;
+ if (receiverComplexity.combine(complexity).isConstant &&
+ interfaceTarget is ir.Procedure &&
+ interfaceTarget.kind == ir.ProcedureKind.Operator) {
+ // Only operator invocations can be part of constant expressions so we
+ // only try to compute an implicit constant when the receiver and all
+ // arguments are constant - and are used in an operator call.
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitDynamicInvocation(ir.DynamicInvocation node) {
+ node.receiver = _handleExpression(node.receiver);
+ if (node.arguments.types.isNotEmpty) {
+ ir.TreeNode receiver = node.receiver;
+ assert(
+ !(receiver is ir.VariableGet &&
+ receiver.variable.parent is ir.LocalFunction),
+ "Unexpected local function invocation ${node} "
+ "(${node.runtimeType}).");
+ VariableUse usage = new VariableUse.instanceTypeArgument(node);
+ visitNodesInContext(node.arguments.types, usage);
+ }
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitFunctionInvocation(ir.FunctionInvocation node) {
+ node.receiver = _handleExpression(node.receiver);
+ if (node.arguments.types.isNotEmpty) {
+ assert(
+ !(node.receiver is ir.VariableGet &&
+ ((node.receiver as ir.VariableGet).variable.parent
+ is ir.LocalFunction)),
+ "Unexpected local function invocation ${node} "
+ "(${node.runtimeType}).");
+ VariableUse usage = new VariableUse.instanceTypeArgument(node);
+ visitNodesInContext(node.arguments.types, usage);
+ }
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitLocalFunctionInvocation(
+ ir.LocalFunctionInvocation node) {
+ if (node.arguments.types.isNotEmpty) {
+ assert(
+ node.variable.parent is ir.LocalFunction,
+ "Unexpected variable in local function invocation ${node} "
+ "(${node.runtimeType}).");
+ VariableUse usage =
+ new VariableUse.localTypeArgument(node.variable.parent, node);
+ visitNodesInContext(node.arguments.types, usage);
+ }
+ visitArguments(node.arguments);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitEqualsNull(ir.EqualsNull node) {
+ node.expression = _handleExpression(node.expression);
+ EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
+ if (receiverComplexity.isConstant) {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitEqualsCall(ir.EqualsCall node) {
+ node.left = _handleExpression(node.left);
+ EvaluationComplexity leftComplexity = _lastExpressionComplexity;
+ node.right = _handleExpression(node.right);
+ EvaluationComplexity rightComplexity = _lastExpressionComplexity;
+ if (leftComplexity.combine(rightComplexity).isConstant) {
return _evaluateImplicitConstant(node);
}
return const EvaluationComplexity.lazy();
@@ -1045,6 +1152,38 @@
}
@override
+ EvaluationComplexity visitInstanceGet(ir.InstanceGet node) {
+ node.receiver = _handleExpression(node.receiver);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ if (complexity.isConstant && node.name.name == 'length') {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitInstanceTearOff(ir.InstanceTearOff node) {
+ node.receiver = _handleExpression(node.receiver);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitDynamicGet(ir.DynamicGet node) {
+ node.receiver = _handleExpression(node.receiver);
+ EvaluationComplexity complexity = _lastExpressionComplexity;
+ if (complexity.isConstant && node.name.name == 'length') {
+ return _evaluateImplicitConstant(node);
+ }
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitFunctionTearOff(ir.FunctionTearOff node) {
+ node.receiver = _handleExpression(node.receiver);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
EvaluationComplexity visitPropertySet(ir.PropertySet node) {
node.receiver = _handleExpression(node.receiver);
node.value = _handleExpression(node.value);
@@ -1052,6 +1191,20 @@
}
@override
+ EvaluationComplexity visitInstanceSet(ir.InstanceSet node) {
+ node.receiver = _handleExpression(node.receiver);
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
+ EvaluationComplexity visitDynamicSet(ir.DynamicSet node) {
+ node.receiver = _handleExpression(node.receiver);
+ node.value = _handleExpression(node.value);
+ return const EvaluationComplexity.lazy();
+ }
+
+ @override
EvaluationComplexity visitNot(ir.Not node) {
node.operand = _handleExpression(node.operand);
EvaluationComplexity complexity = _lastExpressionComplexity;
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index 52b27ac..6846687 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -112,18 +112,90 @@
}
@override
+ void visitInstanceGet(ir.InstanceGet node) {
+ registerNode(node);
+ super.visitInstanceGet(node);
+ }
+
+ @override
+ void visitInstanceTearOff(ir.InstanceTearOff node) {
+ registerNode(node);
+ super.visitInstanceTearOff(node);
+ }
+
+ @override
+ void visitDynamicGet(ir.DynamicGet node) {
+ registerNode(node);
+ super.visitDynamicGet(node);
+ }
+
+ @override
+ void visitFunctionTearOff(ir.FunctionTearOff node) {
+ registerNode(node);
+ super.visitFunctionTearOff(node);
+ }
+
+ @override
void visitPropertySet(ir.PropertySet node) {
registerNode(node);
super.visitPropertySet(node);
}
@override
+ void visitInstanceSet(ir.InstanceSet node) {
+ registerNode(node);
+ super.visitInstanceSet(node);
+ }
+
+ @override
+ void visitDynamicSet(ir.DynamicSet node) {
+ registerNode(node);
+ super.visitDynamicSet(node);
+ }
+
+ @override
void visitMethodInvocation(ir.MethodInvocation node) {
registerNode(node);
super.visitMethodInvocation(node);
}
@override
+ void visitInstanceInvocation(ir.InstanceInvocation node) {
+ registerNode(node);
+ super.visitInstanceInvocation(node);
+ }
+
+ @override
+ void visitDynamicInvocation(ir.DynamicInvocation node) {
+ registerNode(node);
+ super.visitDynamicInvocation(node);
+ }
+
+ @override
+ void visitFunctionInvocation(ir.FunctionInvocation node) {
+ registerNode(node);
+ super.visitFunctionInvocation(node);
+ }
+
+ @override
+ void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
+ registerNode(node);
+ super.visitLocalFunctionInvocation(node);
+ }
+
+ @override
+ void visitEqualsNull(ir.EqualsNull node) {
+ registerNode(node);
+ super.visitEqualsNull(node);
+ }
+
+ @override
+ void visitEqualsCall(ir.EqualsCall node) {
+ registerNode(node);
+ super.visitEqualsCall(node);
+ }
+
+ @override
void visitStaticInvocation(ir.StaticInvocation node) {
registerNode(node);
super.visitStaticInvocation(node);
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 5b4f99f..235fefb 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -7134,6 +7134,33 @@
}
@override
+ visitInstanceGet(ir.InstanceGet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ }
+
+ @override
+ visitInstanceTearOff(ir.InstanceTearOff node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ }
+
+ @override
+ visitDynamicGet(ir.DynamicGet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ }
+
+ @override
visitPropertySet(ir.PropertySet node) {
registerCall();
registerRegularNode();
@@ -7144,6 +7171,26 @@
}
@override
+ visitInstanceSet(ir.InstanceSet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ visit(node.value);
+ }
+
+ @override
+ visitDynamicSet(ir.DynamicSet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ visit(node.value);
+ }
+
+ @override
visitVariableGet(ir.VariableGet node) {
if (discountParameters && node.variable.parent is ir.FunctionNode) return;
registerRegularNode();
@@ -7201,6 +7248,63 @@
_processArguments(node.arguments, null);
}
+ @override
+ visitInstanceInvocation(ir.InstanceInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ visit(node.receiver);
+ skipReductiveNodes(() => visit(node.name));
+ _processArguments(node.arguments, null);
+ }
+
+ @override
+ visitDynamicInvocation(ir.DynamicInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ visit(node.receiver);
+ skipReductiveNodes(() => visit(node.name));
+ _processArguments(node.arguments, null);
+ }
+
+ @override
+ visitFunctionInvocation(ir.FunctionInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ visit(node.receiver);
+ skipReductiveNodes(() => visit(node.name));
+ _processArguments(node.arguments, null);
+ }
+
+ @override
+ visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ _processArguments(node.arguments, null);
+ // Account for the implicit access to the local variable:
+ registerRegularNode();
+ registerReductiveNode();
+ }
+
+ @override
+ visitEqualsNull(ir.EqualsNull node) {
+ registerRegularNode();
+ registerReductiveNode();
+ visit(node.expression);
+ }
+
+ @override
+ visitEqualsCall(ir.EqualsCall node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ visit(node.left);
+ visit(node.right);
+ }
+
_processArguments(ir.Arguments arguments, ir.FunctionNode target) {
registerRegularNode();
if (arguments.types.isNotEmpty) {
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 58af2ac..a4c69bd 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -9,7 +9,8 @@
import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
show DiagnosticMessage, DiagnosticMessageHandler;
-import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message, Code;
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
+ show Code, Message, PlainAndColorizedString;
import 'package:dev_compiler/dev_compiler.dart';
import 'package:dev_compiler/src/js_ast/js_ast.dart' as js_ast;
@@ -44,8 +45,8 @@
return Message(Code<String>('Expression Compiler Internal error'),
message: msg)
.withLocation(uri, 0, 0)
- .withFormatting(
- 'Internal error: $msg', line, col, Severity.internalProblem, []);
+ .withFormatting(PlainAndColorizedString.plainOnly('Internal error: $msg'),
+ line, col, Severity.internalProblem, []);
}
/// Dart scope
diff --git a/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart b/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
index ab69e10..124a899 100644
--- a/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
+++ b/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
@@ -4,110 +4,18 @@
library front_end.terminal_color_support;
-import 'dart:convert' show jsonEncode;
-
-import 'dart:io' show Platform, Process, ProcessResult, stderr, stdout;
-
import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
show DiagnosticMessage;
-import 'package:_fe_analyzer_shared/src/util/colors.dart'
- show ALL_CODES, TERMINAL_CAPABILITIES;
+import 'package:_fe_analyzer_shared/src/util/colors.dart' show enableColors;
-/// True if we should enable colors in output.
-///
-/// We enable colors only when both [stdout] and [stderr] support ANSI escapes.
-final bool enableTerminalColors = _computeEnableColors();
+export 'package:_fe_analyzer_shared/src/util/colors.dart' show enableColors;
void printDiagnosticMessage(
DiagnosticMessage message, void Function(String) println) {
- if (enableTerminalColors) {
+ if (enableColors) {
message.ansiFormatted.forEach(println);
} else {
message.plainTextFormatted.forEach(println);
}
}
-
-/// On Windows, colors are enabled if both stdout and stderr supports ANSI
-/// escapes. On other platforms, we rely on the external programs `tty` and
-/// `tput` to compute if ANSI colors are supported.
-bool _computeEnableColors() {
- const bool debug =
- const bool.fromEnvironment("front_end.debug_compute_enable_colors");
-
- if (Platform.isWindows) {
- if (!stdout.supportsAnsiEscapes || !stderr.supportsAnsiEscapes) {
- // In this case, either [stdout] or [stderr] did not support the property
- // `supportsAnsiEscapes`. Since we do not have another way to determine
- // support for colors, we disable them.
- if (debug) {
- print("Not enabling colors as ANSI is not supported.");
- }
- return false;
- }
- if (debug) {
- print("Enabling colors as OS is Windows.");
- }
- return true;
- }
-
- // We have to check if the terminal actually supports colors. Currently, to
- // avoid linking the Dart VM with ncurses, ANSI escape support is reduced to
- // `Platform.environment['TERM'].contains("xterm")`.
-
- // Check if stdin is a terminal (TTY).
- ProcessResult result =
- Process.runSync("/bin/sh", ["-c", "tty > /dev/null 2> /dev/null"]);
-
- if (result.exitCode != 0) {
- if (debug) {
- print("Not enabling colors, stdin isn't a terminal.");
- }
- return false;
- }
-
- // The `-S` option of `tput` allows us to query multiple capabilities at
- // once.
- result = Process.runSync(
- "/bin/sh", ["-c", "printf '%s' '$TERMINAL_CAPABILITIES' | tput -S"]);
-
- if (result.exitCode != 0) {
- if (debug) {
- print("Not enabling colors, running tput failed.");
- }
- return false;
- }
-
- List<String> lines = result.stdout.split("\n");
-
- if (lines.length != 2) {
- if (debug) {
- print("Not enabling colors, unexpected output from tput: "
- "${jsonEncode(result.stdout)}.");
- }
- return false;
- }
-
- String numberOfColors = lines[0];
- if ((int.tryParse(numberOfColors) ?? -1) < 8) {
- if (debug) {
- print("Not enabling colors, less than 8 colors supported: "
- "${jsonEncode(numberOfColors)}.");
- }
- return false;
- }
-
- String allCodes = lines[1].trim();
- if (ALL_CODES != allCodes) {
- if (debug) {
- print("Not enabling colors, color codes don't match: "
- "${jsonEncode(ALL_CODES)} != ${jsonEncode(allCodes)}.");
- }
- return false;
- }
-
- if (debug) {
- print("Enabling colors.");
- }
- return true;
-}
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 5aa7e6d..5fe07cd 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -36,7 +36,7 @@
export '../api_prototype/standard_file_system.dart' show StandardFileSystem;
export '../api_prototype/terminal_color_support.dart'
- show printDiagnosticMessage;
+ show printDiagnosticMessage, enableColors;
export '../base/nnbd_mode.dart' show NnbdMode;
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 94a7d0d..1ea8dc4 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -45,6 +45,7 @@
FormattedMessage,
LocatedMessage,
Message,
+ PlainAndColorizedString,
messageCantInferPackagesFromManyInputs,
messageCantInferPackagesFromPackageUri,
messageCompilingWithSoundNullSafety,
@@ -216,7 +217,7 @@
int offset = message.charOffset;
Uri uri = message.uri;
Location location = offset == -1 ? null : getLocation(uri, offset);
- String formatted =
+ PlainAndColorizedString formatted =
command_line_reporting.format(message, severity, location: location);
List<FormattedMessage> formattedContext;
if (context != null && context.isNotEmpty) {
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 4c89f92..ae2dc15 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -198,6 +198,8 @@
origin.procedure.isExternal = _procedure.isExternal;
origin.procedure.function = _procedure.function;
origin.procedure.function.parent = origin.procedure;
+ origin.procedure.isRedirectingFactoryConstructor =
+ _procedure.isRedirectingFactoryConstructor;
return 1;
}
}
@@ -712,6 +714,7 @@
bodyInternal = new RedirectingFactoryBody(target, typeArguments);
function.body = bodyInternal;
bodyInternal?.parent = function;
+ procedure.isRedirectingFactoryConstructor = true;
if (isPatch) {
if (function.typeParameters != null) {
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
diff --git a/pkg/front_end/lib/src/fasta/command_line_reporting.dart b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
index 2b05cc6..9ff9cf4 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
@@ -21,7 +21,7 @@
show $CARET, $SPACE, $TAB;
import 'package:_fe_analyzer_shared/src/util/colors.dart'
- show enableColors, green, magenta, red, yellow;
+ show green, magenta, red, yellow;
import 'package:_fe_analyzer_shared/src/util/relativize.dart'
show isWindows, relativizeUri;
@@ -34,7 +34,7 @@
import 'crash.dart' show Crash, safeToString;
-import 'fasta_codes.dart' show LocatedMessage;
+import 'fasta_codes.dart' show LocatedMessage, PlainAndColorizedString;
import 'messages.dart' show getLocation, getSourceLine;
@@ -42,10 +42,10 @@
const bool hideWarnings = false;
-/// Formats [message] as a string that is suitable for output from a
-/// command-line tool. This includes source snippets and different colors based
-/// on [severity].
-String format(LocatedMessage message, Severity severity,
+/// Formats [message] as two strings that is suitable for output from a
+/// command-line tool. This includes source snippets and - in the colorized
+/// version - different colors based on [severity].
+PlainAndColorizedString format(LocatedMessage message, Severity severity,
{Location location, Map<Uri, Source> uriToSource}) {
try {
int length = message.length;
@@ -55,34 +55,34 @@
length = 1;
}
String prefix = severityPrefixes[severity];
- String messageText =
+ String messageTextTmp =
prefix == null ? message.message : "$prefix: ${message.message}";
if (message.tip != null) {
- messageText += "\n${message.tip}";
+ messageTextTmp += "\n${message.tip}";
}
- if (enableColors) {
- switch (severity) {
- case Severity.error:
- case Severity.internalProblem:
- messageText = red(messageText);
- break;
+ final String messageTextPlain = messageTextTmp;
+ String messageTextColorized;
+ switch (severity) {
+ case Severity.error:
+ case Severity.internalProblem:
+ messageTextColorized = red(messageTextPlain);
+ break;
- case Severity.warning:
- messageText = magenta(messageText);
- break;
+ case Severity.warning:
+ messageTextColorized = magenta(messageTextPlain);
+ break;
- case Severity.context:
- messageText = green(messageText);
- break;
+ case Severity.context:
+ messageTextColorized = green(messageTextPlain);
+ break;
- case Severity.info:
- messageText = yellow(messageText);
- break;
+ case Severity.info:
+ messageTextColorized = yellow(messageTextPlain);
+ break;
- case Severity.ignored:
- default:
- return unhandled("$severity", "format", -1, null);
- }
+ case Severity.ignored:
+ default:
+ return unhandled("$severity", "format", -1, null);
}
if (message.uri != null) {
@@ -94,10 +94,17 @@
location = null;
}
String sourceLine = getSourceLine(location, uriToSource);
- return formatErrorMessage(
- sourceLine, location, length, path, messageText);
+ return new PlainAndColorizedString(
+ formatErrorMessage(
+ sourceLine, location, length, path, messageTextPlain),
+ formatErrorMessage(
+ sourceLine, location, length, path, messageTextColorized),
+ );
} else {
- return messageText;
+ return new PlainAndColorizedString(
+ messageTextPlain,
+ messageTextColorized,
+ );
}
} catch (error, trace) {
print("Crash when formatting: "
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index a1d2005..913a4e1 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -8,6 +8,7 @@
import 'dart:async' show Zone, runZoned;
+import 'package:_fe_analyzer_shared/src/messages/codes.dart';
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
@@ -79,16 +80,10 @@
}
/// Format [message] as a text string that can be included in generated code.
- String format(LocatedMessage message, Severity severity) {
+ PlainAndColorizedString format(LocatedMessage message, Severity severity) {
return command_line_reporting.format(message, severity);
}
- /// Format [message] as a text string that can be included in generated code.
- // TODO(askesc): Remove this and direct callers directly to format.
- String formatWithoutLocation(Message message, Severity severity) {
- return command_line_reporting.format(message.withoutLocation(), severity);
- }
-
// TODO(ahe): Remove this.
void logError(Object message, Severity severity) {
errors.add(message);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 15637c2..e5da386 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5981,7 +5981,8 @@
wasHandled: true, context: context);
}
String text = libraryBuilder.loader.target.context
- .format(message.withLocation(uri, charOffset, length), Severity.error);
+ .format(message.withLocation(uri, charOffset, length), Severity.error)
+ .plain;
InvalidExpression expression = new InvalidExpression(text)
..fileOffset = charOffset;
return expression;
@@ -6456,7 +6457,8 @@
addProblemErrorIfConst(message, charOffset, length,
wasHandled: wasHandled, context: context);
String text = libraryBuilder.loader.target.context
- .format(message.withLocation(uri, charOffset, length), Severity.error);
+ .format(message.withLocation(uri, charOffset, length), Severity.error)
+ .plain;
InvalidExpression expression = new InvalidExpression(text)
..fileOffset = charOffset;
return expression;
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 0d82df2..cdbabbe 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -6,22 +6,7 @@
library fasta.redirecting_factory_body;
-import 'package:kernel/ast.dart'
- show
- DartType,
- Expression,
- ExpressionStatement,
- Field,
- FunctionNode,
- InvalidExpression,
- Let,
- Member,
- NullLiteral,
- Procedure,
- StaticGet,
- StringLiteral,
- TypeParameterType,
- VariableDeclaration;
+import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart' show Substitution;
@@ -44,6 +29,10 @@
/// information in a factory method body.
const String letName = "#redirecting_factory";
+/// Name used for a synthesized let variable used to encode type arguments to
+/// the redirection target in a factory method body.
+const String varNamePrefix = "#typeArg";
+
class RedirectingFactoryBody extends ExpressionStatement {
RedirectingFactoryBody.internal(Expression value,
[List<DartType> typeArguments])
@@ -104,8 +93,38 @@
..parent = function;
}
+ static bool hasRedirectingFactoryBodyShape(Procedure factory) {
+ if (factory.function.body is! ExpressionStatement) return false;
+ Expression body = (factory.function.body as ExpressionStatement).expression;
+ if (body is Let &&
+ body.variable.name == letName &&
+ body.variable.type is DynamicType &&
+ body.variable.initializer is StaticGet) {
+ Expression currentArgument = body.body;
+ int argumentCount = 0;
+ while (currentArgument is! InvalidExpression) {
+ Expression argument = currentArgument;
+ if (argument is Let) {
+ String argumentName = "${varNamePrefix}${argumentCount}";
+ if (argument.variable.name != argumentName) {
+ return false;
+ }
+ if (argument.variable.initializer is! NullLiteral) {
+ return false;
+ }
+ currentArgument = argument.body;
+ ++argumentCount;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
static Expression encodeTypeArguments(List<DartType> typeArguments) {
- String varNamePrefix = "#typeArg";
Expression result = new InvalidExpression(null);
if (typeArguments == null) {
return result;
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 468697e..9a23516 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -29,7 +29,10 @@
import '../type_inference/type_schema.dart' show UnknownType;
import 'redirecting_factory_body.dart'
- show RedirectingFactoryBody, getRedirectingFactoryBody;
+ show
+ RedirectingFactoryBody,
+ getRedirectingFactoryBody,
+ isRedirectingFactory;
List<LocatedMessage> verifyComponent(Component component,
{bool isOutline, bool afterConst, bool skipPlatform: false}) {
@@ -220,7 +223,11 @@
@override
void visitLibrary(Library node) {
// Issue(http://dartbug.com/32530)
- if (skipPlatform && node.importUri.scheme == 'dart') {
+ // 'dart:test' is used in the unit tests and isn't an actual part of the
+ // platform.
+ if (skipPlatform &&
+ node.importUri.scheme == 'dart' &&
+ node.importUri.path != 'test') {
return;
}
@@ -260,6 +267,22 @@
void visitProcedure(Procedure node) {
enterTreeNode(node);
fileUri = checkLocation(node, node.name.text, node.fileUri);
+
+ // TODO(dmitryas): Investigate why some redirecting factory bodies retain
+ // the shape, but aren't of the RedirectingFactoryBody type.
+ bool hasBody = isRedirectingFactory(node) ||
+ RedirectingFactoryBody.hasRedirectingFactoryBodyShape(node);
+ bool hasFlag = node.isRedirectingFactoryConstructor;
+ if (hasBody != hasFlag) {
+ String hasBodyString = hasBody ? "has" : "doesn't have";
+ String hasFlagString = hasFlag ? "has" : "doesn't have";
+ problem(
+ node,
+ "Procedure '${node.name}' ${hasBodyString} a body "
+ "of a redirecting factory, but ${hasFlagString} the "
+ "'isRedirectingFactoryConstructor' bit set.");
+ }
+
super.visitProcedure(node);
exitTreeNode(node);
}
@@ -422,7 +445,11 @@
@override
visitLibrary(Library node) {
- if (skipPlatform && node.importUri.scheme == 'dart') {
+ // 'dart:test' is used in the unit tests and isn't an actual part of the
+ // platform.
+ if (skipPlatform &&
+ node.importUri.scheme == 'dart' &&
+ node.importUri.path != "test") {
return;
}
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index 3ebad1e..7aa716d 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -54,13 +54,11 @@
var component = new ir.Component();
new BinaryBuilder(new File.fromUri(componentUri).readAsBytesSync())
.readComponent(component);
- checkIsRedirectingFactory(component, 'collection', 'HashMap', 'identity',
- isPatch: true);
+ checkIsRedirectingFactory(component, 'collection', 'HashMap', 'identity');
}
void checkIsRedirectingFactory(ir.Component component, String uriPath,
- String className, String constructorName,
- {bool isPatch: false}) {
+ String className, String constructorName) {
var lib =
component.libraries.firstWhere((l) => l.importUri.path.endsWith(uriPath));
var cls = lib.classes.firstWhere((c) => c.name == className);
@@ -69,8 +67,7 @@
Expect.isTrue(
member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
Expect.isTrue(api.isRedirectingFactory(member));
- // TODO: this should always be true. Issue #33495
- Expect.equals(!isPatch, member.isRedirectingFactoryConstructor);
+ Expect.isTrue(member.isRedirectingFactoryConstructor);
}
const aSource = '''
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index 2728954..691adfa 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -14,6 +14,7 @@
front_end/lib/src/api_prototype/front_end/Exports: Fail
front_end/lib/src/api_prototype/incremental_kernel_generator/Exports: Fail
front_end/lib/src/api_prototype/language_version/Exports: Fail
+front_end/lib/src/api_prototype/terminal_color_support/Exports: Fail
front_end/lib/src/api_unstable/bazel_worker/ImportsTwice: Fail
front_end/lib/src/fasta/fasta_codes/Exports: Fail
front_end/lib/src/fasta/incremental_compiler/ImportsTwice: Fail
diff --git a/pkg/front_end/test/messages_json_test.dart b/pkg/front_end/test/messages_json_test.dart
index e8fe28a..7f87ca4 100644
--- a/pkg/front_end/test/messages_json_test.dart
+++ b/pkg/front_end/test/messages_json_test.dart
@@ -27,18 +27,34 @@
LocatedMessage locatedMessage1 =
new LocatedMessage(Uri.parse("what:ever/fun_1.dart"), 117, 2, message);
FormattedMessage formattedMessage2 = new FormattedMessage(
- null, "Formatted string #2", 13, 2, Severity.error, []);
+ null,
+ "Formatted string Plain #2",
+ "Formatted string Colorized #2",
+ 13,
+ 2,
+ Severity.error, []);
FormattedMessage formattedMessage3 = new FormattedMessage(
- null, "Formatted string #3", 313, 32, Severity.error, []);
+ null,
+ "Formatted string Plain #3",
+ "Formatted string Colorized #3",
+ 313,
+ 32,
+ Severity.error, []);
FormattedMessage formattedMessage1 = new FormattedMessage(
- locatedMessage1, "Formatted string", 42, 86, severity, [
+ locatedMessage1,
+ "Formatted string Plain",
+ "Formatted string Colorized",
+ 42,
+ 86,
+ severity, [
formattedMessage2,
formattedMessage3
- ], involvedFiles: [
- Uri.parse("what:ever/foo.dart"),
- Uri.parse("what:ever/bar.dart")
- ]);
+ ],
+ involvedFiles: [
+ Uri.parse("what:ever/foo.dart"),
+ Uri.parse("what:ever/bar.dart")
+ ]);
expect(formattedMessage1.codeName, "MyCodeName");
DiagnosticMessageFromJson diagnosticMessageFromJson =
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 60a1dd6..8fe1b6b 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -210,6 +210,7 @@
codec
codes
collision
+colorized
com
combinations
combinator
diff --git a/pkg/front_end/test/static_types/cfe_allowed.json b/pkg/front_end/test/static_types/cfe_allowed.json
index 63088f0..ca079c1 100644
--- a/pkg/front_end/test/static_types/cfe_allowed.json
+++ b/pkg/front_end/test/static_types/cfe_allowed.json
@@ -1,7 +1,4 @@
{
- "pkg/front_end/lib/src/api_prototype/terminal_color_support.dart": {
- "Dynamic invocation of 'split'.": 1
- },
"pkg/front_end/lib/src/base/libraries_specification.dart": {
"Dynamic invocation of 'toList'.": 1,
"Dynamic invocation of 'map'.": 1,
diff --git a/pkg/front_end/test/utils/validating_instrumentation.dart b/pkg/front_end/test/utils/validating_instrumentation.dart
index 184e7cb..1c1af83 100644
--- a/pkg/front_end/test/utils/validating_instrumentation.dart
+++ b/pkg/front_end/test/utils/validating_instrumentation.dart
@@ -228,11 +228,14 @@
String _formatProblem(
Uri uri, int offset, String desc, StackTrace stackTrace) {
- return CompilerContext.current.format(
- templateUnspecified
- .withArguments('$desc${stackTrace == null ? '' : '\n$stackTrace'}')
- .withLocation(uri, offset, noLength),
- Severity.internalProblem);
+ return CompilerContext.current
+ .format(
+ templateUnspecified
+ .withArguments(
+ '$desc${stackTrace == null ? '' : '\n$stackTrace'}')
+ .withLocation(uri, offset, noLength),
+ Severity.internalProblem)
+ .plain;
}
String _makeExpectationComment(String property, InstrumentationValue value) {
diff --git a/pkg/front_end/testcases/general/issue45101/libraries.json b/pkg/front_end/testcases/general/issue45101/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/libraries.json
@@ -0,0 +1,12 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ }
+ }
+ }
+}
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart b/pkg/front_end/testcases/general/issue45101/main.dart
new file mode 100644
index 0000000..171b59b
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart
@@ -0,0 +1,7 @@
+// 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:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline.expect
new file mode 100644
index 0000000..9ededd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+// @dart = 2.9
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9ededd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+// @dart = 2.9
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.weak.expect b/pkg/front_end/testcases/general/issue45101/main.dart.weak.expect
new file mode 100644
index 0000000..8c7b289
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.weak.expect
@@ -0,0 +1,60 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:_internal";
+
+class _ArraySize<T extends core::Object* = dynamic> extends core::Object implements self2::Array<self2::_ArraySize::T*> /*hasConstConstructor*/ { // from org-dartlang-testcase:///patch_lib.dart
+ final field core::int* foo;
+ const constructor •(core::int* foo) → self2::_ArraySize<self2::_ArraySize::T*>*
+ : self2::_ArraySize::foo = foo, super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+@#C1
+@#C4
+class Array<T extends core::Object* = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self2::Array::•];
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
+ let dynamic #redirecting_factory = self2::_ArraySize::• in let self2::Array::•::T* #typeArg0 = null in invalid-expression;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+constants {
+ #C1 = _in::_Patch {}
+ #C2 = "vm:entry-point"
+ #C3 = null
+ #C4 = core::pragma {name:#C2, options:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///origin_lib.dart:
+- pragma._ (from org-dartlang-sdk:///sdk/lib/core/annotations.dart:188:9)
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
new file mode 100644
index 0000000..c56c375
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
@@ -0,0 +1,56 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:_internal";
+
+class _ArraySize<T extends core::Object* = dynamic> extends core::Object implements self2::Array<self2::_ArraySize::T*> /*hasConstConstructor*/ { // from org-dartlang-testcase:///patch_lib.dart
+ final field core::int* foo;
+ const constructor •(core::int* foo) → self2::_ArraySize<self2::_ArraySize::T*>*
+ : self2::_ArraySize::foo = foo, super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+@_in::patch
+@core::pragma::_("vm:entry-point")
+class Array<T extends core::Object* = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self2::Array::•];
+ @_in::patch
+ external static factory •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
+ let dynamic #redirecting_factory = self2::_ArraySize::• in let self2::Array::•::T* #typeArg0 = null in invalid-expression;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:10:1 -> InstanceConstant(const _Patch{})
+Evaluated: ConstructorInvocation @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const pragma{pragma.name: "vm:entry-point", pragma.options: null})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 9, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue45101/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..8c7b289
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.weak.transformed.expect
@@ -0,0 +1,60 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:_internal";
+
+class _ArraySize<T extends core::Object* = dynamic> extends core::Object implements self2::Array<self2::_ArraySize::T*> /*hasConstConstructor*/ { // from org-dartlang-testcase:///patch_lib.dart
+ final field core::int* foo;
+ const constructor •(core::int* foo) → self2::_ArraySize<self2::_ArraySize::T*>*
+ : self2::_ArraySize::foo = foo, super core::Object::•()
+ ;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+@#C1
+@#C4
+class Array<T extends core::Object* = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self2::Array::•];
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
+ let dynamic #redirecting_factory = self2::_ArraySize::• in let self2::Array::•::T* #typeArg0 = null in invalid-expression;
+ abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+ abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+ abstract member-signature method toString() → core::String*; -> core::Object::toString
+ abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+
+constants {
+ #C1 = _in::_Patch {}
+ #C2 = "vm:entry-point"
+ #C3 = null
+ #C4 = core::pragma {name:#C2, options:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///origin_lib.dart:
+- pragma._ (from org-dartlang-sdk:///sdk/lib/core/annotations.dart:188:9)
diff --git a/pkg/front_end/testcases/general/issue45101/origin_lib.dart b/pkg/front_end/testcases/general/issue45101/origin_lib.dart
new file mode 100644
index 0000000..2aabe5a
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/origin_lib.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.
+// @dart=2.9
+
+class Array<T> {
+ external const factory Array(int foo);
+}
diff --git a/pkg/front_end/testcases/general/issue45101/patch_lib.dart b/pkg/front_end/testcases/general/issue45101/patch_lib.dart
new file mode 100644
index 0000000..b5a1fd5
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue45101/patch_lib.dart
@@ -0,0 +1,21 @@
+// 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
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+@pragma("vm:entry-point")
+class Array<T> {
+ // ...
+
+ @patch
+ const factory Array(int foo) = _ArraySize<T>;
+}
+
+class _ArraySize<T> implements Array<T> {
+ final int foo;
+
+ const _ArraySize(this.foo);
+}
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
index 910440d..fa7c510 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
@@ -24,4 +24,4 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
index 494a391..77d29d6 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
@@ -50,4 +50,4 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
index e502c15..5125b89 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
@@ -24,4 +24,4 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
index c9607e0..bd41225 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
@@ -50,4 +50,4 @@
Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:107:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/_internal/vm/lib/ffi_patch.dart:133:9)
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 754f7f2..e38ab78 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -24,6 +24,7 @@
import 'package:front_end/src/api_prototype/standard_file_system.dart'
show StandardFileSystem;
+import 'package:front_end/src/api_prototype/terminal_color_support.dart';
import 'package:front_end/src/base/nnbd_mode.dart';
import 'package:front_end/src/base/processed_options.dart'
@@ -39,9 +40,10 @@
import 'package:front_end/src/fasta/fasta_codes.dart'
show
Message,
- templateFastaCLIArgumentRequired,
+ PlainAndColorizedString,
messageFastaUsageLong,
messageFastaUsageShort,
+ templateFastaCLIArgumentRequired,
templateUnspecified;
import 'package:front_end/src/fasta/problems.dart' show DebugAbort;
@@ -440,10 +442,18 @@
problem = e;
}
- return CompilerContext.runWithOptions<T>(options, (c) {
+ return CompilerContext.runWithOptions<T>(options, (CompilerContext c) {
if (problem != null) {
print(computeUsage(programName, options.verbose).message);
- print(c.formatWithoutLocation(problem.message, Severity.error));
+ PlainAndColorizedString formatted =
+ c.format(problem.message.withoutLocation(), Severity.error);
+ String formattedText;
+ if (enableColors) {
+ formattedText = formatted.colorized;
+ } else {
+ formattedText = formatted.plain;
+ }
+ print(formattedText);
exit(1);
}
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 0fcaf18..4c46e9e 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -93,7 +93,8 @@
int nullSafety,
List<String> experimentalFlags,
Uri packagesUri,
- List<String> errors,
+ List<String> errorsPlain,
+ List<String> errorsColorized,
String invocationModes,
String verbosityLevel) {
final expFlags = <String>[];
@@ -113,8 +114,10 @@
..verbose = verbose
..omitPlatform = true
..explicitExperimentalFlags = parseExperimentalFlags(
- parseExperimentalArguments(expFlags),
- onError: (msg) => errors.add(msg))
+ parseExperimentalArguments(expFlags), onError: (msg) {
+ errorsPlain.add(msg);
+ errorsColorized.add(msg);
+ })
..environmentDefines = new EnvironmentMap()
..nnbdMode = (nullSafety == kNullSafetyOptionStrong)
? NnbdMode.Strong
@@ -128,7 +131,8 @@
// TODO(sigmund): support emitting code with errors as long as they
// are handled in the generated code.
printToStdErr = false; // errors are printed by VM
- errors.addAll(message.plainTextFormatted);
+ errorsPlain.addAll(message.plainTextFormatted);
+ errorsColorized.addAll(message.ansiFormatted);
break;
case Severity.warning:
printToStdErr = true;
@@ -168,7 +172,8 @@
final bool supportCodeCoverage;
final bool supportHotReload;
- final List<String> errors = <String>[];
+ final List<String> errorsPlain = <String>[];
+ final List<String> errorsColorized = <String>[];
CompilerOptions options;
@@ -202,7 +207,8 @@
nullSafety,
experimentalFlags,
packagesUri,
- errors,
+ errorsPlain,
+ errorsColorized,
invocationModes,
verbosityLevel);
}
@@ -212,7 +218,7 @@
final CompilerResult compilerResult = await compileInternal(script);
final Component component = compilerResult.component;
- if (errors.isEmpty) {
+ if (errorsPlain.isEmpty) {
// Record dependencies only if compilation was error free.
_recordDependencies(isolateGroupId, component, options.packagesFileUri);
}
@@ -333,7 +339,8 @@
if (generator == null) {
generator = new IncrementalCompiler(options, script);
}
- errors.clear();
+ errorsPlain.clear();
+ errorsColorized.clear();
final component = await generator.compile(entryPoint: script);
return new CompilerResult(component, const {},
generator.getClassHierarchy(), generator.getCoreTypes());
@@ -609,7 +616,8 @@
return;
}
- compiler.errors.clear();
+ compiler.errorsPlain.clear();
+ compiler.errorsColorized.clear();
CompilationResult result;
try {
@@ -622,10 +630,13 @@
return;
}
- if (compiler.errors.isNotEmpty) {
+ assert(compiler.errorsPlain.length == compiler.errorsColorized.length);
+ // Any error will be printed verbatim in observatory, so we always use the
+ // plain version (i.e. the one without ANSI escape codes in it).
+ if (compiler.errorsPlain.isNotEmpty) {
// TODO(sigmund): the compiler prints errors to the console, so we
// shouldn't print those messages again here.
- result = new CompilationResult.errors(compiler.errors, null);
+ result = new CompilationResult.errors(compiler.errorsPlain, null);
} else {
Component component = createExpressionEvaluationComponent(procedure);
result = new CompilationResult.ok(serializeComponent(component));
@@ -811,7 +822,8 @@
// resolve it against the working directory.
packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
}
- final List<String> errors = <String>[];
+ final List<String> errorsPlain = <String>[];
+ final List<String> errorsColorized = <String>[];
var options = setupCompilerOptions(
fileSystem,
platformKernelPath,
@@ -819,7 +831,8 @@
nullSafety,
experimentalFlags,
packagesUri,
- errors,
+ errorsPlain,
+ errorsColorized,
invocationModes,
verbosityLevel);
@@ -872,14 +885,22 @@
CompilerResult compilerResult = await compiler.compile(script);
Set<Library> loadedLibraries = compilerResult.loadedLibraries;
- if (compiler.errors.isNotEmpty) {
+ assert(compiler.errorsPlain.length == compiler.errorsColorized.length);
+ // http://dartbug.com/45137
+ // enableColors calls `stdout.supportsAnsiEscapes` which - on Windows -
+ // does something with line endings. To avoid this when no error
+ // messages are do be printed anyway, we are carefull not to call it unless
+ // neccessary.
+ if (compiler.errorsColorized.isNotEmpty) {
+ final List<String> errors =
+ (enableColors) ? compiler.errorsColorized : compiler.errorsPlain;
if (compilerResult.component != null) {
result = new CompilationResult.errors(
- compiler.errors,
+ errors,
serializeComponent(compilerResult.component,
filter: (lib) => !loadedLibraries.contains(lib)));
} else {
- result = new CompilationResult.errors(compiler.errors, null);
+ result = new CompilationResult.errors(errors, null);
}
} else {
// We serialize the component excluding vm_platform.dill because the VM has
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 1bb096e..e3708c8 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -229,7 +229,8 @@
bool has_field_initializers = false;
for (intptr_t i = 0; i < list_length; ++i) {
- if (PeekTag() == kRedirectingInitializer) {
+ if (PeekTag() == kRedirectingInitializer ||
+ PeekTag() == kRedirectingFactoryConstructor) {
is_redirecting_constructor = true;
} else if (PeekTag() == kFieldInitializer) {
has_field_initializers = true;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 06aeae2..1da5a95 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -433,15 +433,18 @@
}
const String& TranslationHelper::DartProcedureName(NameIndex procedure) {
- ASSERT(IsProcedure(procedure));
+ ASSERT(IsProcedure(procedure) || IsConstructor(procedure));
if (IsSetter(procedure)) {
return DartSetterName(procedure);
} else if (IsGetter(procedure)) {
return DartGetterName(procedure);
} else if (IsFactory(procedure)) {
return DartFactoryName(procedure);
- } else {
+ } else if (IsMethod(procedure)) {
return DartMethodName(procedure);
+ } else {
+ ASSERT(IsConstructor(procedure));
+ return DartConstructorName(procedure);
}
}
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index ed93ed2..38dbcda 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -122,6 +122,15 @@
throw RangeError.range(index, 0, _size);
}
}
+
+ @patch
+ const factory Array(int dimension1) = _ArraySize<T>;
+}
+
+class _ArraySize<T extends NativeType> implements Array<T> {
+ final int dimension1;
+
+ const _ArraySize(this.dimension1);
}
/// Returns an integer encoding the ABI used for size and alignment
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index e747811..8510065 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -97,14 +97,7 @@
/// ```
///
/// Do not invoke in normal code.
- const factory Array(int dimension1) = _ArraySize<T>;
-}
-
-// TODO(http://dartbug.com/45101): Move to ffi_patch.dart.
-class _ArraySize<T extends NativeType> implements Array<T> {
- final int dimension1;
-
- const _ArraySize(this.dimension1);
+ external const factory Array(int dimension1);
}
/// Extension on [Pointer] specialized for the type argument [NativeFunction].
diff --git a/tests/ffi/structs_test.dart b/tests/ffi/structs_test.dart
index 77026a4..18448c0 100644
--- a/tests/ffi/structs_test.dart
+++ b/tests/ffi/structs_test.dart
@@ -4,7 +4,7 @@
//
// Dart test program for testing dart:ffi struct pointers.
//
-// VMOptions=--deterministic --optimization-counter-threshold=50 --enable-inlining-annotations
+// VMOptions=--deterministic --optimization-counter-threshold=50
import 'dart:ffi';
diff --git a/tests/ffi_2/structs_test.dart b/tests/ffi_2/structs_test.dart
index 77026a4..18448c0 100644
--- a/tests/ffi_2/structs_test.dart
+++ b/tests/ffi_2/structs_test.dart
@@ -4,7 +4,7 @@
//
// Dart test program for testing dart:ffi struct pointers.
//
-// VMOptions=--deterministic --optimization-counter-threshold=50 --enable-inlining-annotations
+// VMOptions=--deterministic --optimization-counter-threshold=50
import 'dart:ffi';
diff --git a/tests/standalone/io/https_connection_closed_during_handshake_test.dart b/tests/standalone/io/https_connection_closed_during_handshake_test.dart
index 7918ee2..0d82100 100644
--- a/tests/standalone/io/https_connection_closed_during_handshake_test.dart
+++ b/tests/standalone/io/https_connection_closed_during_handshake_test.dart
@@ -50,8 +50,11 @@
asyncStart();
- final serverProcess = await Process.start(
- Platform.executable, [Platform.script.toFilePath(), 'server']);
+ final serverProcess = await Process.start(Platform.executable, [
+ ...Platform.executableArguments,
+ Platform.script.toFilePath(),
+ 'server'
+ ]);
final serverPortCompleter = Completer<int>();
serverProcess.stdout
diff --git a/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart b/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
index 789f529..0d82100 100644
--- a/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
+++ b/tests/standalone_2/io/https_connection_closed_during_handshake_test.dart
@@ -47,10 +47,14 @@
print('server: exiting');
exit(1);
}
+
asyncStart();
- final serverProcess = await Process.start(
- Platform.executable, [Platform.script.toFilePath(), 'server']);
+ final serverProcess = await Process.start(Platform.executable, [
+ ...Platform.executableArguments,
+ Platform.script.toFilePath(),
+ 'server'
+ ]);
final serverPortCompleter = Completer<int>();
serverProcess.stdout
diff --git a/tools/VERSION b/tools/VERSION
index f8cb69e..f2eb8a7 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 84
+PRERELEASE 85
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/gn.py b/tools/gn.py
index ce133c3..336b1df 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -575,13 +575,17 @@
def Main(argv):
starttime = time.time()
+
args = parse_args(argv)
+ if args is None:
+ return 1
result = RunGnOnConfiguredConfigurations(args)
- endtime = time.time()
if args.verbose:
+ endtime = time.time()
print("GN Time: %.3f seconds" % (endtime - starttime))
+
return result