Version 2.13.0-72.0.dev
Merge commit 'f63f7736c5681d8a2c1c5bdccbc4feaf403fbdac' 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/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index e18d6aa..7f8587d 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -510,7 +510,10 @@
: super(provider, path);
@override
- bool get exists => provider._pathToResource[path] is _MemoryFolder;
+ bool get exists {
+ var canonicalPath = provider._resolveLinks(path);
+ return provider._pathToResource[canonicalPath] is _MemoryFolder;
+ }
@override
bool get isRoot {
@@ -580,15 +583,47 @@
@override
List<Resource> getChildren() {
+ var canonicalPath = provider._resolveLinks(path);
+ if (canonicalPath != path) {
+ var target = provider.getFolder(canonicalPath);
+ var canonicalChildren = target.getChildren();
+ return canonicalChildren.map((child) {
+ var childPath = provider.pathContext.join(path, child.shortName);
+ if (child is Folder) {
+ return _MemoryFolder(provider, childPath);
+ } else {
+ return _MemoryFile(provider, childPath);
+ }
+ }).toList();
+ }
+
if (!exists) {
throw FileSystemException(path, 'Folder does not exist.');
}
- List<Resource> children = <Resource>[];
+
+ var children = <Resource>[];
+
provider._pathToResource.forEach((resourcePath, resource) {
if (provider.pathContext.dirname(resourcePath) == path) {
children.add(resource);
}
});
+
+ provider._pathToLinkedPath.forEach((resourcePath, targetPath) {
+ if (provider.pathContext.dirname(resourcePath) == path) {
+ var target = provider.getResource(targetPath);
+ if (target is File) {
+ children.add(
+ _MemoryFile(provider, resourcePath),
+ );
+ } else if (target is Folder) {
+ children.add(
+ _MemoryFolder(provider, resourcePath),
+ );
+ }
+ }
+ });
+
return children;
}
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index dfe0af7..5936481 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -399,5 +399,8 @@
_OverlayResource._from(provider, _resource.resolveSymbolicLinksSync());
@override
+ String toString() => path;
+
+ @override
Uri toUri() => _resource.toUri();
}
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 8e3378d..b5e8a0a 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -56,12 +56,6 @@
///
/// [1]: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md.
class ContextBuilder {
- /// A callback for when analysis drivers are created, which takes all the same
- /// arguments as the dart analysis driver constructor so that plugins may
- /// create their own drivers with the same tools, in theory. Here as a stopgap
- /// until the official plugin API is complete
- static Function? onCreateAnalysisDriver;
-
/// The [ResourceProvider] by which paths are converted into [Resource]s.
final ResourceProvider resourceProvider;
@@ -160,11 +154,6 @@
),
);
- // temporary plugin support:
- if (onCreateAnalysisDriver != null) {
- onCreateAnalysisDriver!(driver, analysisDriverScheduler, performanceLog,
- resourceProvider, byteStore, fileContentOverlay, path, sf, options);
- }
declareVariablesInDriver(driver);
return driver;
}
diff --git a/pkg/analyzer/test/file_system/file_system_test_support.dart b/pkg/analyzer/test/file_system/file_system_test_support.dart
index 7947b4b..2323080 100644
--- a/pkg/analyzer/test/file_system/file_system_test_support.dart
+++ b/pkg/analyzer/test/file_system/file_system_test_support.dart
@@ -30,6 +30,10 @@
/// to work.
String /*!*/ get tempPath;
+ /// Create a link from [path] to [target].
+ /// The [target] does not have to exist, can be create later, or not at all.
+ void createLink({required String path, required String target});
+
/// Return a file accessed through the resource provider. If [exists] is
/// `true` then the returned file will exist, otherwise it won't. If [content]
/// is provided then the file will have the given content, otherwise it will
@@ -134,6 +138,33 @@
expect(file.exists, isTrue);
}
+ test_exists_links_existing() {
+ var a_path = join(tempPath, 'a.dart');
+ var b_path = join(tempPath, 'b.dart');
+
+ createLink(path: b_path, target: a_path);
+ getFile(exists: true, filePath: a_path);
+
+ var a = provider.getFile(a_path);
+ var b = provider.getFile(b_path);
+
+ expect(a.exists, isTrue);
+ expect(b.exists, isTrue);
+ }
+
+ test_exists_links_notExisting() {
+ var a_path = join(tempPath, 'a.dart');
+ var b_path = join(tempPath, 'b.dart');
+
+ createLink(path: b_path, target: a_path);
+
+ var a = provider.getFile(a_path);
+ var b = provider.getFile(b_path);
+
+ expect(a.exists, isFalse);
+ expect(b.exists, isFalse);
+ }
+
test_exists_notExisting() {
File file = getFile(exists: false);
@@ -458,6 +489,33 @@
expect(folder1 == folder2, isTrue);
}
+ test_exists_links_existing() {
+ var foo_path = join(tempPath, 'foo');
+ var bar_path = join(tempPath, 'bar');
+
+ createLink(path: bar_path, target: foo_path);
+ getFolder(exists: true, folderPath: foo_path);
+
+ var foo = provider.getFolder(foo_path);
+ var bar = provider.getFolder(bar_path);
+
+ expect(foo.exists, isTrue);
+ expect(bar.exists, isTrue);
+ }
+
+ test_exists_links_notExisting() {
+ var foo_path = join(tempPath, 'foo');
+ var bar_path = join(tempPath, 'bar');
+
+ createLink(path: bar_path, target: foo_path);
+
+ var foo = provider.getFolder(foo_path);
+ var bar = provider.getFolder(bar_path);
+
+ expect(foo.exists, isFalse);
+ expect(bar.exists, isFalse);
+ }
+
test_getChild_doesNotExist() {
Folder folder = getFolder(exists: true);
@@ -568,6 +626,68 @@
expect(children[2], isFile);
}
+ test_getChildren_hasLink_file() {
+ var a_path = join(tempPath, 'a.dart');
+ var b_path = join(tempPath, 'b.dart');
+
+ createLink(path: b_path, target: a_path);
+ var a = getFile(exists: true, filePath: a_path);
+
+ var children = provider.getFolder(tempPath).getChildren();
+ expect(children, hasLength(2));
+ expect(
+ children.map((e) => e.path),
+ unorderedEquals([a_path, b_path]),
+ );
+
+ var b = children.singleWhere((e) => e.path == b_path) as File;
+ expect(b.resolveSymbolicLinksSync(), a);
+ }
+
+ test_getChildren_hasLink_folder() {
+ var foo_path = join(tempPath, 'foo');
+ var bar_path = join(tempPath, 'bar');
+
+ var foo = getFolder(exists: true, folderPath: foo_path);
+ createLink(path: bar_path, target: foo_path);
+
+ var children = provider.getFolder(tempPath).getChildren();
+ expect(children, hasLength(2));
+ expect(
+ children.map((e) => e.path),
+ unorderedEquals([foo_path, bar_path]),
+ );
+
+ var b = children.singleWhere((e) => e.path == bar_path) as Folder;
+ expect(b.resolveSymbolicLinksSync(), foo);
+ }
+
+ test_getChildren_isLink() {
+ var foo_path = join(tempPath, 'foo');
+ var bar_path = join(tempPath, 'bar');
+ var foo_a_path = join(foo_path, 'a.dart');
+ var bar_a_path = join(bar_path, 'a.dart');
+ var foo_b_path = join(foo_path, 'b');
+ var bar_b_path = join(bar_path, 'b');
+
+ var foo_a = getFile(exists: true, filePath: foo_a_path);
+ var foo_b = getFolder(exists: true, folderPath: foo_b_path);
+ createLink(path: bar_path, target: foo_path);
+
+ var children = provider.getFolder(bar_path).getChildren();
+ expect(children, hasLength(2));
+ expect(
+ children.map((e) => e.path),
+ unorderedEquals([bar_a_path, bar_b_path]),
+ );
+
+ var bar_a = children.singleWhere((e) => e.path == bar_a_path) as File;
+ expect(bar_a.resolveSymbolicLinksSync(), foo_a);
+
+ var bar_b = children.singleWhere((e) => e.path == bar_b_path) as Folder;
+ expect(bar_b.resolveSymbolicLinksSync(), foo_b);
+ }
+
test_hashCode() {
Folder folder1 = getFolder(exists: false);
Folder folder2 = getFolder(exists: false);
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index 6c925f4..9dc70d1 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -52,6 +52,11 @@
@override
MemoryResourceProvider get provider => _provider ??= createProvider();
+ @override
+ void createLink({required String path, required String target}) {
+ provider.newLink(path, target);
+ }
+
/// Create the resource provider to be used by the tests. Subclasses can
/// override this method to change the class of resource provider that is
/// used.
@@ -252,14 +257,14 @@
@override
test_resolveSymbolicLinksSync_links_existing() {
- var a = provider.convertPath('/test/lib/a.dart');
- var b = provider.convertPath('/test/lib/b.dart');
+ var a_path = provider.convertPath('/test/lib/a.dart');
+ var b_path = provider.convertPath('/test/lib/b.dart');
- provider.newLink(b, a);
- provider.newFile(a, 'aaa');
+ provider.newLink(b_path, a_path);
+ provider.newFile(a_path, '');
- var resolved = provider.getFile(b).resolveSymbolicLinksSync();
- expect(resolved.path, a);
+ var resolved = provider.getFile(b_path).resolveSymbolicLinksSync();
+ expect(resolved.path, a_path);
}
@override
diff --git a/pkg/analyzer/test/file_system/physical_file_system_test.dart b/pkg/analyzer/test/file_system/physical_file_system_test.dart
index 63a4e5a..48a75fa 100644
--- a/pkg/analyzer/test/file_system/physical_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/physical_file_system_test.dart
@@ -52,6 +52,11 @@
@override
PhysicalResourceProvider get provider => _provider ??= createProvider();
+ @override
+ void createLink({required String path, required String target}) {
+ io.Link(path).createSync(target);
+ }
+
/// Create the resource provider to be used by the tests. Subclasses can
/// override this method to change the class of resource provider that is
/// used.
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 6ba066f..019fe7b 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -211,6 +211,10 @@
expect(library.id, id);
}
+ @SkippedTest(
+ issue: 'https://github.com/dart-lang/sdk/issues/44501',
+ reason: 'Actually, with fixed ResourceProvider, this test cycles',
+ )
test_getLibrary_exportViaRecursiveLink() async {
resourceProvider.newLink(
convertPath('/home/test/lib/foo'),
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index a837766..8215421 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,5 +1,7 @@
-## 0.4.1-dev
+## 0.5.0-dev
- Changed the support version range of the analyzer to `>=0.42.0 <0.43.0`.
+- Removed `Plugin.fileContentOverlay`, instead `Plugin.resourceProvider` is
+ now `OverlayResourceProvider`, and `analysis.updateContent` updates it.
## 0.4.0
- Deprecated the class `DartChangeBuilder` and enhanced `ChangeBuilder` to be
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index cdf8829..9fb108f 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -4,12 +4,12 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart'
show AnalysisDriver, AnalysisDriverGeneric, AnalysisDriverScheduler;
import 'package:analyzer/src/dart/analysis/file_byte_store.dart';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer_plugin/channel/channel.dart';
@@ -36,7 +36,10 @@
PluginCommunicationChannel _channel;
/// The resource provider used to access the file system.
- final ResourceProvider resourceProvider;
+ final OverlayResourceProvider resourceProvider;
+
+ /// The next modification stamp for a changed file in the [resourceProvider].
+ int _overlayModificationStamp = 0;
/// The object used to manage analysis subscriptions.
final SubscriptionManager subscriptionManager = SubscriptionManager();
@@ -60,14 +63,12 @@
/// The SDK manager used to manage SDKs.
DartSdkManager _sdkManager;
- /// The file content overlay used by any analysis drivers that are created.
- final FileContentOverlay fileContentOverlay = FileContentOverlay();
-
/// Initialize a newly created analysis server plugin. If a resource [provider]
/// is given, then it will be used to access the file system. Otherwise a
/// resource provider that accesses the physical file system will be used.
ServerPlugin(ResourceProvider provider)
- : resourceProvider = provider ?? PhysicalResourceProvider.INSTANCE {
+ : resourceProvider = OverlayResourceProvider(
+ provider ?? PhysicalResourceProvider.INSTANCE) {
analysisDriverScheduler = AnalysisDriverScheduler(performanceLog);
analysisDriverScheduler.start();
}
@@ -275,11 +276,20 @@
AnalysisUpdateContentParams parameters) async {
Map<String, Object> files = parameters.files;
files.forEach((String filePath, Object overlay) {
+ // Prepare the old overlay contents.
+ String oldContents;
+ try {
+ if (resourceProvider.hasOverlay(filePath)) {
+ var file = resourceProvider.getFile(filePath);
+ oldContents = file.readAsStringSync();
+ }
+ } catch (_) {}
+
+ // Prepare the new contents.
+ String newContents;
if (overlay is AddContentOverlay) {
- fileContentOverlay[filePath] = overlay.content;
+ newContents = overlay.content;
} else if (overlay is ChangeContentOverlay) {
- var oldContents = fileContentOverlay[filePath];
- String newContents;
if (oldContents == null) {
// The server should only send a ChangeContentOverlay if there is
// already an existing overlay for the source.
@@ -292,10 +302,20 @@
throw RequestFailure(
RequestErrorFactory.invalidOverlayChangeInvalidEdit());
}
- fileContentOverlay[filePath] = newContents;
} else if (overlay is RemoveContentOverlay) {
- fileContentOverlay[filePath] = null;
+ newContents = null;
}
+
+ if (newContents != null) {
+ resourceProvider.setOverlay(
+ filePath,
+ content: newContents,
+ modificationStamp: _overlayModificationStamp++,
+ );
+ } else {
+ resourceProvider.removeOverlay(filePath);
+ }
+
contentChanged(filePath);
});
return AnalysisUpdateContentResult();
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 07562d9..2a91465 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
name: analyzer_plugin
description: A framework and support code for building plugins for the analysis server.
-version: 0.4.1-dev
+version: 0.5.0-dev
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 8037da0..780642b 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -8,6 +8,9 @@
/// convenience methods.
abstract class AbstractDataSource extends DataSourceMixin
implements DataSource {
+ static final List<ir.DartType> emptyListOfDartTypes =
+ List<ir.DartType>.filled(0, null, growable: false);
+
final bool useDataKinds;
EntityReader _entityReader = const EntityReader();
ComponentLookup _componentLookup;
@@ -143,6 +146,7 @@
List<ir.DartType> _readDartTypeNodes(
List<ir.TypeParameter> functionTypeVariables) {
int count = readInt();
+ if (count == 0) return emptyListOfDartTypes;
List<ir.DartType> types = new List<ir.DartType>.filled(count, null);
for (int index = 0; index < count; index++) {
types[index] = _readDartTypeNode(functionTypeVariables);
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 1b23da1..a3dcde5 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/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 edcd72b..e9cd910 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5976,7 +5976,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;
@@ -6451,7 +6452,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/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 626be69..e262498 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/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..e740e1a 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,17 @@
CompilerResult compilerResult = await compiler.compile(script);
Set<Library> loadedLibraries = compilerResult.loadedLibraries;
- if (compiler.errors.isNotEmpty) {
+ assert(compiler.errorsPlain.length == compiler.errorsColorized.length);
+ final List<String> errors =
+ enableColors ? compiler.errorsColorized : compiler.errorsPlain;
+ if (errors.isNotEmpty) {
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/tests/lib/lib.status b/tests/lib/lib.status
index 3d14826..ab707d3 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -37,6 +37,9 @@
html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/properties_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/method_call_on_object_test: SkipByDesign # Issue 42085.
js/mock_test/*: SkipByDesign # Issue 42085.
js/parameters_test: SkipByDesign # Issue 42085.
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index a5af78e..f338b66 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -37,6 +37,9 @@
html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/properties_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/method_call_on_object_test: SkipByDesign # Issue 42085.
js/mock_test/*: SkipByDesign # Issue 42085.
js/parameters_test: SkipByDesign # Issue 42085.
diff --git a/tools/VERSION b/tools/VERSION
index c50233a..ca15bdb 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 71
+PRERELEASE 72
PRERELEASE_PATCH 0
\ No newline at end of file