Version 2.17.0-68.0.dev
Merge commit 'd1baf327a18dfc92476049a09985b645c08072f5' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 185cc30..acfcb38 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -37,29 +37,23 @@
return;
}
- var classOrMixin = request.target.containingNode
- .thisOrAncestorOfType<ClassOrMixinDeclaration>();
- if (classOrMixin != null) {
- var type = classOrMixin.declaredElement?.thisType;
- if (type != null) {
- _addExtensionMembers(extensions, defaultKind, type);
- }
+ var thisClassType = request.target.enclosingClassElement?.thisType;
+ if (thisClassType != null) {
+ _addExtensionMembers(extensions, defaultKind, thisClassType);
} else {
- var extension = request.target.containingNode
- .thisOrAncestorOfType<ExtensionDeclaration>();
- if (extension != null) {
- var extendedType = extension.extendedType.type;
- if (extendedType is InterfaceType) {
- var types = [extendedType, ...extendedType.allSupertypes];
- for (var type in types) {
- var inheritanceDistance = memberBuilder.request.featureComputer
- .inheritanceDistanceFeature(
- extendedType.element, type.element);
- _addTypeMembers(type, defaultKind, inheritanceDistance);
- }
- _addExtensionMembers(extensions, defaultKind, extendedType);
+ var thisExtendedType =
+ request.target.enclosingExtensionElement?.extendedType;
+ if (thisExtendedType is InterfaceType) {
+ var types = [thisExtendedType, ...thisExtendedType.allSupertypes];
+ for (var type in types) {
+ var inheritanceDistance = memberBuilder.request.featureComputer
+ .inheritanceDistanceFeature(
+ thisExtendedType.element, type.element);
+ _addTypeMembers(type, defaultKind, inheritanceDistance);
}
+ _addExtensionMembers(extensions, defaultKind, thisExtendedType);
}
+ // TODO(scheglov) It seems that we don't support non-interface types.
}
return;
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 9c20706..ce716df 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -117,6 +117,16 @@
/// otherwise this is `null`.
ParameterElement? _parameterElement;
+ /// The enclosing [ClassElement], or `null` if not in a class.
+ late final ClassElement? enclosingClassElement = containingNode
+ .thisOrAncestorOfType<ClassOrMixinDeclaration>()
+ ?.declaredElement;
+
+ /// The enclosing [ExtensionElement], or `null` if not in an extension.
+ late final ExtensionElement? enclosingExtensionElement = containingNode
+ .thisOrAncestorOfType<ExtensionDeclaration>()
+ ?.declaredElement;
+
/// Compute the appropriate [CompletionTarget] for the given [offset] within
/// the [entryPoint].
factory CompletionTarget.forOffset(AstNode entryPoint, int offset) {
diff --git a/pkg/dartdev/lib/src/commands/devtools.dart b/pkg/dartdev/lib/src/commands/devtools.dart
index 35d216c..63ff69c 100644
--- a/pkg/dartdev/lib/src/commands/devtools.dart
+++ b/pkg/dartdev/lib/src/commands/devtools.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:args/args.dart';
import 'package:dds/devtools_server.dart';
import 'package:dds/src/devtools/utils.dart';
import 'package:path/path.dart' as path;
@@ -10,162 +11,27 @@
import '../sdk.dart';
class DevToolsCommand extends DartdevCommand {
- static const commandDescription =
- 'Open DevTools (optionally connecting to an existing application).';
-
- static const protocolVersion = '1.1.0';
- static const argHelp = 'help';
- static const argVmUri = 'vm-uri';
- static const argEnableNotifications = 'enable-notifications';
- static const argAllowEmbedding = 'allow-embedding';
- static const argAppSizeBase = 'appSizeBase';
- static const argAppSizeTest = 'appSizeTest';
- static const argHeadlessMode = 'headless';
- static const argDebugMode = 'debug';
- static const argLaunchBrowser = 'launch-browser';
- static const argMachine = 'machine';
- static const argHost = 'host';
- static const argPort = 'port';
- static const argProfileMemory = 'record-memory-profile';
- static const argTryPorts = 'try-ports';
- static const argVerbose = 'verbose';
- static const argVersion = 'version';
- static const launchDevToolsService = 'launchDevTools';
-
DevToolsCommand({
this.customDevToolsPath,
bool verbose = false,
- }) : super(
+ }) : _argParser = DevToolsServer.buildArgParser(verbose: verbose),
+ super(
'devtools',
- commandDescription,
+ DevToolsServer.commandDescription,
verbose,
- ) {
- argParser
- ..addFlag(
- argVersion,
- negatable: false,
- help: 'Prints the DevTools version.',
- )
- ..addFlag(
- argVerbose,
- negatable: false,
- abbr: 'v',
- help: 'Output more informational messages.',
- )
- ..addOption(
- argHost,
- valueHelp: 'host',
- help: 'Hostname to serve DevTools on (defaults to localhost).',
- )
- ..addOption(
- argPort,
- defaultsTo: '9100',
- valueHelp: 'port',
- help: 'Port to serve DevTools on; specify 0 to automatically use any '
- 'available port.',
- )
- ..addFlag(
- argLaunchBrowser,
- help:
- 'Launches DevTools in a browser immediately at start.\n(defaults to on unless in --machine mode)',
- )
- ..addFlag(
- argMachine,
- negatable: false,
- help: 'Sets output format to JSON for consumption in tools.',
- )
- ..addSeparator('Memory profiling options:')
- ..addOption(
- argProfileMemory,
- valueHelp: 'file',
- defaultsTo: 'memory_samples.json',
- help:
- 'Start devtools headlessly and write memory profiling samples to the '
- 'indicated file.',
- );
-
- if (verbose) {
- argParser.addSeparator('App size options:');
- }
-
- // TODO(devoncarew): --appSizeBase and --appSizeTest should be renamed to
- // something like --app-size-base and --app-size-test; #3146.
- argParser
- ..addOption(
- argAppSizeBase,
- valueHelp: 'appSizeBase',
- help: 'Path to the base app size file used for app size debugging.',
- hide: !verbose,
- )
- ..addOption(
- argAppSizeTest,
- valueHelp: 'appSizeTest',
- help:
- 'Path to the test app size file used for app size debugging.\nThis '
- 'file should only be specified if --$argAppSizeBase is also specified.',
- hide: !verbose,
- );
-
- if (verbose) {
- argParser.addSeparator('Advanced options:');
- }
-
- // Args to show for verbose mode.
- argParser
- ..addOption(
- argTryPorts,
- defaultsTo: DevToolsServer.defaultTryPorts.toString(),
- valueHelp: 'count',
- help: 'The number of ascending ports to try binding to before failing '
- 'with an error. ',
- hide: !verbose,
- )
- ..addFlag(
- argEnableNotifications,
- negatable: false,
- help: 'Requests notification permissions immediately when a client '
- 'connects back to the server.',
- hide: !verbose,
- )
- ..addFlag(
- argAllowEmbedding,
- help: 'Allow embedding DevTools inside an iframe.',
- hide: !verbose,
- )
- ..addFlag(
- argHeadlessMode,
- negatable: false,
- help: 'Causes the server to spawn Chrome in headless mode for use in '
- 'automated testing.',
- hide: !verbose,
- );
-
- // Deprecated and hidden args.
- // TODO: Remove this - prefer that clients use the rest arg.
- argParser
- ..addOption(
- argVmUri,
- defaultsTo: '',
- help: 'VM Service protocol URI.',
- hide: true,
- )
-
- // Development only args.
- ..addFlag(
- argDebugMode,
- negatable: false,
- help: 'Run a debug build of the DevTools web frontend.',
- hide: true,
- );
- }
+ );
final String? customDevToolsPath;
@override
+ ArgParser get argParser => _argParser;
+ late final ArgParser _argParser;
+
+ @override
String get name => 'devtools';
@override
- String get description => commandDescription;
+ String get description => DevToolsServer.commandDescription;
@override
String get invocation => '${super.invocation} [service protocol uri]';
@@ -173,29 +39,33 @@
@override
Future<int> run() async {
final args = argResults!;
- final bool version = args[argVersion];
- final bool machineMode = args[argMachine];
+ final bool version = args[DevToolsServer.argVersion];
+ final bool machineMode = args[DevToolsServer.argMachine];
// launchBrowser defaults based on machine-mode if not explicitly supplied.
- final bool launchBrowser = args.wasParsed(argLaunchBrowser)
- ? args[argLaunchBrowser]
+ final bool launchBrowser = args.wasParsed(DevToolsServer.argLaunchBrowser)
+ ? args[DevToolsServer.argLaunchBrowser]
: !machineMode;
- final bool enableNotifications = args[argEnableNotifications];
- final bool allowEmbedding =
- args.wasParsed(argAllowEmbedding) ? args[argAllowEmbedding] : true;
+ final bool enableNotifications =
+ args[DevToolsServer.argEnableNotifications];
+ final bool allowEmbedding = args.wasParsed(DevToolsServer.argAllowEmbedding)
+ ? args[DevToolsServer.argAllowEmbedding]
+ : true;
- final port = args[argPort] != null ? int.tryParse(args[argPort]) ?? 0 : 0;
+ final port = args[DevToolsServer.argPort] != null
+ ? int.tryParse(args[DevToolsServer.argPort]) ?? 0
+ : 0;
- final bool headlessMode = args[argHeadlessMode];
- final bool debugMode = args[argDebugMode];
+ final bool headlessMode = args[DevToolsServer.argHeadlessMode];
+ final bool debugMode = args[DevToolsServer.argDebugMode];
- final numPortsToTry = args[argTryPorts] != null
- ? int.tryParse(args[argTryPorts]) ?? 0
+ final numPortsToTry = args[DevToolsServer.argTryPorts] != null
+ ? int.tryParse(args[DevToolsServer.argTryPorts]) ?? 0
: DevToolsServer.defaultTryPorts;
- final bool verboseMode = args[argVerbose];
- final String? hostname = args[argHost];
- final String? appSizeBase = args[argAppSizeBase];
- final String? appSizeTest = args[argAppSizeTest];
+ final bool verboseMode = args[DevToolsServer.argVerbose];
+ final String? hostname = args[DevToolsServer.argHost];
+ final String? appSizeBase = args[DevToolsServer.argAppSizeBase];
+ final String? appSizeTest = args[DevToolsServer.argAppSizeTest];
final sdkDir = path.dirname(sdk.dart);
final fullSdk = sdkDir.endsWith('bin');
@@ -219,14 +89,14 @@
String? serviceProtocolUri;
if (args.rest.isNotEmpty) {
serviceProtocolUri = args.rest.first;
- } else if (args.wasParsed(argVmUri)) {
- serviceProtocolUri = args[argVmUri];
+ } else if (args.wasParsed(DevToolsServer.argVmUri)) {
+ serviceProtocolUri = args[DevToolsServer.argVmUri];
}
// Support collecting profile data.
String? profileFilename;
- if (args.wasParsed(argProfileMemory)) {
- profileFilename = args[argProfileMemory];
+ if (args.wasParsed(DevToolsServer.argProfileMemory)) {
+ profileFilename = args[DevToolsServer.argProfileMemory];
}
if (profileFilename != null && !path.isAbsolute(profileFilename)) {
profileFilename = path.absolute(profileFilename);
diff --git a/pkg/dds/lib/devtools_server.dart b/pkg/dds/lib/devtools_server.dart
index ee451fa..1462458 100644
--- a/pkg/dds/lib/devtools_server.dart
+++ b/pkg/dds/lib/devtools_server.dart
@@ -5,8 +5,10 @@
import 'dart:async';
import 'dart:io';
+import 'package:args/args.dart';
import 'package:browser_launcher/browser_launcher.dart';
import 'package:http_multi_server/http_multi_server.dart';
+import 'package:path/path.dart' as path;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf;
@@ -20,11 +22,154 @@
class DevToolsServer {
static const protocolVersion = '1.1.0';
static const defaultTryPorts = 10;
+ static const commandDescription =
+ 'Open DevTools (optionally connecting to an existing application).';
+
+ static const argHelp = 'help';
+ static const argVmUri = 'vm-uri';
+ static const argEnableNotifications = 'enable-notifications';
+ static const argAllowEmbedding = 'allow-embedding';
+ static const argAppSizeBase = 'appSizeBase';
+ static const argAppSizeTest = 'appSizeTest';
+ static const argHeadlessMode = 'headless';
+ static const argDebugMode = 'debug';
+ static const argLaunchBrowser = 'launch-browser';
+ static const argMachine = 'machine';
+ static const argHost = 'host';
+ static const argPort = 'port';
+ static const argProfileMemory = 'record-memory-profile';
+ static const argTryPorts = 'try-ports';
+ static const argVerbose = 'verbose';
+ static const argVersion = 'version';
+ static const launchDevToolsService = 'launchDevTools';
MachineModeCommandHandler? _machineModeCommandHandler;
late ClientManager clientManager;
final bool _isChromeOS = File('/dev/.cros_milestone').existsSync();
+ static ArgParser buildArgParser({bool verbose = false}) {
+ final argParser = ArgParser();
+ argParser
+ ..addFlag(
+ argVersion,
+ negatable: false,
+ help: 'Prints the DevTools version.',
+ )
+ ..addFlag(
+ argVerbose,
+ negatable: false,
+ abbr: 'v',
+ help: 'Output more informational messages.',
+ )
+ ..addOption(
+ argHost,
+ valueHelp: 'host',
+ help: 'Hostname to serve DevTools on (defaults to localhost).',
+ )
+ ..addOption(
+ argPort,
+ defaultsTo: '9100',
+ valueHelp: 'port',
+ help: 'Port to serve DevTools on; specify 0 to automatically use any '
+ 'available port.',
+ )
+ ..addFlag(
+ argLaunchBrowser,
+ help:
+ 'Launches DevTools in a browser immediately at start.\n(defaults to on unless in --machine mode)',
+ )
+ ..addFlag(
+ argMachine,
+ negatable: false,
+ help: 'Sets output format to JSON for consumption in tools.',
+ )
+ ..addSeparator('Memory profiling options:')
+ ..addOption(
+ argProfileMemory,
+ valueHelp: 'file',
+ defaultsTo: 'memory_samples.json',
+ help:
+ 'Start devtools headlessly and write memory profiling samples to the '
+ 'indicated file.',
+ );
+
+ if (verbose) {
+ argParser.addSeparator('App size options:');
+ }
+
+ // TODO(devoncarew): --appSizeBase and --appSizeTest should be renamed to
+ // something like --app-size-base and --app-size-test; #3146.
+ argParser
+ ..addOption(
+ argAppSizeBase,
+ valueHelp: 'appSizeBase',
+ help: 'Path to the base app size file used for app size debugging.',
+ hide: !verbose,
+ )
+ ..addOption(
+ argAppSizeTest,
+ valueHelp: 'appSizeTest',
+ help:
+ 'Path to the test app size file used for app size debugging.\nThis '
+ 'file should only be specified if --$argAppSizeBase is also specified.',
+ hide: !verbose,
+ );
+
+ if (verbose) {
+ argParser.addSeparator('Advanced options:');
+ }
+
+ // Args to show for verbose mode.
+ argParser
+ ..addOption(
+ argTryPorts,
+ defaultsTo: DevToolsServer.defaultTryPorts.toString(),
+ valueHelp: 'count',
+ help: 'The number of ascending ports to try binding to before failing '
+ 'with an error. ',
+ hide: !verbose,
+ )
+ ..addFlag(
+ argEnableNotifications,
+ negatable: false,
+ help: 'Requests notification permissions immediately when a client '
+ 'connects back to the server.',
+ hide: !verbose,
+ )
+ ..addFlag(
+ argAllowEmbedding,
+ help: 'Allow embedding DevTools inside an iframe.',
+ hide: !verbose,
+ )
+ ..addFlag(
+ argHeadlessMode,
+ negatable: false,
+ help: 'Causes the server to spawn Chrome in headless mode for use in '
+ 'automated testing.',
+ hide: !verbose,
+ );
+
+ // Deprecated and hidden args.
+ // TODO: Remove this - prefer that clients use the rest arg.
+ argParser
+ ..addOption(
+ argVmUri,
+ defaultsTo: '',
+ help: 'VM Service protocol URI.',
+ hide: true,
+ )
+
+ // Development only args.
+ ..addFlag(
+ argDebugMode,
+ negatable: false,
+ help: 'Run a debug build of the DevTools web frontend.',
+ hide: true,
+ );
+
+ return argParser;
+ }
+
/// Serves DevTools.
///
/// `handler` is the [shelf.Handler] that the server will use for all requests.
@@ -199,6 +344,131 @@
return server;
}
+ void _printUsage(ArgParser argParser) {
+ print(commandDescription);
+ print('\nUsage: devtools [arguments] [service protocol uri]');
+ print(argParser.usage);
+ }
+
+ /// Wraps [serveDevTools] `arguments` parsed, as from the command line.
+ ///
+ /// For more information on `handler`, see [serveDevTools].
+ // Note: this method is used in google3 as well as by DevTools' main method.
+ Future<HttpServer?> serveDevToolsWithArgs(
+ List<String> arguments, {
+ shelf.Handler? handler,
+ String? customDevToolsPath,
+ }) async {
+ ArgResults args;
+ final verbose = arguments.contains('-v') || arguments.contains('--verbose');
+ final argParser = buildArgParser(verbose: verbose);
+ try {
+ args = argParser.parse(arguments);
+ } on FormatException catch (e) {
+ print(e.message);
+ print('');
+ _printUsage(argParser);
+ return null;
+ }
+
+ return await _serveDevToolsWithArgs(
+ args,
+ verbose,
+ handler: handler,
+ customDevToolsPath: customDevToolsPath,
+ );
+ }
+
+ Future<HttpServer?> _serveDevToolsWithArgs(
+ ArgResults args,
+ bool verbose, {
+ shelf.Handler? handler,
+ String? customDevToolsPath,
+ }) async {
+ final help = args[argHelp];
+ final bool version = args[argVersion];
+ final bool machineMode = args[argMachine];
+ // launchBrowser defaults based on machine-mode if not explicitly supplied.
+ final bool launchBrowser = args.wasParsed(argLaunchBrowser)
+ ? args[argLaunchBrowser]
+ : !machineMode;
+ final bool enableNotifications = args[argEnableNotifications];
+ final bool allowEmbedding =
+ args.wasParsed(argAllowEmbedding) ? args[argAllowEmbedding] : true;
+
+ final port = args[argPort] != null ? int.tryParse(args[argPort]) ?? 0 : 0;
+
+ final bool headlessMode = args[argHeadlessMode];
+ final bool debugMode = args[argDebugMode];
+
+ final numPortsToTry = args[argTryPorts] != null
+ ? int.tryParse(args[argTryPorts]) ?? 0
+ : defaultTryPorts;
+
+ final bool verboseMode = args[argVerbose];
+ final String? hostname = args[argHost];
+ final String? appSizeBase = args[argAppSizeBase];
+ final String? appSizeTest = args[argAppSizeTest];
+
+ if (help) {
+ print(
+ 'Dart DevTools version ${await DevToolsUtils.getVersion(customDevToolsPath ?? "")}');
+ print('');
+ _printUsage(buildArgParser(verbose: verbose));
+ return null;
+ }
+
+ if (version) {
+ final versionStr =
+ await DevToolsUtils.getVersion(customDevToolsPath ?? '');
+ DevToolsUtils.printOutput(
+ 'Dart DevTools version $versionStr',
+ {
+ 'version': versionStr,
+ },
+ machineMode: machineMode,
+ );
+ return null;
+ }
+
+ // Prefer getting the VM URI from the rest args; fall back on the 'vm-url'
+ // option otherwise.
+ String? serviceProtocolUri;
+ if (args.rest.isNotEmpty) {
+ serviceProtocolUri = args.rest.first;
+ } else if (args.wasParsed(argVmUri)) {
+ serviceProtocolUri = args[argVmUri];
+ }
+
+ // Support collecting profile data.
+ String? profileFilename;
+ if (args.wasParsed(argProfileMemory)) {
+ profileFilename = args[argProfileMemory];
+ }
+ if (profileFilename != null && !path.isAbsolute(profileFilename)) {
+ profileFilename = path.absolute(profileFilename);
+ }
+
+ return serveDevTools(
+ machineMode: machineMode,
+ debugMode: debugMode,
+ launchBrowser: launchBrowser,
+ enableNotifications: enableNotifications,
+ allowEmbedding: allowEmbedding,
+ port: port,
+ headlessMode: headlessMode,
+ numPortsToTry: numPortsToTry,
+ handler: handler,
+ customDevToolsPath: customDevToolsPath,
+ serviceProtocolUri: serviceProtocolUri,
+ profileFilename: profileFilename,
+ verboseMode: verboseMode,
+ hostname: hostname,
+ appSizeBase: appSizeBase,
+ appSizeTest: appSizeTest,
+ );
+ }
+
Future<Map<String, dynamic>> launchDevTools(
Map<String, dynamic> params,
Uri vmServiceUri,
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 22e251c..cb3837e 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -11,6 +11,7 @@
sdk: '>=2.13.0 <3.0.0'
dependencies:
+ args: ^2.0.0
async: ^2.4.1
browser_launcher: ^1.0.0
collection: ^1.15.0
@@ -32,7 +33,6 @@
web_socket_channel: ^2.0.0
dev_dependencies:
- args: ^2.0.0
http: ^0.13.0
test: ^1.0.0
webdriver: ^3.0.0
diff --git a/tools/VERSION b/tools/VERSION
index 3987f2f..3153f2c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 67
+PRERELEASE 68
PRERELEASE_PATCH 0
\ No newline at end of file