Version 2.11.0-175.0.dev
Merge commit '5a087b90ce55c9d3da9bf1b63211fbd09a7bff7c' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
index cf17314..b5936f4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
@@ -17,7 +17,9 @@
/// Initialize a newly generated code template with the given [kind] and
/// [components].
- CodeTemplate(this.kind, this.components);
+ CodeTemplate(this.kind, this.components)
+ : assert(kind != null),
+ assert(components != null);
/// Use the [context] to validate that this template will be able to generate
/// a value.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
index 2007991..8394acd 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
@@ -20,6 +20,15 @@
/**
* Parameters:
+ * 0: the key with which the value is associated
+ * 1: the allowed values as a comma-separated list
+ */
+ static const TransformSetErrorCode invalidValueOneOf = TransformSetErrorCode(
+ 'invalid_value_one_of',
+ "The value of '{0}' must be one of the following: '{1}'.");
+
+ /**
+ * Parameters:
* 0: the missing key
*/
static const TransformSetErrorCode missingKey =
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index 96b3af0..d283e88 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -147,19 +147,21 @@
TransformSetErrorCode.missingTemplateEnd,
templateOffset + variableStart,
2);
- return null;
+ // Ignore the invalid component, treating it as if it extended to the
+ // end of the template.
+ return components;
} else {
var name = template.substring(variableStart + 2, endIndex).trim();
- var extractor = generators[name];
- if (extractor == null) {
+ var generator = generators[name];
+ if (generator == null) {
errorReporter.reportErrorForOffset(
TransformSetErrorCode.undefinedVariable,
templateOffset + template.indexOf(name, variableStart),
name.length,
[name]);
- return null;
+ // Ignore the invalid component.
} else {
- components.add(TemplateVariable(extractor));
+ components.add(TemplateVariable(generator));
}
}
textStart = endIndex + 2;
@@ -217,6 +219,15 @@
return null;
}
+ /// Report that the value represented by the [node] does not have the
+ /// [expectedType], using the [context] to get the key to use in the message.
+ Null _reportInvalidValueOneOf(
+ YamlNode node, ErrorContext context, List<String> allowedValues) {
+ _reportError(TransformSetErrorCode.invalidValueOneOf, node,
+ [context.key, allowedValues.join(', ')]);
+ return null;
+ }
+
/// Report that a required key is missing, using the [context] to locate the
/// node associated with the diagnostic and the key to use in the message.
Null _reportMissingKey(ErrorContext context) {
@@ -372,19 +383,25 @@
if (node is YamlMap) {
var kind = _translateString(node.valueAt(_kindKey),
ErrorContext(key: _kindKey, parentNode: node));
- if (kind == _addTypeParameterKind) {
- return _translateAddTypeParameterChange(node);
- } else if (kind == _renameKind) {
- return _translateRenameChange(node);
+ if (kind == null) {
+ return null;
} else if (kind == _addParameterKind) {
_translateAddParameterChange(node);
return null;
+ } else if (kind == _addTypeParameterKind) {
+ return _translateAddTypeParameterChange(node);
} else if (kind == _removeParameterKind) {
_translateRemoveParameterChange(node);
return null;
+ } else if (kind == _renameKind) {
+ return _translateRenameChange(node);
}
- // TODO(brianwilkerson) Report the invalid change kind.
- return null;
+ return _reportInvalidValueOneOf(node, context, [
+ _addParameterKind,
+ _addTypeParameterKind,
+ _removeParameterKind,
+ _renameKind,
+ ]);
} else {
return _reportInvalidValue(node, context, 'Map');
}
@@ -425,10 +442,11 @@
return null;
}
}
- var extractors = _translateTemplateVariables(node.valueAt(_variablesKey),
+ // TODO(brianwilkerson) We should report unreferenced variables.
+ var generators = _translateTemplateVariables(node.valueAt(_variablesKey),
ErrorContext(key: _variablesKey, parentNode: node));
var components =
- _extractTemplateComponents(template, extractors, templateOffset);
+ _extractTemplateComponents(template, generators, templateOffset);
return CodeTemplate(kind, components);
} else if (node == null) {
if (required) {
@@ -668,7 +686,7 @@
for (var entry in node.nodes.entries) {
var name = _translateKey(entry.key);
if (name != null) {
- var value = _translateValueExtractor(
+ var value = _translateValueGenerator(
entry.value, ErrorContext(key: name, parentNode: node));
if (value != null) {
generators[name] = value;
@@ -782,17 +800,21 @@
/// extractor, or `null` if the [node] does not represent a valid value
/// extractor. If the [node] is not valid, use the [context] to report the
/// error.
- ValueGenerator _translateValueExtractor(YamlNode node, ErrorContext context) {
+ ValueGenerator _translateValueGenerator(YamlNode node, ErrorContext context) {
if (node is YamlMap) {
var kind = _translateString(node.valueAt(_kindKey),
ErrorContext(key: _kindKey, parentNode: node));
- if (kind == _argumentKind) {
+ if (kind == null) {
+ return null;
+ } else if (kind == _argumentKind) {
return _translateArgumentExtractor(node);
} else if (kind == _importKind) {
return _translateImportValue(node);
}
- // TODO(brianwilkerson) Report the invalid extractor kind.
- return null;
+ return _reportInvalidValueOneOf(node, context, [
+ _argumentKind,
+ _importKind,
+ ]);
} else if (node == null) {
return _reportMissingKey(context);
} else {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
new file mode 100644
index 0000000..2e606bb
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(InvalidValueOneOfTest);
+ });
+}
+
+@reflectiveTest
+class InvalidValueOneOfTest extends AbstractTransformSetParserTest {
+ void test_changeKind() {
+ assertErrors('''
+version: 1
+transforms:
+- title: 'Rename A'
+ date: 2020-09-08
+ element:
+ uris: ['test.dart']
+ class: 'A'
+ changes:
+ - kind: 'invalid'
+''', [
+ error(TransformSetErrorCode.invalidValueOneOf, 129, 16),
+ ]);
+ }
+
+ void test_valueKind() {
+ assertErrors('''
+version: 1
+transforms:
+- title: 'Rename A'
+ date: 2020-09-08
+ element:
+ uris: ['test.dart']
+ class: 'A'
+ changes:
+ - kind: 'addTypeParameter'
+ index: 0
+ name: 'T'
+ argumentValue:
+ expression: ''
+ variables:
+ x:
+ kind: 'invalid'
+''', [
+ error(TransformSetErrorCode.invalidValueOneOf, 274, 16),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
index 76bb9b4..e8bbf94 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
@@ -4,6 +4,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'invalid_value_one_of_test.dart' as invalid_value_one_of;
import 'invalid_value_test.dart' as invalid_value;
import 'missing_key_test.dart' as missing_key;
import 'missing_template_end_test.dart' as missing_template_end;
@@ -13,6 +14,7 @@
void main() {
defineReflectiveSuite(() {
+ invalid_value_one_of.main();
invalid_value.main();
missing_key.main();
missing_template_end.main();
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 8a0a2ef..ae2ec2a 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -179,7 +179,9 @@
// The arg.contains('.') matches a file name pattern, i.e. some 'foo.dart'
if (arg.contains('.')) {
argsContainFile = true;
- } else if (arg == '--help' || arg == '-h' || arg == 'help') {
+ } else if (!argsContainFile &&
+ (arg == '--help' || arg == '-h' || arg == 'help')) {
+ // Only print usage if a help flag is provided before the script name.
printUsage();
return 0;
}
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index b7dc7ba..dcacb48 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 1.4.0
+- Added `done` property to `DartDevelopmentService`.
+- Throw `DartDeveloperServiceException` when shutdown occurs during startup.
+- Fixed issue where `StateError` was thrown when DDS was shutdown with pending
+ requests.
+
# 1.3.5
- Fixed issue where clients subscribing to the `Service` stream were not being
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart
index f35e4d3..0f716c6 100644
--- a/pkg/dds/lib/dds.dart
+++ b/pkg/dds/lib/dds.dart
@@ -118,6 +118,9 @@
/// authentication code to connect.
bool get authCodesEnabled;
+ /// Completes when this [DartDevelopmentService] has shut down.
+ Future<void> get done;
+
/// The HTTP [Uri] of the remote VM service instance that this service will
/// forward requests to.
Uri get remoteVmServiceUri;
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index a4c2f81..06327a8 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -16,21 +16,50 @@
}
Future<void> startService() async {
+ bool started = false;
+ final completer = Completer<void>();
// TODO(bkonyi): throw if we've already shutdown.
// Establish the connection to the VM service.
_vmServiceSocket = WebSocketChannel.connect(remoteVmServiceWsUri);
_vmServiceClient = _BinaryCompatiblePeer(_vmServiceSocket, _streamManager);
// Setup the JSON RPC client with the VM service.
- unawaited(_vmServiceClient.listen().then((_) => shutdown()));
+ unawaited(
+ _vmServiceClient.listen().then(
+ (_) {
+ shutdown();
+ if (!started && !completer.isCompleted) {
+ completer.completeError(
+ DartDevelopmentServiceException._(
+ 'Failed to start Dart Development Service',
+ ),
+ );
+ }
+ },
+ onError: (e, st) {
+ shutdown();
+ if (!completer.isCompleted) {
+ completer.completeError(e, st);
+ }
+ },
+ ),
+ );
+ try {
+ // Setup stream event handling.
+ await streamManager.listen();
- // Setup stream event handling.
- await streamManager.listen();
+ // Populate initial isolate state.
+ await _isolateManager.initialize();
- // Populate initial isolate state.
- await _isolateManager.initialize();
-
- // Once we have a connection to the VM service, we're ready to spawn the intermediary.
- await _startDDSServer();
+ // Once we have a connection to the VM service, we're ready to spawn the intermediary.
+ await _startDDSServer();
+ started = true;
+ completer.complete();
+ } on StateError {
+ /* Ignore json-rpc state errors */
+ } catch (e, st) {
+ completer.completeError(e, st);
+ }
+ return completer.future;
}
Future<void> _startDDSServer() async {
diff --git a/pkg/dds/lib/src/isolate_manager.dart b/pkg/dds/lib/src/isolate_manager.dart
index 50ace65..c94d4cd 100644
--- a/pkg/dds/lib/src/isolate_manager.dart
+++ b/pkg/dds/lib/src/isolate_manager.dart
@@ -160,6 +160,9 @@
/// Initializes the set of running isolates.
Future<void> initialize() async {
+ if (_initialized) {
+ return;
+ }
final vm = await dds._vmServiceClient.sendRequest('getVM');
final List<Map> isolateRefs = vm['isolates'].cast<Map<String, dynamic>>();
// Check the pause event for each isolate to determine whether or not the
@@ -179,6 +182,7 @@
isolateStarted(id, name);
}
}
+ _initialized = true;
}
/// Initializes state for a newly started isolate.
@@ -232,6 +236,7 @@
return resumeResult;
}
+ bool _initialized = false;
final _DartDevelopmentService dds;
final Map<String, _RunningIsolate> isolates = {};
}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 4fb4ebe..1874281 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,7 +3,7 @@
A library used to spawn the Dart Developer Service, used to communicate with
a Dart VM Service instance.
-version: 1.3.5
+version: 1.4.0
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
diff --git a/tools/VERSION b/tools/VERSION
index 275af0f..1fad799 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 174
+PRERELEASE 175
PRERELEASE_PATCH 0
\ No newline at end of file