Upgrade language version of dartdev to 3.11
Changes are reformatting and using the nullable list element operator. Change-Id: Iea1f4d2fcb06056f14804c8fe8b33c0b4d9037f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/477561 Commit-Queue: Sigurd Meldgaard <sigurdm@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
committed by
Commit Queue
parent
b2c4c10bba
commit
65c4d768f1
@@ -57,9 +57,11 @@ Future<void> runDartdev(List<String> args, SendPort? port) async {
|
||||
} catch (e, st) {
|
||||
// Unexpected error encountered.
|
||||
io.stderr.writeln('An unexpected error was encountered by the Dart CLI.');
|
||||
io.stderr.writeln('Please file an issue at '
|
||||
'https://github.com/dart-lang/sdk/issues/new with the following '
|
||||
'details:\n');
|
||||
io.stderr.writeln(
|
||||
'Please file an issue at '
|
||||
'https://github.com/dart-lang/sdk/issues/new with the following '
|
||||
'details:\n',
|
||||
);
|
||||
io.stderr.writeln("Invocation: 'dart ${args.join(' ')}'");
|
||||
io.stderr.writeln("Exception: '$e'");
|
||||
io.stderr.writeln('Stack Trace:');
|
||||
@@ -89,56 +91,72 @@ class DartdevRunner extends CommandRunner<int> {
|
||||
Analytics? analyticsOverride,
|
||||
bool isAnalyticsTest = false,
|
||||
List<String> vmArgs = const [],
|
||||
}) : verbose = args.contains('-v') || args.contains('--verbose'),
|
||||
argParser = globalDartdevOptionsParser(
|
||||
verbose: args.contains('-v') || args.contains('--verbose')),
|
||||
vmEnabledExperiments = parseVmEnabledExperiments(vmArgs),
|
||||
_unifiedAnalytics = analyticsOverride,
|
||||
_isAnalyticsTest = isAnalyticsTest,
|
||||
super('dart', '$dartdevDescription.') {
|
||||
}) : verbose = args.contains('-v') || args.contains('--verbose'),
|
||||
argParser = globalDartdevOptionsParser(
|
||||
verbose: args.contains('-v') || args.contains('--verbose'),
|
||||
),
|
||||
vmEnabledExperiments = parseVmEnabledExperiments(vmArgs),
|
||||
_unifiedAnalytics = analyticsOverride,
|
||||
_isAnalyticsTest = isAnalyticsTest,
|
||||
super('dart', '$dartdevDescription.') {
|
||||
// The list of commands should be kept in sync with
|
||||
// `DartDevIsolate::ShouldParseCommand` in `runtime/bin/dartdev_isolate.cc`.
|
||||
addCommand(AnalyzeCommand(verbose: verbose));
|
||||
addCommand(CompilationServerCommand(verbose: verbose));
|
||||
final nativeAssetsExperimentEnabled =
|
||||
nativeAssetsEnabled(vmEnabledExperiments);
|
||||
final nativeAssetsExperimentEnabled = nativeAssetsEnabled(
|
||||
vmEnabledExperiments,
|
||||
);
|
||||
final dataAssetsExperimentEnabled = dataAssetsEnabled(vmEnabledExperiments);
|
||||
if (nativeAssetsExperimentEnabled) {
|
||||
final recordUseExperimentEnabled = recordUseEnabled(vmEnabledExperiments);
|
||||
addCommand(BuildCommand(
|
||||
addCommand(
|
||||
BuildCommand(
|
||||
verbose: verbose,
|
||||
recordUseEnabled: recordUseExperimentEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled));
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
}
|
||||
addCommand(CompileCommand(
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
));
|
||||
addCommand(
|
||||
CompileCommand(
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
addCommand(CreateCommand(verbose: verbose));
|
||||
addCommand(DebugAdapterCommand(verbose: verbose));
|
||||
addCommand(DevelopmentServiceCommand(verbose: verbose));
|
||||
addCommand(DevToolsCommand(verbose: verbose));
|
||||
addCommand(DocCommand(verbose: verbose));
|
||||
addCommand(FixCommand(verbose: verbose));
|
||||
addCommand(FormatCommand(
|
||||
verbose: verbose,
|
||||
category: CommandCategory.sourceCode.name,
|
||||
));
|
||||
addCommand(
|
||||
FormatCommand(
|
||||
verbose: verbose,
|
||||
category: CommandCategory.sourceCode.name,
|
||||
),
|
||||
);
|
||||
addCommand(InfoCommand(verbose: verbose));
|
||||
addCommand(LanguageServerCommand(verbose: verbose));
|
||||
addCommand(DartMCPServerCommand(verbose: verbose));
|
||||
addCommand(pubCommand(
|
||||
isVerbose: () => verbose,
|
||||
category: CommandCategory.project.name,
|
||||
));
|
||||
addCommand(RunCommand(
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
));
|
||||
addCommand(TestCommand(
|
||||
addCommand(
|
||||
pubCommand(
|
||||
isVerbose: () => verbose,
|
||||
category: CommandCategory.project.name,
|
||||
),
|
||||
);
|
||||
addCommand(
|
||||
RunCommand(
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled));
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
addCommand(
|
||||
TestCommand(
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
addCommand(ToolingDaemonCommand(verbose: verbose));
|
||||
if (nativeAssetsExperimentEnabled) {
|
||||
addCommand(InstallCommand(verbose: verbose));
|
||||
@@ -165,14 +183,16 @@ class DartdevRunner extends CommandRunner<int> {
|
||||
// We don't want to run analytics when we're running in a CI environment
|
||||
// unless we're explicitly testing analytics for dartdev.
|
||||
final implicitlySuppressAnalytics = isBot() && !_isAnalyticsTest;
|
||||
bool suppressAnalytics = !topLevelResults.flag('analytics') ||
|
||||
bool suppressAnalytics =
|
||||
!topLevelResults.flag('analytics') ||
|
||||
topLevelResults.flag('suppress-analytics') ||
|
||||
implicitlySuppressAnalytics;
|
||||
|
||||
if (topLevelResults.wasParsed('analytics')) {
|
||||
io.stderr.writeln(
|
||||
'`--[no-]analytics` is deprecated. Use `--suppress-analytics` '
|
||||
'to disable analytics for one run instead.');
|
||||
'`--[no-]analytics` is deprecated. Use `--suppress-analytics` '
|
||||
'to disable analytics for one run instead.',
|
||||
);
|
||||
}
|
||||
final enableAnalytics = topLevelResults.flag('enable-analytics');
|
||||
final disableAnalytics = topLevelResults.flag('disable-analytics');
|
||||
@@ -182,8 +202,10 @@ class DartdevRunner extends CommandRunner<int> {
|
||||
(enableAnalytics || disableAnalytics)) {
|
||||
// This isn't an error if we're implicitly disabling analytics because
|
||||
// we're running in a CI environment.
|
||||
io.stderr.writeln('`--suppress-analytics` cannot be used with either'
|
||||
' `--enable-analytics` or `--disable-analytics`.');
|
||||
io.stderr.writeln(
|
||||
'`--suppress-analytics` cannot be used with either'
|
||||
' `--enable-analytics` or `--disable-analytics`.',
|
||||
);
|
||||
return 254;
|
||||
}
|
||||
// The Analytics instance used to report information back to Google Analytics;
|
||||
@@ -231,7 +253,8 @@ class DartdevRunner extends CommandRunner<int> {
|
||||
// If we make it this far, it means the VM couldn't find the file on disk.
|
||||
if (firstArg.endsWith('.dart')) {
|
||||
io.stderr.writeln(
|
||||
"Error when reading '$firstArg': No such file or directory.");
|
||||
"Error when reading '$firstArg': No such file or directory.",
|
||||
);
|
||||
// This is the exit code used by the frontend.
|
||||
return 254;
|
||||
}
|
||||
@@ -241,8 +264,9 @@ class DartdevRunner extends CommandRunner<int> {
|
||||
log = Logger.verbose(ansi: ansi);
|
||||
}
|
||||
|
||||
late final List<String> experimentErrors =
|
||||
validateExperiments(vmEnabledExperiments);
|
||||
late final List<String> experimentErrors = validateExperiments(
|
||||
vmEnabledExperiments,
|
||||
);
|
||||
if (experimentErrors.isNotEmpty) {
|
||||
experimentErrors.forEach(io.stderr.writeln);
|
||||
return 254;
|
||||
|
||||
@@ -22,8 +22,12 @@ import 'sdk.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
/// When set, this function is executed just before the Analysis Server starts.
|
||||
void Function(String cmdName, List<FileSystemEntity> analysisRoots,
|
||||
ArgResults? argResults)? preAnalysisServerStart;
|
||||
void Function(
|
||||
String cmdName,
|
||||
List<FileSystemEntity> analysisRoots,
|
||||
ArgResults? argResults,
|
||||
)?
|
||||
preAnalysisServerStart;
|
||||
|
||||
/// A class to provide an API wrapper around an analysis server process.
|
||||
class AnalysisServer {
|
||||
@@ -39,8 +43,8 @@ class AnalysisServer {
|
||||
this.disableStatusNotificationDebouncing = false,
|
||||
this.suppressAnalytics = false,
|
||||
bool useAotSnapshot = false,
|
||||
}) : _useAotSnapshot = useAotSnapshot,
|
||||
_usePlugins = usePlugins;
|
||||
}) : _useAotSnapshot = useAotSnapshot,
|
||||
_usePlugins = usePlugins;
|
||||
|
||||
final String? cacheDirectoryPath;
|
||||
final File? packagesFile;
|
||||
@@ -72,8 +76,7 @@ class AnalysisServer {
|
||||
|
||||
Stream<bool> get onAnalyzing {
|
||||
// {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
|
||||
return _streamController('server.status')
|
||||
.stream
|
||||
return _streamController('server.status').stream
|
||||
.where((event) => event['analysis'] != null)
|
||||
.map((event) => (event['analysis']['isAnalyzing']!) as bool);
|
||||
}
|
||||
@@ -91,7 +94,7 @@ class AnalysisServer {
|
||||
final errorsList = event['errors'] as List<dynamic>;
|
||||
final errors = [
|
||||
for (final error in errorsList)
|
||||
AnalysisError((error as Map).cast<String, dynamic>())
|
||||
AnalysisError((error as Map).cast<String, dynamic>()),
|
||||
];
|
||||
return FileAnalysisErrors(file, errors);
|
||||
});
|
||||
@@ -156,9 +159,12 @@ class AnalysisServer {
|
||||
|
||||
_streamController('server.pluginError').stream.listen(_handlePluginError);
|
||||
|
||||
_sendCommand('server.setSubscriptions', params: <String, dynamic>{
|
||||
'subscriptions': <String>['STATUS'],
|
||||
});
|
||||
_sendCommand(
|
||||
'server.setSubscriptions',
|
||||
params: <String, dynamic>{
|
||||
'subscriptions': <String>['STATUS'],
|
||||
},
|
||||
);
|
||||
|
||||
// Reference and trim off any trailing slash, the Dart Analysis Server
|
||||
// protocol throws an error (INVALID_FILE_PATH_FORMAT) if there is a
|
||||
@@ -169,7 +175,9 @@ class AnalysisServer {
|
||||
final analysisRootPaths = [
|
||||
for (final root in analysisRoots)
|
||||
trimEnd(
|
||||
root.absolute.resolveSymbolicLinksSync(), path.context.separator),
|
||||
root.absolute.resolveSymbolicLinksSync(),
|
||||
path.context.separator,
|
||||
),
|
||||
];
|
||||
|
||||
onAnalyzing.listen((isAnalyzing) {
|
||||
@@ -186,10 +194,10 @@ class AnalysisServer {
|
||||
});
|
||||
|
||||
if (setAnalysisRoots) {
|
||||
await _sendCommand('analysis.setAnalysisRoots', params: {
|
||||
'included': analysisRootPaths,
|
||||
'excluded': [],
|
||||
});
|
||||
await _sendCommand(
|
||||
'analysis.setAnalysisRoots',
|
||||
params: {'included': analysisRootPaths, 'excluded': []},
|
||||
);
|
||||
}
|
||||
|
||||
return process.pid;
|
||||
@@ -215,7 +223,7 @@ class AnalysisServer {
|
||||
if (packagesFile != null) '--packages=${packagesFile!.path}',
|
||||
if (enabledExperiments.isNotEmpty)
|
||||
'--$experimentFlagName=${enabledExperiments.join(',')}',
|
||||
if (!_usePlugins) '--no-plugins'
|
||||
if (!_usePlugins) '--no-plugins',
|
||||
];
|
||||
|
||||
log.trace('$executable ${arguments.join(' ')}');
|
||||
@@ -223,48 +231,67 @@ class AnalysisServer {
|
||||
}
|
||||
|
||||
Future<String> getVersion() {
|
||||
return _sendCommand('server.getVersion')
|
||||
.then((response) => response['version']);
|
||||
return _sendCommand(
|
||||
'server.getVersion',
|
||||
).then((response) => response['version']);
|
||||
}
|
||||
|
||||
Future<EditBulkFixesResult> requestBulkFixes(
|
||||
String filePath, bool inTestMode, List<String> codes,
|
||||
{bool updatePubspec = false}) {
|
||||
return _sendCommand('edit.bulkFixes', params: <String, dynamic>{
|
||||
'included': [path.canonicalize(filePath)],
|
||||
'inTestMode': inTestMode,
|
||||
'updatePubspec': updatePubspec,
|
||||
if (codes.isNotEmpty) 'codes': codes,
|
||||
}).then((result) {
|
||||
String filePath,
|
||||
bool inTestMode,
|
||||
List<String> codes, {
|
||||
bool updatePubspec = false,
|
||||
}) {
|
||||
return _sendCommand(
|
||||
'edit.bulkFixes',
|
||||
params: <String, dynamic>{
|
||||
'included': [path.canonicalize(filePath)],
|
||||
'inTestMode': inTestMode,
|
||||
'updatePubspec': updatePubspec,
|
||||
if (codes.isNotEmpty) 'codes': codes,
|
||||
},
|
||||
).then((result) {
|
||||
return EditBulkFixesResult.fromJson(
|
||||
ResponseDecoder(null), 'result', result);
|
||||
ResponseDecoder(null),
|
||||
'result',
|
||||
result,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> shutdown({Duration? timeout}) async {
|
||||
// Request shutdown.
|
||||
final Future<void> future =
|
||||
_sendCommand('server.shutdown').then((Map<String, dynamic> value) {
|
||||
final Future<void> future = _sendCommand('server.shutdown').then((
|
||||
Map<String, dynamic> value,
|
||||
) {
|
||||
_shutdownResponseReceived = true;
|
||||
return;
|
||||
});
|
||||
await (timeout != null
|
||||
? future.timeout(timeout, onTimeout: () {
|
||||
log.stderr(
|
||||
'The analysis server timed out while shutting down.');
|
||||
})
|
||||
? future.timeout(
|
||||
timeout,
|
||||
onTimeout: () {
|
||||
log.stderr(
|
||||
'The analysis server timed out while shutting down.',
|
||||
);
|
||||
},
|
||||
)
|
||||
: future)
|
||||
.whenComplete(dispose);
|
||||
}
|
||||
|
||||
/// Send an `analysis.updateContent` request with the given [files].
|
||||
Future<void> updateContent(Map<String, AddContentOverlay> files) async {
|
||||
await _sendCommand('analysis.updateContent',
|
||||
params: AnalysisUpdateContentParams(files).toJson());
|
||||
await _sendCommand(
|
||||
'analysis.updateContent',
|
||||
params: AnalysisUpdateContentParams(files).toJson(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _sendCommand(String method,
|
||||
{Map<String, dynamic>? params}) {
|
||||
Future<Map<String, dynamic>> _sendCommand(
|
||||
String method, {
|
||||
Map<String, dynamic>? params,
|
||||
}) {
|
||||
final String id = (++_id).toString();
|
||||
final String message = json.encode(<String, dynamic>{
|
||||
'id': id,
|
||||
@@ -300,15 +327,20 @@ class AnalysisServer {
|
||||
final response = json.decode(line) as Object?;
|
||||
|
||||
if (response is Map<String, dynamic>) {
|
||||
if (response
|
||||
case {'event': final String event, 'params': final Object? params}) {
|
||||
if (response case {
|
||||
'event': final String event,
|
||||
'params': final Object? params,
|
||||
}) {
|
||||
if (params is Map<String, dynamic>) {
|
||||
_streamController(event).add(params.cast<String, dynamic>());
|
||||
}
|
||||
} else if (response case {'id': final String id}) {
|
||||
if (response case {'error': final Map<String, Object?> error}) {
|
||||
_requestCompleters.remove(id)?.completeError(
|
||||
RequestError.parse(error.cast<String, dynamic>()));
|
||||
_requestCompleters
|
||||
.remove(id)
|
||||
?.completeError(
|
||||
RequestError.parse(error.cast<String, dynamic>()),
|
||||
);
|
||||
} else {
|
||||
_requestCompleters.remove(id)?.complete(response['result'] ?? {});
|
||||
}
|
||||
@@ -320,9 +352,11 @@ class AnalysisServer {
|
||||
_serverErrorReceived = true;
|
||||
final err = error!;
|
||||
log.stderr('An unexpected error was encountered by the Analysis Server.');
|
||||
log.stderr('Please file an issue at '
|
||||
'https://github.com/dart-lang/sdk/issues/new/choose with the following '
|
||||
'details:\n');
|
||||
log.stderr(
|
||||
'Please file an issue at '
|
||||
'https://github.com/dart-lang/sdk/issues/new/choose with the following '
|
||||
'details:\n',
|
||||
);
|
||||
// Fields are 'isFatal', 'message', and 'stackTrace'.
|
||||
log.stderr(err['message']);
|
||||
final stackTrace = err['stackTrace'];
|
||||
@@ -333,7 +367,9 @@ class AnalysisServer {
|
||||
|
||||
StreamController<Map<String, dynamic>> _streamController(String streamId) {
|
||||
return _streamControllers.putIfAbsent(
|
||||
streamId, () => StreamController<Map<String, dynamic>>.broadcast());
|
||||
streamId,
|
||||
() => StreamController<Map<String, dynamic>>.broadcast(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> dispose() async {
|
||||
@@ -341,22 +377,17 @@ class AnalysisServer {
|
||||
}
|
||||
}
|
||||
|
||||
enum _AnalysisSeverity {
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
none,
|
||||
}
|
||||
enum _AnalysisSeverity { error, warning, info, none }
|
||||
|
||||
class AnalysisError implements Comparable<AnalysisError> {
|
||||
AnalysisError(this.json);
|
||||
|
||||
static final Map<String, _AnalysisSeverity> _severityMap =
|
||||
<String, _AnalysisSeverity>{
|
||||
'INFO': _AnalysisSeverity.info,
|
||||
'WARNING': _AnalysisSeverity.warning,
|
||||
'ERROR': _AnalysisSeverity.error,
|
||||
};
|
||||
'INFO': _AnalysisSeverity.info,
|
||||
'WARNING': _AnalysisSeverity.warning,
|
||||
'ERROR': _AnalysisSeverity.error,
|
||||
};
|
||||
|
||||
// "severity":"INFO","type":"TODO","location":{
|
||||
// "file":"/Users/.../lib/test.dart","offset":362,"length":72,"startLine":15,"startColumn":4
|
||||
@@ -427,7 +458,8 @@ class AnalysisError implements Comparable<AnalysisError> {
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '${severity!.toLowerCase()} • '
|
||||
String toString() =>
|
||||
'${severity!.toLowerCase()} • '
|
||||
'$message • $file:$startLine:$startColumn • '
|
||||
'($code)';
|
||||
}
|
||||
|
||||
@@ -39,13 +39,18 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
static final int _return = '\r'.codeUnitAt(0);
|
||||
|
||||
AnalyzeCommand({bool verbose = false})
|
||||
: super(cmdName, 'Analyze Dart code in a directory.', verbose) {
|
||||
: super(cmdName, 'Analyze Dart code in a directory.', verbose) {
|
||||
argParser
|
||||
..addFlag('fatal-infos',
|
||||
help: 'Treat info level issues as fatal.', negatable: false)
|
||||
..addFlag('fatal-warnings',
|
||||
help: 'Treat warning level issues as fatal.', defaultsTo: true)
|
||||
|
||||
..addFlag(
|
||||
'fatal-infos',
|
||||
help: 'Treat info level issues as fatal.',
|
||||
negatable: false,
|
||||
)
|
||||
..addFlag(
|
||||
'fatal-warnings',
|
||||
help: 'Treat warning level issues as fatal.',
|
||||
defaultsTo: true,
|
||||
)
|
||||
// Options hidden by default.
|
||||
..addOption(
|
||||
'cache',
|
||||
@@ -55,7 +60,8 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
)
|
||||
..addFlag(
|
||||
'memory',
|
||||
help: 'Attempt to print memory usage before exiting. '
|
||||
help:
|
||||
'Attempt to print memory usage before exiting. '
|
||||
'Will only print if format is json.',
|
||||
hide: !verbose,
|
||||
)
|
||||
@@ -67,10 +73,11 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
allowedHelp: {
|
||||
'default':
|
||||
'The default output format. This format is intended to be user '
|
||||
'consumable.\nThe format is not specified and can change '
|
||||
'between releases.',
|
||||
'consumable.\nThe format is not specified and can change '
|
||||
'between releases.',
|
||||
'json': 'A machine readable output in a JSON format.',
|
||||
'machine': 'A machine readable output. The format is:\n\n'
|
||||
'machine':
|
||||
'A machine readable output. The format is:\n\n'
|
||||
'SEVERITY|TYPE|ERROR_CODE|FILE_PATH|LINE|COLUMN|LENGTH|ERROR_MESSAGE\n\n'
|
||||
'Note that the pipe character is escaped with backslashes for '
|
||||
'the file path and error message fields.',
|
||||
@@ -80,7 +87,8 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
..addOption(
|
||||
'packages',
|
||||
valueHelp: 'path',
|
||||
help: 'The path to the package resolution configuration file, which '
|
||||
help:
|
||||
'The path to the package resolution configuration file, which '
|
||||
'supplies a mapping of package names\ninto paths.',
|
||||
hide: !verbose,
|
||||
)
|
||||
@@ -96,8 +104,12 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
defaultsTo: true,
|
||||
hide: true,
|
||||
)
|
||||
..addFlag('plugins',
|
||||
help: 'Use analyzer plugins', defaultsTo: true, hide: true)
|
||||
..addFlag(
|
||||
'plugins',
|
||||
help: 'Use analyzer plugins',
|
||||
defaultsTo: true,
|
||||
hide: true,
|
||||
)
|
||||
..addExperimentalFlags();
|
||||
}
|
||||
|
||||
@@ -157,8 +169,10 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
snapshotName,
|
||||
);
|
||||
if (!io.File(snapshotPath).existsSync()) {
|
||||
usageException("Invalid Dart SDK path has no '$snapshotName' file: "
|
||||
'${sdkPath.path}');
|
||||
usageException(
|
||||
"Invalid Dart SDK path has no '$snapshotName' file: "
|
||||
'${sdkPath.path}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
sdkPath = io.Directory(sdk.sdkPath);
|
||||
@@ -169,18 +183,21 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
if (experiment.startsWith('no-'))
|
||||
experiment.substring(3)
|
||||
else
|
||||
experiment
|
||||
experiment,
|
||||
};
|
||||
final unknownExperiments =
|
||||
experimentNames.difference(ExperimentStatus.knownFeatures.keys.toSet());
|
||||
final unknownExperiments = experimentNames.difference(
|
||||
ExperimentStatus.knownFeatures.keys.toSet(),
|
||||
);
|
||||
if (unknownExperiments.isNotEmpty) {
|
||||
final unknownExperimentsText =
|
||||
unknownExperiments.map((e) => "'$e'").join(', ');
|
||||
final unknownExperimentsText = unknownExperiments
|
||||
.map((e) => "'$e'")
|
||||
.join(', ');
|
||||
usageException('Unknown experiment(s): $unknownExperimentsText');
|
||||
}
|
||||
|
||||
final targetsNames =
|
||||
targets.map((entity) => path.basename(entity.path)).join(', ');
|
||||
final targetsNames = targets
|
||||
.map((entity) => path.basename(entity.path))
|
||||
.join(', ');
|
||||
final progress = machineFormat || jsonFormat
|
||||
? null
|
||||
: log.progress('Analyzing $targetsNames');
|
||||
@@ -200,13 +217,17 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
);
|
||||
|
||||
server.onErrors.listen((FileAnalysisErrors fileErrors) {
|
||||
var isPriorityFile = const {'analysis_options.yaml', 'pubspec.yaml'}
|
||||
.contains(path.basename(fileErrors.file));
|
||||
var isPriorityFile = const {
|
||||
'analysis_options.yaml',
|
||||
'pubspec.yaml',
|
||||
}.contains(path.basename(fileErrors.file));
|
||||
|
||||
// Record the issues found (but filter out to do comments unless they've
|
||||
// been upgraded from INFO).
|
||||
for (var error in fileErrors.errors.where((AnalysisError error) =>
|
||||
error.type != 'TODO' || error.severity != 'INFO')) {
|
||||
for (var error in fileErrors.errors.where(
|
||||
(AnalysisError error) =>
|
||||
error.type != 'TODO' || error.severity != 'INFO',
|
||||
)) {
|
||||
if (isPriorityFile && error.severity == 'ERROR') {
|
||||
priorityErrors.add(error);
|
||||
} else {
|
||||
@@ -238,8 +259,8 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
|
||||
UsageInfo? usageInfo;
|
||||
if (printMemory) {
|
||||
usageInfo =
|
||||
await ProcessProfiler.getProfilerForPlatform()?.getProcessUsage(pid);
|
||||
usageInfo = await ProcessProfiler.getProfilerForPlatform()
|
||||
?.getProcessUsage(pid);
|
||||
}
|
||||
|
||||
await server.shutdown();
|
||||
@@ -281,9 +302,11 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
|
||||
if (priorityErrors.isNotEmpty) {
|
||||
log.stdout('');
|
||||
log.stdout("Errors were found in 'pubspec.yaml' and/or "
|
||||
"'analysis_options.yaml' which might result in either invalid "
|
||||
'diagnostics being produced or valid diagnostics being missed.');
|
||||
log.stdout(
|
||||
"Errors were found in 'pubspec.yaml' and/or "
|
||||
"'analysis_options.yaml' which might result in either invalid "
|
||||
'diagnostics being produced or valid diagnostics being missed.',
|
||||
);
|
||||
|
||||
emit(priorityErrors);
|
||||
if (errors.isNotEmpty) {
|
||||
@@ -374,7 +397,8 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
message += ' ${error.correction}';
|
||||
}
|
||||
var location = '$filePath:${error.startLine}:${error.startColumn}';
|
||||
var output = '$location $bullet '
|
||||
var output =
|
||||
'$location $bullet '
|
||||
'$message $bullet '
|
||||
'${ansi.green}$codeRef${ansi.none}';
|
||||
|
||||
@@ -391,9 +415,11 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
var contextPath = _relativePath(message.filePath, relativeToDir);
|
||||
var messageSentenceFragment = trimEnd(message.message, '.');
|
||||
|
||||
log.stdout('$_bodyIndent'
|
||||
' - $messageSentenceFragment at '
|
||||
'$contextPath:${message.line}:${message.column}.');
|
||||
log.stdout(
|
||||
'$_bodyIndent'
|
||||
' - $messageSentenceFragment at '
|
||||
'$contextPath:${message.line}:${message.column}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,26 +428,25 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
|
||||
@visibleForTesting
|
||||
static void emitJsonFormat(
|
||||
Logger log, List<AnalysisError> errors, UsageInfo? usageInfo) {
|
||||
Logger log,
|
||||
List<AnalysisError> errors,
|
||||
UsageInfo? usageInfo,
|
||||
) {
|
||||
Map<String, dynamic> location(
|
||||
String filePath, Map<String, dynamic> range) =>
|
||||
{
|
||||
'file': filePath,
|
||||
'range': range,
|
||||
};
|
||||
String filePath,
|
||||
Map<String, dynamic> range,
|
||||
) => {'file': filePath, 'range': range};
|
||||
|
||||
Map<String, dynamic> position(int? offset, int? line, int? column) => {
|
||||
'offset': offset,
|
||||
'line': line,
|
||||
'column': column,
|
||||
};
|
||||
'offset': offset,
|
||||
'line': line,
|
||||
'column': column,
|
||||
};
|
||||
|
||||
Map<String, dynamic> range(
|
||||
Map<String, dynamic> start, Map<String, dynamic> end) =>
|
||||
{
|
||||
'start': start,
|
||||
'end': end,
|
||||
};
|
||||
Map<String, dynamic> start,
|
||||
Map<String, dynamic> end,
|
||||
) => {'start': start, 'end': end};
|
||||
|
||||
var diagnostics = <Map<String, dynamic>>[];
|
||||
for (final AnalysisError error in errors) {
|
||||
@@ -430,12 +455,16 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
var startOffset = contextMessage.offset;
|
||||
contextMessages.add({
|
||||
'location': location(
|
||||
contextMessage.filePath,
|
||||
range(
|
||||
position(
|
||||
startOffset, contextMessage.line, contextMessage.column),
|
||||
position(startOffset + contextMessage.length,
|
||||
contextMessage.endLine, contextMessage.endColumn))),
|
||||
contextMessage.filePath,
|
||||
range(
|
||||
position(startOffset, contextMessage.line, contextMessage.column),
|
||||
position(
|
||||
startOffset + contextMessage.length,
|
||||
contextMessage.endLine,
|
||||
contextMessage.endColumn,
|
||||
),
|
||||
),
|
||||
),
|
||||
'message': contextMessage.message,
|
||||
});
|
||||
}
|
||||
@@ -445,37 +474,46 @@ class AnalyzeCommand extends DartdevCommand {
|
||||
'severity': error.severity,
|
||||
'type': error.type,
|
||||
'location': location(
|
||||
error.file,
|
||||
range(
|
||||
position(startOffset, error.startLine, error.startColumn),
|
||||
position(startOffset + error.length, error.endLine,
|
||||
error.endColumn))),
|
||||
error.file,
|
||||
range(
|
||||
position(startOffset, error.startLine, error.startColumn),
|
||||
position(
|
||||
startOffset + error.length,
|
||||
error.endLine,
|
||||
error.endColumn,
|
||||
),
|
||||
),
|
||||
),
|
||||
'problemMessage': error.message,
|
||||
if (error.correction != null) 'correctionMessage': error.correction,
|
||||
if (contextMessages.isNotEmpty) 'contextMessages': contextMessages,
|
||||
if (error.url != null) 'documentation': error.url,
|
||||
});
|
||||
}
|
||||
log.stdout(json.encode({
|
||||
'version': 1,
|
||||
'diagnostics': diagnostics,
|
||||
if (usageInfo != null) 'memory': usageInfo.memoryKB
|
||||
}));
|
||||
log.stdout(
|
||||
json.encode({
|
||||
'version': 1,
|
||||
'diagnostics': diagnostics,
|
||||
if (usageInfo != null) 'memory': usageInfo.memoryKB,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
static void emitMachineFormat(Logger log, List<AnalysisError> errors) {
|
||||
for (final AnalysisError error in errors) {
|
||||
log.stdout([
|
||||
error.severity,
|
||||
error.type,
|
||||
error.code.toUpperCase(),
|
||||
_escapeForMachineMode(error.file),
|
||||
error.startLine.toString(),
|
||||
error.startColumn.toString(),
|
||||
error.length.toString(),
|
||||
_escapeForMachineMode(error.message),
|
||||
].join('|'));
|
||||
log.stdout(
|
||||
[
|
||||
error.severity,
|
||||
error.type,
|
||||
error.code.toUpperCase(),
|
||||
_escapeForMachineMode(error.file),
|
||||
error.startLine.toString(),
|
||||
error.startColumn.toString(),
|
||||
error.length.toString(),
|
||||
_escapeForMachineMode(error.message),
|
||||
].join('|'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,17 +29,22 @@ class BuildCommand extends DartdevCommand {
|
||||
final bool recordUseEnabled;
|
||||
final bool dataAssetsExperimentEnabled;
|
||||
|
||||
BuildCommand(
|
||||
{bool verbose = false,
|
||||
required this.recordUseEnabled,
|
||||
required this.dataAssetsExperimentEnabled})
|
||||
: super(cmdName, 'Build a Dart application including code assets.',
|
||||
verbose) {
|
||||
addSubcommand(BuildCliSubcommand(
|
||||
verbose: verbose,
|
||||
recordUseEnabled: recordUseEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
));
|
||||
BuildCommand({
|
||||
bool verbose = false,
|
||||
required this.recordUseEnabled,
|
||||
required this.dataAssetsExperimentEnabled,
|
||||
}) : super(
|
||||
cmdName,
|
||||
'Build a Dart application including code assets.',
|
||||
verbose,
|
||||
) {
|
||||
addSubcommand(
|
||||
BuildCliSubcommand(
|
||||
verbose: verbose,
|
||||
recordUseEnabled: recordUseEnabled,
|
||||
dataAssetsExperimentEnabled: dataAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -59,13 +64,13 @@ class BuildCliSubcommand extends CompileSubcommandCommand {
|
||||
|
||||
final bool dataAssetsExperimentEnabled;
|
||||
|
||||
BuildCliSubcommand(
|
||||
{bool verbose = false,
|
||||
required this.recordUseEnabled,
|
||||
required this.dataAssetsExperimentEnabled})
|
||||
: super(
|
||||
cmdName,
|
||||
'''Build a Dart application with a command line interface (CLI).
|
||||
BuildCliSubcommand({
|
||||
bool verbose = false,
|
||||
required this.recordUseEnabled,
|
||||
required this.dataAssetsExperimentEnabled,
|
||||
}) : super(
|
||||
cmdName,
|
||||
'''Build a Dart application with a command line interface (CLI).
|
||||
|
||||
The resulting CLI app bundle is structured in the following manner:
|
||||
|
||||
@@ -75,18 +80,23 @@ bundle/
|
||||
lib/
|
||||
<dynamic libraries>
|
||||
''',
|
||||
verbose) {
|
||||
final binDirectory =
|
||||
Directory.fromUri(Directory.current.uri.resolve('bin/'));
|
||||
verbose,
|
||||
) {
|
||||
final binDirectory = Directory.fromUri(
|
||||
Directory.current.uri.resolve('bin/'),
|
||||
);
|
||||
|
||||
final outputDirectoryDefault = Directory.fromUri(Directory.current.uri
|
||||
.resolve('build/cli/${OS.current}_${Architecture.current}/'));
|
||||
final outputDirectoryDefault = Directory.fromUri(
|
||||
Directory.current.uri.resolve(
|
||||
'build/cli/${OS.current}_${Architecture.current}/',
|
||||
),
|
||||
);
|
||||
entryPoints = binDirectory.existsSync()
|
||||
? binDirectory
|
||||
.listSync()
|
||||
.whereType<File>()
|
||||
.where((e) => e.path.endsWith('dart'))
|
||||
.toList()
|
||||
.listSync()
|
||||
.whereType<File>()
|
||||
.where((e) => e.path.endsWith('dart'))
|
||||
.toList()
|
||||
: [];
|
||||
argParser
|
||||
..addOption(
|
||||
@@ -110,8 +120,10 @@ If the "--target" option is omitted, and there is a single Dart file in bin/,
|
||||
then that is used instead.''',
|
||||
valueHelp: 'path',
|
||||
defaultsTo: entryPoints.length == 1
|
||||
? path.relative(entryPoints.single.path,
|
||||
from: Directory.current.path)
|
||||
? path.relative(
|
||||
entryPoints.single.path,
|
||||
from: Directory.current.path,
|
||||
)
|
||||
: null,
|
||||
)
|
||||
..addOption(
|
||||
@@ -149,8 +161,9 @@ then that is used instead.''',
|
||||
);
|
||||
return 255;
|
||||
}
|
||||
final sourceUri =
|
||||
File.fromUri(Uri.file(target).normalizePath()).absolute.uri;
|
||||
final sourceUri = File.fromUri(
|
||||
Uri.file(target).normalizePath(),
|
||||
).absolute.uri;
|
||||
if (!checkFile(sourceUri.toFilePath())) {
|
||||
return genericErrorExitCode;
|
||||
}
|
||||
@@ -170,8 +183,9 @@ then that is used instead.''',
|
||||
final packageConfigUri = await DartNativeAssetsBuilder.ensurePackageConfig(
|
||||
sourceUri,
|
||||
);
|
||||
final pubspecUri =
|
||||
await DartNativeAssetsBuilder.findWorkspacePubspec(packageConfigUri);
|
||||
final pubspecUri = await DartNativeAssetsBuilder.findWorkspacePubspec(
|
||||
packageConfigUri,
|
||||
);
|
||||
final executableName = path.basenameWithoutExtension(sourceUri.path);
|
||||
|
||||
return await doBuild(
|
||||
@@ -230,16 +244,18 @@ then that is used instead.''',
|
||||
final binDirectory = Directory.fromUri(bundleDirectory.uri.resolve('bin/'));
|
||||
await binDirectory.create(recursive: true);
|
||||
|
||||
final packageConfig =
|
||||
await DartNativeAssetsBuilder.loadPackageConfig(packageConfigUri);
|
||||
final packageConfig = await DartNativeAssetsBuilder.loadPackageConfig(
|
||||
packageConfigUri,
|
||||
);
|
||||
if (packageConfig == null) {
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
final runPackageName = await DartNativeAssetsBuilder.findRootPackageName(
|
||||
executables.first.sourceEntryPoint,
|
||||
);
|
||||
pubspecUri ??=
|
||||
await DartNativeAssetsBuilder.findWorkspacePubspec(packageConfigUri);
|
||||
pubspecUri ??= await DartNativeAssetsBuilder.findWorkspacePubspec(
|
||||
packageConfigUri,
|
||||
);
|
||||
final builder = DartNativeAssetsBuilder(
|
||||
pubspecUri: pubspecUri,
|
||||
packageConfigUri: packageConfigUri,
|
||||
@@ -254,10 +270,7 @@ then that is used instead.''',
|
||||
final hasHooks = await builder.hasHooks();
|
||||
if (hasHooks) {
|
||||
buildResult = await (showProgress
|
||||
? progress(
|
||||
'Running build hooks',
|
||||
builder.buildNativeAssetsAOT,
|
||||
)
|
||||
? progress('Running build hooks', builder.buildNativeAssetsAOT)
|
||||
: builder.buildNativeAssetsAOT());
|
||||
if (buildResult == null) {
|
||||
stderr.writeln('Running build hooks failed.');
|
||||
@@ -323,8 +336,8 @@ then that is used instead.''',
|
||||
final allAssets = [
|
||||
if (hasHooks) ...[
|
||||
...buildResult!.encodedAssets,
|
||||
...linkResult!.encodedAssets
|
||||
]
|
||||
...linkResult!.encodedAssets,
|
||||
],
|
||||
];
|
||||
|
||||
final staticAssets = allAssets
|
||||
@@ -333,8 +346,9 @@ then that is used instead.''',
|
||||
.where((e) => e.linkMode == StaticLinking());
|
||||
if (staticAssets.isNotEmpty) {
|
||||
stderr.write(
|
||||
"""'dart build' does not yet support CodeAssets with static linking.
|
||||
Use linkMode as dynamic library instead.""");
|
||||
"""'dart build' does not yet support CodeAssets with static linking.
|
||||
Use linkMode as dynamic library instead.""",
|
||||
);
|
||||
return 255;
|
||||
}
|
||||
|
||||
@@ -348,8 +362,10 @@ Use linkMode as dynamic library instead.""");
|
||||
relocatable: true,
|
||||
verbose: true,
|
||||
);
|
||||
nativeAssetsYamlUri =
|
||||
await writeNativeAssetsYaml(kernelAssets, tempDir.uri);
|
||||
nativeAssetsYamlUri = await writeNativeAssetsYaml(
|
||||
kernelAssets,
|
||||
tempDir.uri,
|
||||
);
|
||||
}
|
||||
|
||||
await snapshotGenerator.generate(
|
||||
|
||||
@@ -33,12 +33,7 @@ class CompilationServerCommand extends DartdevCommand {
|
||||
'using the --resident-compiler-info-file option.';
|
||||
|
||||
CompilationServerCommand({bool verbose = false})
|
||||
: super(
|
||||
commandName,
|
||||
commandDescription,
|
||||
false,
|
||||
hidden: !verbose,
|
||||
) {
|
||||
: super(commandName, commandDescription, false, hidden: !verbose) {
|
||||
addSubcommand(CompilationServerStartCommand());
|
||||
addSubcommand(CompilationServerShutdownCommand());
|
||||
}
|
||||
@@ -53,12 +48,7 @@ class CompilationServerStartCommand extends DartdevCommand {
|
||||
static const commandDescription = 'Start a resident frontend compiler.';
|
||||
|
||||
CompilationServerStartCommand({bool verbose = false})
|
||||
: super(
|
||||
commandName,
|
||||
commandDescription,
|
||||
false,
|
||||
hidden: !verbose,
|
||||
) {
|
||||
: super(commandName, commandDescription, false, hidden: !verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
CompilationServerCommand.residentCompilerInfoFileFlag,
|
||||
@@ -112,7 +102,7 @@ Shut down a resident frontend compiler.
|
||||
Note that this command name and usage could change as we evolve the resident frontend compiler behavior.''';
|
||||
|
||||
CompilationServerShutdownCommand({bool verbose = false})
|
||||
: super(commandName, commandDescription, false, hidden: !verbose) {
|
||||
: super(commandName, commandDescription, false, hidden: !verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
CompilationServerCommand.residentCompilerInfoFileFlag,
|
||||
@@ -153,8 +143,9 @@ Note that this command name and usage could change as we evolve the resident fro
|
||||
return 0;
|
||||
}
|
||||
|
||||
final residentCompilerInfo =
|
||||
ResidentCompilerInfo.fromFile(residentCompilerInfoFile);
|
||||
final residentCompilerInfo = ResidentCompilerInfo.fromFile(
|
||||
residentCompilerInfoFile,
|
||||
);
|
||||
final address = residentCompilerInfo.address;
|
||||
final port = residentCompilerInfo.port;
|
||||
// There is nothing actionable the user can do in response to an error
|
||||
|
||||
@@ -86,11 +86,7 @@ bool checkFileWriteable(String destPath) {
|
||||
final file = File(destPath);
|
||||
final exists = file.existsSync();
|
||||
try {
|
||||
file.writeAsStringSync(
|
||||
'',
|
||||
mode: FileMode.append,
|
||||
flush: true,
|
||||
);
|
||||
file.writeAsStringSync('', mode: FileMode.append, flush: true);
|
||||
// Don't leave empty files around.
|
||||
if (!exists) {
|
||||
file.deleteSync();
|
||||
@@ -109,7 +105,7 @@ class CompileJSCommand extends CompileSubcommandCommand {
|
||||
final ArgParser argParser = ArgParser.allowAnything();
|
||||
|
||||
CompileJSCommand({bool verbose = false})
|
||||
: super(cmdName, 'Compile Dart to JavaScript.', verbose);
|
||||
: super(cmdName, 'Compile Dart to JavaScript.', verbose);
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
@@ -162,12 +158,12 @@ class CompileDDCCommand extends CompileSubcommandCommand {
|
||||
// This command is an internal developer command used by tools and is
|
||||
// hidden in the help message.
|
||||
CompileDDCCommand({bool verbose = false})
|
||||
: super(
|
||||
cmdName,
|
||||
'Compile Dart to JavaScript using ddc.',
|
||||
verbose,
|
||||
hidden: true,
|
||||
);
|
||||
: super(
|
||||
cmdName,
|
||||
'Compile Dart to JavaScript using ddc.',
|
||||
verbose,
|
||||
hidden: true,
|
||||
);
|
||||
|
||||
@override
|
||||
String get invocation => '${super.invocation} <dart entry point>';
|
||||
@@ -209,12 +205,12 @@ class CompileDDCCommand extends CompileSubcommandCommand {
|
||||
|
||||
class CompileKernelSnapshotCommand extends CompileSubcommandCommand {
|
||||
static const commandName = 'kernel';
|
||||
static const help = 'Compile Dart to a kernel snapshot.\n'
|
||||
static const help =
|
||||
'Compile Dart to a kernel snapshot.\n'
|
||||
'To run the snapshot use: dart run <kernel file>';
|
||||
|
||||
CompileKernelSnapshotCommand({
|
||||
bool verbose = false,
|
||||
}) : super(commandName, help, verbose) {
|
||||
CompileKernelSnapshotCommand({bool verbose = false})
|
||||
: super(commandName, help, verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
outputFileOption.flag,
|
||||
@@ -237,7 +233,8 @@ class CompileKernelSnapshotCommand extends CompileSubcommandCommand {
|
||||
)
|
||||
..addFlag(
|
||||
'link-platform',
|
||||
help: 'Includes the platform kernel in the resulting kernel file. '
|
||||
help:
|
||||
'Includes the platform kernel in the resulting kernel file. '
|
||||
"Required for use with 'dart compile exe' or 'dart compile aot-snapshot'.",
|
||||
defaultsTo: true,
|
||||
)
|
||||
@@ -306,7 +303,8 @@ class CompileKernelSnapshotCommand extends CompileSubcommandCommand {
|
||||
final bool soundNullSafety = args.flag('sound-null-safety');
|
||||
if (!soundNullSafety) {
|
||||
log.stdout(
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.');
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.',
|
||||
);
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
|
||||
@@ -336,13 +334,13 @@ class CompileKernelSnapshotCommand extends CompileSubcommandCommand {
|
||||
}
|
||||
|
||||
class CompileJitSnapshotCommand extends CompileSubcommandCommand {
|
||||
static const help = 'Compile Dart to a JIT snapshot.\n'
|
||||
static const help =
|
||||
'Compile Dart to a JIT snapshot.\n'
|
||||
'The executable will be run once to snapshot a warm JIT.\n'
|
||||
'To run the snapshot use: dart run <JIT file>';
|
||||
|
||||
CompileJitSnapshotCommand({
|
||||
bool verbose = false,
|
||||
}) : super('jit-snapshot', help, verbose) {
|
||||
CompileJitSnapshotCommand({bool verbose = false})
|
||||
: super('jit-snapshot', help, verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
outputFileOption.flag,
|
||||
@@ -374,10 +372,12 @@ class CompileJitSnapshotCommand extends CompileSubcommandCommand {
|
||||
negatable: false,
|
||||
help: enableAssertsOption.help,
|
||||
)
|
||||
..addFlag(soundNullSafetyOption.flag,
|
||||
help: soundNullSafetyOption.help,
|
||||
defaultsTo: soundNullSafetyOption.flagDefaultsTo,
|
||||
hide: true)
|
||||
..addFlag(
|
||||
soundNullSafetyOption.flag,
|
||||
help: soundNullSafetyOption.help,
|
||||
defaultsTo: soundNullSafetyOption.flagDefaultsTo,
|
||||
hide: true,
|
||||
)
|
||||
..addExperimentalFlags(verbose: verbose);
|
||||
}
|
||||
|
||||
@@ -433,7 +433,8 @@ class CompileJitSnapshotCommand extends CompileSubcommandCommand {
|
||||
final bool soundNullSafety = args.flag('sound-null-safety');
|
||||
if (!soundNullSafety) {
|
||||
log.stdout(
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.');
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.',
|
||||
);
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
|
||||
@@ -479,7 +480,7 @@ class CompileNativeCommand extends CompileSubcommandCommand {
|
||||
Target.linuxArm,
|
||||
Target.linuxArm64,
|
||||
Target.linuxRiscv64,
|
||||
Target.linuxX64
|
||||
Target.linuxX64,
|
||||
};
|
||||
|
||||
final String commandName;
|
||||
@@ -525,10 +526,12 @@ class CompileNativeCommand extends CompileSubcommandCommand {
|
||||
valueHelp: packagesOption.valueHelp,
|
||||
help: packagesOption.help,
|
||||
)
|
||||
..addFlag(soundNullSafetyOption.flag,
|
||||
help: soundNullSafetyOption.help,
|
||||
defaultsTo: soundNullSafetyOption.flagDefaultsTo,
|
||||
hide: true)
|
||||
..addFlag(
|
||||
soundNullSafetyOption.flag,
|
||||
help: soundNullSafetyOption.help,
|
||||
defaultsTo: soundNullSafetyOption.flagDefaultsTo,
|
||||
hide: true,
|
||||
)
|
||||
..addOption(
|
||||
'save-debugging-info',
|
||||
abbr: 'S',
|
||||
@@ -554,16 +557,22 @@ Remove debugging information from the output and save it separately to the speci
|
||||
hide: true,
|
||||
valueHelp: 'opt1,opt2,...',
|
||||
)
|
||||
..addOption('target-os',
|
||||
help: 'Compile to a specific target operating system.',
|
||||
allowed: TargetOS.names)
|
||||
..addOption('target-arch',
|
||||
help: 'Compile to a specific target architecture.',
|
||||
allowed: Architecture.values.map((v) => v.name).toList())
|
||||
..addOption('target-sanitizer',
|
||||
help:
|
||||
'Compile to a specific target sanitizer. Sanitizers are not offered with single-file executables because the sanitizers cannot symbolize embedded snapshots.',
|
||||
allowed: availableSanitizers())
|
||||
..addOption(
|
||||
'target-os',
|
||||
help: 'Compile to a specific target operating system.',
|
||||
allowed: TargetOS.names,
|
||||
)
|
||||
..addOption(
|
||||
'target-arch',
|
||||
help: 'Compile to a specific target architecture.',
|
||||
allowed: Architecture.values.map((v) => v.name).toList(),
|
||||
)
|
||||
..addOption(
|
||||
'target-sanitizer',
|
||||
help:
|
||||
'Compile to a specific target sanitizer. Sanitizers are not offered with single-file executables because the sanitizers cannot symbolize embedded snapshots.',
|
||||
allowed: availableSanitizers(),
|
||||
)
|
||||
..addExperimentalFlags(verbose: verbose);
|
||||
}
|
||||
|
||||
@@ -594,7 +603,8 @@ Remove debugging information from the output and save it separately to the speci
|
||||
// executable only supports AOT runtimes, so these commands are disabled.
|
||||
if (Platform.version.contains('ia32')) {
|
||||
stderr.write(
|
||||
"'dart compile $commandName' is not supported on x86 architectures.\n");
|
||||
"'dart compile $commandName' is not supported on x86 architectures.\n",
|
||||
);
|
||||
return 64;
|
||||
}
|
||||
// Kernel is always generated using the host's dartaotruntime and
|
||||
@@ -617,7 +627,8 @@ Remove debugging information from the output and save it separately to the speci
|
||||
|
||||
if (!args.flag('sound-null-safety')) {
|
||||
log.stdout(
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.');
|
||||
'Error: the flag --no-sound-null-safety is not supported in Dart 3.',
|
||||
);
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
|
||||
@@ -629,8 +640,10 @@ Remove debugging information from the output and save it separately to the speci
|
||||
if (target != null) {
|
||||
if (!supportedTargetPlatforms.contains(target)) {
|
||||
stderr.writeln('Unsupported target platform $target.');
|
||||
stderr.writeln('Supported target platforms: '
|
||||
'${supportedTargetPlatforms.join(', ')}');
|
||||
stderr.writeln(
|
||||
'Supported target platforms: '
|
||||
'${supportedTargetPlatforms.join(', ')}',
|
||||
);
|
||||
return crossCompileErrorExitCode;
|
||||
}
|
||||
|
||||
@@ -639,21 +652,31 @@ Remove debugging information from the output and save it separately to the speci
|
||||
cacheDir = Directory(path.join(cacheDir.path, 'dartdev', 'sdk_cache'));
|
||||
} else {
|
||||
cacheDir = Directory.systemTemp.createTempSync();
|
||||
log.stdout('Cannot get dart storage directory. '
|
||||
'Using temp dir ${cacheDir.path}');
|
||||
log.stdout(
|
||||
'Cannot get dart storage directory. '
|
||||
'Using temp dir ${cacheDir.path}',
|
||||
);
|
||||
}
|
||||
final httpClient = http.Client();
|
||||
try {
|
||||
final cache = SdkCache(
|
||||
directory: cacheDir.path, verbose: verbose, httpClient: httpClient);
|
||||
directory: cacheDir.path,
|
||||
verbose: verbose,
|
||||
httpClient: httpClient,
|
||||
);
|
||||
final archiveFolder = await cache.resolveVersion(
|
||||
version: Runtime.runtime.version,
|
||||
revision: sdk.revision ?? '',
|
||||
channelName: Runtime.runtime.channel ?? 'unknown');
|
||||
version: Runtime.runtime.version,
|
||||
revision: sdk.revision ?? '',
|
||||
channelName: Runtime.runtime.channel ?? 'unknown',
|
||||
);
|
||||
genSnapshotBinary = await cache.ensureGenSnapshot(
|
||||
archiveFolder: archiveFolder, target: target);
|
||||
archiveFolder: archiveFolder,
|
||||
target: target,
|
||||
);
|
||||
dartAotRuntimeBinary = await cache.ensureDartAotRuntime(
|
||||
archiveFolder: archiveFolder, target: target);
|
||||
archiveFolder: archiveFolder,
|
||||
target: target,
|
||||
);
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
@@ -663,8 +686,9 @@ Remove debugging information from the output and save it separately to the speci
|
||||
Directory.current.uri,
|
||||
);
|
||||
if (packageConfigUri != null) {
|
||||
final packageConfig =
|
||||
await DartNativeAssetsBuilder.loadPackageConfig(packageConfigUri);
|
||||
final packageConfig = await DartNativeAssetsBuilder.loadPackageConfig(
|
||||
packageConfigUri,
|
||||
);
|
||||
if (packageConfig == null) {
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
@@ -673,16 +697,18 @@ Remove debugging information from the output and save it separately to the speci
|
||||
);
|
||||
if (runPackageName != null) {
|
||||
final pubspecUri = await DartNativeAssetsBuilder.findWorkspacePubspec(
|
||||
packageConfigUri);
|
||||
packageConfigUri,
|
||||
);
|
||||
final builder = DartNativeAssetsBuilder(
|
||||
pubspecUri: pubspecUri,
|
||||
packageConfigUri: packageConfigUri,
|
||||
packageConfig: packageConfig,
|
||||
runPackageName: runPackageName,
|
||||
includeDevDependencies: false,
|
||||
dataAssetsExperimentEnabled: false,
|
||||
verbose: verbose,
|
||||
target: target);
|
||||
pubspecUri: pubspecUri,
|
||||
packageConfigUri: packageConfigUri,
|
||||
packageConfig: packageConfig,
|
||||
runPackageName: runPackageName,
|
||||
includeDevDependencies: false,
|
||||
dataAssetsExperimentEnabled: false,
|
||||
verbose: verbose,
|
||||
target: target,
|
||||
);
|
||||
if (!nativeAssetsExperimentEnabled) {
|
||||
if (await builder.warnOnNativeAssets()) {
|
||||
return 255;
|
||||
@@ -707,10 +733,7 @@ Remove debugging information from the output and save it separately to the speci
|
||||
kind: format,
|
||||
sourceFile: sourcePath,
|
||||
outputFile: args.option('output'),
|
||||
defines: [
|
||||
...sanitizer.defines,
|
||||
...args.multiOption(defineOption.flag),
|
||||
],
|
||||
defines: [...sanitizer.defines, ...args.multiOption(defineOption.flag)],
|
||||
packages: args.option('packages'),
|
||||
enableExperiment: args.enabledExperiments.join(','),
|
||||
enableAsserts: args.flag(enableAssertsOption.flag),
|
||||
@@ -778,7 +801,7 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
static const String help = 'Compile Dart to a WebAssembly/WasmGC module.';
|
||||
|
||||
CompileWasmCommand({bool verbose = false})
|
||||
: super(commandName, help, verbose) {
|
||||
: super(commandName, help, verbose) {
|
||||
argParser
|
||||
..addOption(
|
||||
outputFileOption.flag,
|
||||
@@ -788,7 +811,8 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
..addFlag(
|
||||
'minify',
|
||||
negatable: true,
|
||||
help: 'Minify names that are needed at runtime (such as class names). '
|
||||
help:
|
||||
'Minify names that are needed at runtime (such as class names). '
|
||||
'Affects e.g. `<obj>.runtimeType.toString()`). If passed, this '
|
||||
'takes precedence over the optimization-level option.',
|
||||
hide: !verbose,
|
||||
@@ -826,19 +850,23 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
)
|
||||
..addOption(
|
||||
'shared-memory',
|
||||
help: 'Import a shared memory buffer.'
|
||||
help:
|
||||
'Import a shared memory buffer.'
|
||||
' The max number of pages must be passed.',
|
||||
valueHelp: 'page count',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addMultiOption('phases',
|
||||
help: 'Specifies which phases of the dart2wasm compiler to run. Each '
|
||||
'phase will emit a partial result that is then the input to the '
|
||||
'next phase.',
|
||||
allowed: ['cfe', 'tfa', 'codegen', 'opt'],
|
||||
defaultsTo: ['cfe', 'tfa', 'codegen', 'opt'],
|
||||
hide: !verbose,
|
||||
splitCommas: true)
|
||||
..addMultiOption(
|
||||
'phases',
|
||||
help:
|
||||
'Specifies which phases of the dart2wasm compiler to run. Each '
|
||||
'phase will emit a partial result that is then the input to the '
|
||||
'next phase.',
|
||||
allowed: ['cfe', 'tfa', 'codegen', 'opt'],
|
||||
defaultsTo: ['cfe', 'tfa', 'codegen', 'opt'],
|
||||
hide: !verbose,
|
||||
splitCommas: true,
|
||||
)
|
||||
..addMultiOption(
|
||||
'extra-compiler-option',
|
||||
abbr: 'E',
|
||||
@@ -849,7 +877,8 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
..addOption(
|
||||
'optimization-level',
|
||||
abbr: 'O',
|
||||
help: 'Controls optimizations that can help reduce code-size and '
|
||||
help:
|
||||
'Controls optimizations that can help reduce code-size and '
|
||||
'improve performance of the generated code.',
|
||||
allowed: ['0', '1', '2', '3', '4'],
|
||||
defaultsTo: '1',
|
||||
@@ -861,11 +890,14 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
help: 'Generate a source map file.',
|
||||
defaultsTo: true,
|
||||
)
|
||||
..addFlag('enable-deferred-loading',
|
||||
help: 'Emit multiple modules based on the Dart program\'s deferred '
|
||||
'import graph.',
|
||||
hide: !verbose,
|
||||
defaultsTo: false)
|
||||
..addFlag(
|
||||
'enable-deferred-loading',
|
||||
help:
|
||||
'Emit multiple modules based on the Dart program\'s deferred '
|
||||
'import graph.',
|
||||
hide: !verbose,
|
||||
defaultsTo: false,
|
||||
)
|
||||
..addOption(
|
||||
packagesOption.flag,
|
||||
abbr: packagesOption.abbr,
|
||||
@@ -904,8 +936,9 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
}
|
||||
final String sourcePath = args.rest[0];
|
||||
final extraCompilerOptions = args.multiOption('extra-compiler-option');
|
||||
final isMultiRoot =
|
||||
extraCompilerOptions.any((e) => e.contains('multi-root'));
|
||||
final isMultiRoot = extraCompilerOptions.any(
|
||||
(e) => e.contains('multi-root'),
|
||||
);
|
||||
|
||||
// If we know the source file doesn't exist, we want to abort early with an
|
||||
// obvious error message. We can't resolve the actual path here if the input
|
||||
@@ -935,7 +968,8 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
maxPages = int.tryParse(args.option('shared-memory')!);
|
||||
if (maxPages == null) {
|
||||
usageException(
|
||||
'Error: The --shared-memory flag must specify a number!');
|
||||
'Error: The --shared-memory flag must specify a number!',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -946,7 +980,8 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
optimizationLevel = int.tryParse(args.option('optimization-level')!);
|
||||
if (optimizationLevel == null) {
|
||||
usageException(
|
||||
'Error: The --optimization-level flag must specify a number!');
|
||||
'Error: The --optimization-level flag must specify a number!',
|
||||
);
|
||||
}
|
||||
if (optimizationLevel == 0) {
|
||||
if (!args.wasParsed('phases')) {
|
||||
@@ -1003,7 +1038,8 @@ class CompileWasmCommand extends CompileSubcommandCommand {
|
||||
|
||||
final mjsFile = '$outputFileBasename.mjs';
|
||||
log.stdout(
|
||||
"Generated wasm module '$outputFile', and JS init file '$mjsFile'.");
|
||||
"Generated wasm module '$outputFile', and JS init file '$mjsFile'.",
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1042,19 +1078,26 @@ For example: dart compile $name -Da=1,b=2 main.dart''',
|
||||
);
|
||||
|
||||
late final Option packagesOption = Option(
|
||||
flag: 'packages',
|
||||
abbr: 'p',
|
||||
valueHelp: 'path',
|
||||
help:
|
||||
'''Get package locations from the specified file instead of .dart_tool/package_config.json.
|
||||
flag: 'packages',
|
||||
abbr: 'p',
|
||||
valueHelp: 'path',
|
||||
help:
|
||||
'''Get package locations from the specified file instead of .dart_tool/package_config.json.
|
||||
<path> can be relative or absolute.
|
||||
For example: dart compile $name --packages=/tmp/pkgs.json main.dart''');
|
||||
For example: dart compile $name --packages=/tmp/pkgs.json main.dart''',
|
||||
);
|
||||
|
||||
final Option enableAssertsOption =
|
||||
Option(flag: 'enable-asserts', help: 'Enable assert statements.');
|
||||
final Option enableAssertsOption = Option(
|
||||
flag: 'enable-asserts',
|
||||
help: 'Enable assert statements.',
|
||||
);
|
||||
|
||||
CompileSubcommandCommand(super.name, super.description, super.verbose,
|
||||
{super.hidden});
|
||||
CompileSubcommandCommand(
|
||||
super.name,
|
||||
super.description,
|
||||
super.verbose, {
|
||||
super.hidden,
|
||||
});
|
||||
}
|
||||
|
||||
class CompileCommand extends DartdevCommand {
|
||||
@@ -1068,21 +1111,26 @@ class CompileCommand extends DartdevCommand {
|
||||
addSubcommand(CompileDDCCommand(verbose: verbose));
|
||||
addSubcommand(CompileJitSnapshotCommand(verbose: verbose));
|
||||
addSubcommand(CompileKernelSnapshotCommand(verbose: verbose));
|
||||
addSubcommand(CompileNativeCommand(
|
||||
commandName: CompileNativeCommand.exeCmdName,
|
||||
help: 'to a self-contained executable.',
|
||||
format: Kind.exe,
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
));
|
||||
addSubcommand(CompileNativeCommand(
|
||||
commandName: CompileNativeCommand.aotSnapshotCmdName,
|
||||
help: 'to an AOT snapshot.\n'
|
||||
'To run the snapshot use: dartaotruntime <AOT snapshot file>',
|
||||
format: Kind.aot,
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
));
|
||||
addSubcommand(
|
||||
CompileNativeCommand(
|
||||
commandName: CompileNativeCommand.exeCmdName,
|
||||
help: 'to a self-contained executable.',
|
||||
format: Kind.exe,
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
addSubcommand(
|
||||
CompileNativeCommand(
|
||||
commandName: CompileNativeCommand.aotSnapshotCmdName,
|
||||
help:
|
||||
'to an AOT snapshot.\n'
|
||||
'To run the snapshot use: dartaotruntime <AOT snapshot file>',
|
||||
format: Kind.aot,
|
||||
verbose: verbose,
|
||||
nativeAssetsExperimentEnabled: nativeAssetsExperimentEnabled,
|
||||
),
|
||||
);
|
||||
addSubcommand(CompileWasmCommand(verbose: verbose));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,19 +20,19 @@ class CreateCommand extends DartdevCommand {
|
||||
static const String defaultTemplateId = 'console';
|
||||
|
||||
static List<String> legalTemplateIds({bool includeDeprecated = false}) => [
|
||||
for (var g in generators) ...[
|
||||
if (includeDeprecated || !g.deprecated) g.id,
|
||||
if (includeDeprecated && g.alternateId != null) g.alternateId!
|
||||
]
|
||||
];
|
||||
for (var g in generators) ...[
|
||||
if (includeDeprecated || !g.deprecated) g.id,
|
||||
if (includeDeprecated && g.alternateId != null) g.alternateId!,
|
||||
],
|
||||
];
|
||||
|
||||
static final Map<String, String> templateHelp = {
|
||||
for (var g in generators)
|
||||
if (!g.deprecated) g.id: g.description
|
||||
if (!g.deprecated) g.id: g.description,
|
||||
};
|
||||
|
||||
CreateCommand({bool verbose = false})
|
||||
: super(cmdName, 'Create a new Dart project.', verbose) {
|
||||
: super(cmdName, 'Create a new Dart project.', verbose) {
|
||||
argParser.addOption(
|
||||
'template',
|
||||
allowed: legalTemplateIds(includeDeprecated: true),
|
||||
@@ -41,9 +41,11 @@ class CreateCommand extends DartdevCommand {
|
||||
defaultsTo: defaultTemplateId,
|
||||
abbr: 't',
|
||||
);
|
||||
argParser.addFlag('pub',
|
||||
defaultsTo: true,
|
||||
help: "Whether to run 'pub get' after the project has been created.");
|
||||
argParser.addFlag(
|
||||
'pub',
|
||||
defaultsTo: true,
|
||||
help: "Whether to run 'pub get' after the project has been created.",
|
||||
);
|
||||
argParser.addFlag(
|
||||
'list-templates',
|
||||
negatable: false,
|
||||
@@ -53,7 +55,8 @@ class CreateCommand extends DartdevCommand {
|
||||
argParser.addFlag(
|
||||
'force',
|
||||
negatable: false,
|
||||
help: 'Force project generation, even if the target directory already '
|
||||
help:
|
||||
'Force project generation, even if the target directory already '
|
||||
'exists.',
|
||||
);
|
||||
}
|
||||
@@ -97,8 +100,10 @@ class CreateCommand extends DartdevCommand {
|
||||
projectName = normalizeProjectName(projectName);
|
||||
|
||||
if (!isValidPackageName(projectName)) {
|
||||
log.stderr('"$projectName" is not a valid Dart project name.\n\n'
|
||||
'See https://dart.dev/tools/pub/pubspec#name for more information.');
|
||||
log.stderr(
|
||||
'"$projectName" is not a valid Dart project name.\n\n'
|
||||
'See https://dart.dev/tools/pub/pubspec#name for more information.',
|
||||
);
|
||||
return 73;
|
||||
}
|
||||
|
||||
@@ -140,26 +145,25 @@ class CreateCommand extends DartdevCommand {
|
||||
|
||||
log.stdout('');
|
||||
log.stdout(
|
||||
'Created project $projectName in ${p.relative(dir)}! In order to get '
|
||||
'started, run the following commands:');
|
||||
'Created project $projectName in ${p.relative(dir)}! In order to get '
|
||||
'started, run the following commands:',
|
||||
);
|
||||
log.stdout('');
|
||||
log.stdout(generator.getInstallInstructions(
|
||||
dir,
|
||||
scriptPath: projectName,
|
||||
));
|
||||
log.stdout(generator.getInstallInstructions(dir, scriptPath: projectName));
|
||||
log.stdout('');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
String _availableTemplatesJson() {
|
||||
var items =
|
||||
generators.where((g) => !g.deprecated).map((Generator generator) {
|
||||
var items = generators.where((g) => !g.deprecated).map((
|
||||
Generator generator,
|
||||
) {
|
||||
var m = {
|
||||
'name': generator.id,
|
||||
'label': generator.label,
|
||||
'description': generator.description,
|
||||
'categories': generator.categories
|
||||
'categories': generator.categories,
|
||||
};
|
||||
|
||||
if (generator.entrypoint != null) {
|
||||
|
||||
@@ -22,18 +22,23 @@ A stdio based Model Context Protocol (MCP) server to aid in Dart and Flutter dev
|
||||
|
||||
@override
|
||||
ArgParser createArgParser() => dart_mcp_server.createArgParser(
|
||||
usageLineLength: dartdevUsageLineLength, includeHelp: false);
|
||||
usageLineLength: dartdevUsageLineLength,
|
||||
includeHelp: false,
|
||||
);
|
||||
|
||||
DartMCPServerCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose, hidden: true) {
|
||||
argParser.addFlag(_experimentFlag,
|
||||
// This flag is no longer required but we are leaving it in for
|
||||
// backwards compatibility.
|
||||
hide: true,
|
||||
defaultsTo: false,
|
||||
help: 'A required flag in order to use this command. Passing this '
|
||||
'flag is an acknowledgement that you understand it is an '
|
||||
'experimental feature with no stability guarantees.');
|
||||
: super(cmdName, cmdDescription, verbose, hidden: true) {
|
||||
argParser.addFlag(
|
||||
_experimentFlag,
|
||||
// This flag is no longer required but we are leaving it in for
|
||||
// backwards compatibility.
|
||||
hide: true,
|
||||
defaultsTo: false,
|
||||
help:
|
||||
'A required flag in order to use this command. Passing this '
|
||||
'flag is an acknowledgement that you understand it is an '
|
||||
'experimental feature with no stability guarantees.',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -50,13 +55,9 @@ A stdio based Model Context Protocol (MCP) server to aid in Dart and Flutter dev
|
||||
forwardedArgs.removeWhere((arg) => arg.endsWith(_experimentFlag));
|
||||
}
|
||||
try {
|
||||
VmInteropHandler.run(
|
||||
sdk.dartMCPServerAotSnapshot,
|
||||
[
|
||||
...forwardedArgs,
|
||||
],
|
||||
useExecProcess: false,
|
||||
);
|
||||
VmInteropHandler.run(sdk.dartMCPServerAotSnapshot, [
|
||||
...forwardedArgs,
|
||||
], useExecProcess: false);
|
||||
return 0;
|
||||
} catch (e, st) {
|
||||
log.stderr('Error: launching Dart MCP server failed');
|
||||
|
||||
@@ -21,12 +21,12 @@ class DebugAdapterCommand extends DartdevCommand {
|
||||
static const argTest = 'test';
|
||||
|
||||
DebugAdapterCommand({bool verbose = false})
|
||||
: super(
|
||||
cmdName,
|
||||
'Start a debug adapter that conforms to the Debug Adapter Protocol.',
|
||||
verbose,
|
||||
hidden: true,
|
||||
) {
|
||||
: super(
|
||||
cmdName,
|
||||
'Start a debug adapter that conforms to the Debug Adapter Protocol.',
|
||||
verbose,
|
||||
hidden: true,
|
||||
) {
|
||||
argParser
|
||||
..addFlag(
|
||||
argIpv6,
|
||||
@@ -54,7 +54,8 @@ class DebugAdapterCommand extends DartdevCommand {
|
||||
..addFlag(
|
||||
argTest,
|
||||
defaultsTo: false,
|
||||
help: 'Whether to use the "dart test" debug adapter to run tests'
|
||||
help:
|
||||
'Whether to use the "dart test" debug adapter to run tests'
|
||||
' and emit custom events for test progress/results.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,7 @@ class DevelopmentServiceCommand extends DartdevCommand {
|
||||
static const String commandDescription = "Start Dart's development service.";
|
||||
|
||||
DevelopmentServiceCommand({bool verbose = false})
|
||||
: super(
|
||||
commandName,
|
||||
commandDescription,
|
||||
verbose,
|
||||
hidden: !verbose,
|
||||
) {
|
||||
: super(commandName, commandDescription, verbose, hidden: !verbose) {
|
||||
DartDevelopmentServiceOptions.populateArgParser(
|
||||
argParser: argParser,
|
||||
verbose: verbose,
|
||||
@@ -42,8 +37,10 @@ class DevelopmentServiceCommand extends DartdevCommand {
|
||||
final args = argResults!.arguments;
|
||||
|
||||
if (!checkArtifactExists(snapshot, logError: false)) {
|
||||
log.stderr('Error: launching development server failed : '
|
||||
'Unable to find snapshot for the development server');
|
||||
log.stderr(
|
||||
'Error: launching development server failed : '
|
||||
'Unable to find snapshot for the development server',
|
||||
);
|
||||
return 255;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -17,19 +17,13 @@ import '../sdk.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
class DevToolsCommand extends DartdevCommand {
|
||||
DevToolsCommand({
|
||||
this.customDevToolsPath,
|
||||
bool verbose = false,
|
||||
}) : argParser = DevToolsServer.buildArgParser(
|
||||
verbose: verbose,
|
||||
includeHelpOption: false,
|
||||
usageLineLength: dartdevUsageLineLength,
|
||||
),
|
||||
super(
|
||||
'devtools',
|
||||
DevToolsServer.commandDescription,
|
||||
verbose,
|
||||
);
|
||||
DevToolsCommand({this.customDevToolsPath, bool verbose = false})
|
||||
: argParser = DevToolsServer.buildArgParser(
|
||||
verbose: verbose,
|
||||
includeHelpOption: false,
|
||||
usageLineLength: dartdevUsageLineLength,
|
||||
),
|
||||
super('devtools', DevToolsServer.commandDescription, verbose);
|
||||
|
||||
final String? customDevToolsPath;
|
||||
|
||||
@@ -54,8 +48,9 @@ class DevToolsCommand extends DartdevCommand {
|
||||
|
||||
final sdkDir = path.dirname(sdk.dart);
|
||||
final fullSdk = sdkDir.endsWith('bin');
|
||||
final devToolsBinaries =
|
||||
fullSdk ? sdk.devToolsBinaries : path.absolute(sdkDir, 'devtools');
|
||||
final devToolsBinaries = fullSdk
|
||||
? sdk.devToolsBinaries
|
||||
: path.absolute(sdkDir, 'devtools');
|
||||
|
||||
final argList = await _performDDSCheck(args);
|
||||
final server = await DevToolsServer().serveDevToolsWithArgs(
|
||||
@@ -160,10 +155,7 @@ class DevToolsCommand extends DartdevCommand {
|
||||
if (pathSegments.length == 1) {
|
||||
pathSegments.add('');
|
||||
}
|
||||
uri = ddsWsUri.replace(
|
||||
scheme: 'http',
|
||||
pathSegments: pathSegments,
|
||||
);
|
||||
uri = ddsWsUri.replace(scheme: 'http', pathSegments: pathSegments);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
@@ -186,10 +178,7 @@ class DevToolsCommand extends DartdevCommand {
|
||||
final authCodesEnabled = pathSegments.isNotEmpty;
|
||||
final wsUri = uri.replace(
|
||||
scheme: 'ws',
|
||||
pathSegments: [
|
||||
...pathSegments,
|
||||
'ws',
|
||||
],
|
||||
pathSegments: [...pathSegments, 'ws'],
|
||||
);
|
||||
|
||||
final vmService = await vmServiceConnectUri(wsUri.toString());
|
||||
@@ -221,9 +210,7 @@ class DevToolsCommand extends DartdevCommand {
|
||||
)) {
|
||||
uri = debugSession.ddsUri!;
|
||||
if (!machineMode) {
|
||||
print(
|
||||
'Started the Dart Development Service (DDS) at $uri',
|
||||
);
|
||||
print('Started the Dart Development Service (DDS) at $uri');
|
||||
}
|
||||
} else if (!machineMode) {
|
||||
print(
|
||||
|
||||
@@ -89,8 +89,13 @@ For additional documentation generation options, see the 'dartdoc_options.yaml'
|
||||
}
|
||||
|
||||
// Specify where dartdoc resources are located.
|
||||
final resourcesPath =
|
||||
path.absolute(sdk.sdkPath, 'bin', 'resources', 'dartdoc', 'resources');
|
||||
final resourcesPath = path.absolute(
|
||||
sdk.sdkPath,
|
||||
'bin',
|
||||
'resources',
|
||||
'dartdoc',
|
||||
'resources',
|
||||
);
|
||||
|
||||
// Build remaining options.
|
||||
options.addAll([
|
||||
|
||||
@@ -37,11 +37,13 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
|
||||
FixCommand({bool verbose = false}) : super(cmdName, cmdDescription, verbose) {
|
||||
argParser
|
||||
..addFlag('dry-run',
|
||||
abbr: 'n',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Preview the proposed changes but make no changes.')
|
||||
..addFlag(
|
||||
'dry-run',
|
||||
abbr: 'n',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Preview the proposed changes but make no changes.',
|
||||
)
|
||||
..addFlag(
|
||||
'apply',
|
||||
defaultsTo: false,
|
||||
@@ -120,7 +122,8 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
|
||||
final targetName = path.basename(fixPath);
|
||||
Progress? computeFixesProgress = log.progress(
|
||||
'Computing fixes in ${log.ansi.emphasized(targetName)}$modeText');
|
||||
'Computing fixes in ${log.ansi.emphasized(targetName)}$modeText',
|
||||
);
|
||||
|
||||
var server = AnalysisServer(
|
||||
null,
|
||||
@@ -172,8 +175,12 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
// If there are no more dart edits, check if there are any changes
|
||||
// to pubspec
|
||||
if (edits.isEmpty && detailsMap.isNotEmpty) {
|
||||
var fixes = await server.requestBulkFixes(fixPath, inTestMode, [],
|
||||
updatePubspec: true);
|
||||
var fixes = await server.requestBulkFixes(
|
||||
fixPath,
|
||||
inTestMode,
|
||||
[],
|
||||
updatePubspec: true,
|
||||
);
|
||||
_mergeDetails(detailsMap, fixes.details);
|
||||
edits = fixes.edits;
|
||||
_applyEdits(server, edits);
|
||||
@@ -208,13 +215,17 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
var fileCount = detailsMap.length;
|
||||
var fixCount = detailsMap.values
|
||||
.expand((detail) => detail.fixes)
|
||||
.fold<int>(0,
|
||||
(int previousValue, fixes) => previousValue + fixes.occurrences);
|
||||
.fold<int>(
|
||||
0,
|
||||
(int previousValue, fixes) => previousValue + fixes.occurrences,
|
||||
);
|
||||
|
||||
if (dryRun) {
|
||||
log.stdout('');
|
||||
log.stdout('$fixCount proposed ${_pluralFix(fixCount)} '
|
||||
'in $fileCount ${pluralize("file", fileCount)}.');
|
||||
log.stdout(
|
||||
'$fixCount proposed ${_pluralFix(fixCount)} '
|
||||
'in $fileCount ${pluralize("file", fileCount)}.',
|
||||
);
|
||||
_printDetails(detailsMap, dir);
|
||||
_printApplyFixDetails(detailsMap);
|
||||
} else {
|
||||
@@ -222,8 +233,10 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
_writeFiles();
|
||||
applyFixesProgress.finish(showTiming: true);
|
||||
_printDetails(detailsMap, dir);
|
||||
log.stdout('$fixCount ${_pluralFix(fixCount)} made in '
|
||||
'$fileCount ${pluralize("file", fileCount)}.');
|
||||
log.stdout(
|
||||
'$fixCount ${_pluralFix(fixCount)} made in '
|
||||
'$fileCount ${pluralize("file", fileCount)}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +291,8 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
if (expectFile == null) {
|
||||
result.failCount++;
|
||||
log.stdout(
|
||||
'No corresponding expect file for the Dart file at "$filePath".');
|
||||
'No corresponding expect file for the Dart file at "$filePath".',
|
||||
);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
@@ -306,7 +320,8 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
result.failCount++;
|
||||
log.stdout('Failed to process "$filePath".');
|
||||
log.stdout(
|
||||
' Ensure that the file and its expect file are both readable.');
|
||||
' Ensure that the file and its expect file are both readable.',
|
||||
);
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -315,7 +330,8 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
for (var unmatchedExpectPath in expectFileMap.keys) {
|
||||
result.failCount++;
|
||||
log.stdout(
|
||||
'No corresponding Dart file for the expect file at "$unmatchedExpectPath".');
|
||||
'No corresponding Dart file for the expect file at "$unmatchedExpectPath".',
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -330,8 +346,9 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
usageException('Only one file or directory is expected.');
|
||||
}
|
||||
|
||||
var basePath =
|
||||
argumentCount == 0 ? io.Directory.current.absolute.path : arguments[0];
|
||||
var basePath = argumentCount == 0
|
||||
? io.Directory.current.absolute.path
|
||||
: arguments[0];
|
||||
var normalizedPath = path.canonicalize(path.normalize(basePath));
|
||||
return io.FileSystemEntity.isDirectorySync(normalizedPath)
|
||||
? io.Directory(normalizedPath)
|
||||
@@ -351,7 +368,9 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
}
|
||||
|
||||
void _mergeFixCounts(
|
||||
List<BulkFixDetail> oldFixes, List<BulkFixDetail> newFixes) {
|
||||
List<BulkFixDetail> oldFixes,
|
||||
List<BulkFixDetail> newFixes,
|
||||
) {
|
||||
var originalOldLength = oldFixes.length;
|
||||
newFixLoop:
|
||||
for (var newFix in newFixes) {
|
||||
@@ -399,16 +418,19 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
final bullet = log.ansi.bullet;
|
||||
|
||||
var modifiedFilePaths = detailsMap.keys.toList();
|
||||
modifiedFilePaths
|
||||
.sort((first, second) => relative(first).compareTo(relative(second)));
|
||||
modifiedFilePaths.sort(
|
||||
(first, second) => relative(first).compareTo(relative(second)),
|
||||
);
|
||||
for (var filePath in modifiedFilePaths) {
|
||||
var detail = detailsMap[filePath]!;
|
||||
log.stdout(relative(detail.path));
|
||||
final fixes = detail.fixes.toList();
|
||||
fixes.sort((a, b) => a.code.compareTo(b.code));
|
||||
for (var fix in fixes) {
|
||||
log.stdout(' ${fix.code} $bullet '
|
||||
'${fix.occurrences} ${_pluralFix(fix.occurrences)}');
|
||||
log.stdout(
|
||||
' ${fix.code} $bullet '
|
||||
'${fix.occurrences} ${_pluralFix(fix.occurrences)}',
|
||||
);
|
||||
}
|
||||
log.stdout('');
|
||||
}
|
||||
@@ -416,8 +438,12 @@ To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed
|
||||
|
||||
/// Report that the [actualCode] produced by applying fixes to the content of
|
||||
/// [filePath] did not match the [expectedCode].
|
||||
void _reportFailure(String filePath, String actualCode, String expectedCode,
|
||||
{required bool actualIsOriginal}) {
|
||||
void _reportFailure(
|
||||
String filePath,
|
||||
String actualCode,
|
||||
String expectedCode, {
|
||||
required bool actualIsOriginal,
|
||||
}) {
|
||||
log.stdout('Failed when applying fixes to $filePath');
|
||||
log.stdout('Expected:');
|
||||
log.stdout(expectedCode);
|
||||
@@ -443,7 +469,7 @@ class _FixRequestResult {
|
||||
String message;
|
||||
Map<String, BulkFix> details;
|
||||
_FixRequestResult({this.message = '', Map<String, BulkFix>? details})
|
||||
: details = details ?? {};
|
||||
: details = details ?? {};
|
||||
}
|
||||
|
||||
/// The result of running tests in a given directory.
|
||||
|
||||
@@ -22,7 +22,7 @@ class InfoCommand extends DartdevCommand {
|
||||
CommandCategory get commandCategory => CommandCategory.tools;
|
||||
|
||||
InfoCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
addSubcommand(_DumpCommand(verbose: verbose), isDefault: true);
|
||||
addSubcommand(_RecordPerformanceCommand(verbose: verbose));
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class _DumpCommand extends DartdevCommand {
|
||||
CommandCategory get commandCategory => CommandCategory.tools;
|
||||
|
||||
_DumpCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
argParser.addFlag(
|
||||
removeFilePathsFlag,
|
||||
help: 'Remove file paths in displayed information.',
|
||||
@@ -134,7 +134,7 @@ class _RecordPerformanceCommand extends DartdevCommand {
|
||||
CommandCategory get commandCategory => CommandCategory.tools;
|
||||
|
||||
_RecordPerformanceCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
PerfWitnessRecorderConfig.configureArgParser(argParser);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,16 +47,18 @@ You can specify three different values for the <package> argument:
|
||||
CommandCategory get commandCategory => CommandCategory.global;
|
||||
|
||||
InstallCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
argParser.addOption(
|
||||
gitPathOption,
|
||||
help: 'Path of git package in repository. '
|
||||
help:
|
||||
'Path of git package in repository. '
|
||||
'Only applies when using a git url for <package>.',
|
||||
);
|
||||
|
||||
argParser.addOption(
|
||||
gitRefOption,
|
||||
help: 'Git branch or commit to be retrieved. '
|
||||
help:
|
||||
'Git branch or commit to be retrieved. '
|
||||
'Only applies when using a git url for <package>.',
|
||||
);
|
||||
|
||||
@@ -69,7 +71,8 @@ You can specify three different values for the <package> argument:
|
||||
argParser.addOption(
|
||||
'hosted-url',
|
||||
abbr: 'u',
|
||||
help: 'A custom pub server URL for the package. '
|
||||
help:
|
||||
'A custom pub server URL for the package. '
|
||||
'Only applies when using a package name for <package>.',
|
||||
);
|
||||
}
|
||||
@@ -121,9 +124,7 @@ You can specify three different values for the <package> argument:
|
||||
versionConstraint = args.isEmpty ? 'any' : readArg();
|
||||
}
|
||||
if (args.isNotEmpty) {
|
||||
usageException(
|
||||
'Too many arguments, did not expect "${args.join(' ')}"',
|
||||
);
|
||||
usageException('Too many arguments, did not expect "${args.join(' ')}"');
|
||||
}
|
||||
return InstallCommandParsedArguments(
|
||||
source: argument,
|
||||
@@ -152,7 +153,8 @@ You can specify three different values for the <package> argument:
|
||||
return parsedArgs.source;
|
||||
case RemoteSourceKind.path:
|
||||
final pubspecFile = File.fromUri(
|
||||
Directory(parsedArgs.source).absolute.uri.resolve('pubspec.yaml'));
|
||||
Directory(parsedArgs.source).absolute.uri.resolve('pubspec.yaml'),
|
||||
);
|
||||
if (!await pubspecFile.exists()) {
|
||||
usageException('No pubspec found in ${pubspecFile.path}.');
|
||||
}
|
||||
@@ -175,8 +177,9 @@ You can specify three different values for the <package> argument:
|
||||
required String packageName,
|
||||
required Directory helperPackageDir,
|
||||
}) {
|
||||
final tempPubspec =
|
||||
File.fromUri(helperPackageDir.uri.resolve('pubspec.yaml'));
|
||||
final tempPubspec = File.fromUri(
|
||||
helperPackageDir.uri.resolve('pubspec.yaml'),
|
||||
);
|
||||
final helperPackagePubspec = PubspecYamlFileSyntax(
|
||||
name: _helperPackageName,
|
||||
environment: EnvironmentSyntax(
|
||||
@@ -185,23 +188,23 @@ You can specify three different values for the <package> argument:
|
||||
dependencies: {
|
||||
packageName: switch (parsedArgs.sourceKind) {
|
||||
RemoteSourceKind.git => GitDependencySourceSyntax(
|
||||
git: GitSyntax(
|
||||
url: parsedArgs.source,
|
||||
path$: parsedArgs.gitPath,
|
||||
ref: parsedArgs.gitRef,
|
||||
),
|
||||
git: GitSyntax(
|
||||
url: parsedArgs.source,
|
||||
path$: parsedArgs.gitPath,
|
||||
ref: parsedArgs.gitRef,
|
||||
),
|
||||
),
|
||||
RemoteSourceKind.hosted => HostedDependencySourceSyntax(
|
||||
hosted: parsedArgs.hostedUrl,
|
||||
version: parsedArgs.versionConstraint!,
|
||||
),
|
||||
hosted: parsedArgs.hostedUrl,
|
||||
version: parsedArgs.versionConstraint!,
|
||||
),
|
||||
RemoteSourceKind.path =>
|
||||
// Re-resolve dependencies for path activate, behave like it would work
|
||||
// for users of the package if the activate via hosted or git.
|
||||
PathDependencySourceSyntax(
|
||||
path$: Directory(parsedArgs.source).absolute.path,
|
||||
),
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
helperPackagePubspec.writeSync(tempPubspec);
|
||||
@@ -227,10 +230,12 @@ You can specify three different values for the <package> argument:
|
||||
|
||||
final errors = pubspecSyntax.validateExecutables();
|
||||
if (errors.isNotEmpty) {
|
||||
installException([
|
||||
'The pubspec.yaml contains the following errors:',
|
||||
...errors
|
||||
].join('\n'));
|
||||
installException(
|
||||
[
|
||||
'The pubspec.yaml contains the following errors:',
|
||||
...errors,
|
||||
].join('\n'),
|
||||
);
|
||||
}
|
||||
// This is a map of strings to string. Each key is the name of the command
|
||||
// that will be placed on the user's PATH. The value is the name of the
|
||||
@@ -243,16 +248,18 @@ You can specify three different values for the <package> argument:
|
||||
}
|
||||
if (executablesSyntax.isEmpty) {
|
||||
installException(
|
||||
'The pubspec.yaml executables section contained no executables.');
|
||||
'The pubspec.yaml executables section contained no executables.',
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
for (final executable in executablesSyntax.entries)
|
||||
(
|
||||
name: executable.key,
|
||||
sourceEntryPoint: sourcePackageRootDirectory.uri
|
||||
.resolve('bin/${executable.value ?? executable.key}.dart')
|
||||
)
|
||||
sourceEntryPoint: sourcePackageRootDirectory.uri.resolve(
|
||||
'bin/${executable.value ?? executable.key}.dart',
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -283,8 +290,9 @@ You can specify three different values for the <package> argument:
|
||||
}
|
||||
|
||||
void _uniinstallAllPackageVersions(String packageName) {
|
||||
final bundles =
|
||||
DartInstallDirectory().allAppBundlesSync(packageName: packageName);
|
||||
final bundles = DartInstallDirectory().allAppBundlesSync(
|
||||
packageName: packageName,
|
||||
);
|
||||
|
||||
try {
|
||||
for (final bundle in bundles) {
|
||||
@@ -300,8 +308,10 @@ You can specify three different values for the <package> argument:
|
||||
} on PathAccessException {
|
||||
installException('Deletion failed. The application might be in use.');
|
||||
} on PathNotFoundException {
|
||||
print('Bundle not found when uninstalling. '
|
||||
'Earlier installation may have failed.');
|
||||
print(
|
||||
'Bundle not found when uninstalling. '
|
||||
'Earlier installation may have failed.',
|
||||
);
|
||||
// Continue installing
|
||||
}
|
||||
}
|
||||
@@ -315,21 +325,23 @@ You can specify three different values for the <package> argument:
|
||||
final AppBundleDirectory outputDir;
|
||||
switch (parsedArgs.sourceKind) {
|
||||
case RemoteSourceKind.git:
|
||||
final resolvedGitRef = parsedArgs.gitRef ??
|
||||
final resolvedGitRef =
|
||||
parsedArgs.gitRef ??
|
||||
GitPackageDescriptionSyntax.fromJson(
|
||||
PubspecLockFile.loadSync(helperPackageLockFile)
|
||||
.packages![packageName]!
|
||||
.description
|
||||
.json,
|
||||
PubspecLockFile.loadSync(
|
||||
helperPackageLockFile,
|
||||
).packages![packageName]!.description.json,
|
||||
).resolvedRef;
|
||||
outputDir = DartInstallDirectory().gitAppBundle(
|
||||
packageName,
|
||||
resolvedGitRef,
|
||||
);
|
||||
case RemoteSourceKind.hosted:
|
||||
final packageGraphJson = PackageGraphFile.loadSync(File.fromUri(
|
||||
helperPackageDir.uri.resolve('.dart_tool/package_graph.json'),
|
||||
));
|
||||
final packageGraphJson = PackageGraphFile.loadSync(
|
||||
File.fromUri(
|
||||
helperPackageDir.uri.resolve('.dart_tool/package_graph.json'),
|
||||
),
|
||||
);
|
||||
final resolvedVersion = packageGraphJson.packages
|
||||
.firstWhere((e) => e.name == packageName)
|
||||
.version;
|
||||
@@ -344,10 +356,11 @@ You can specify three different values for the <package> argument:
|
||||
}
|
||||
|
||||
static Future<void> createAppBundleDirectory(
|
||||
AppBundleDirectory appBundleDirectory,
|
||||
Directory buildDirectory,
|
||||
File helperPackageLockFile,
|
||||
File sourcePackagePubspecFile) async {
|
||||
AppBundleDirectory appBundleDirectory,
|
||||
Directory buildDirectory,
|
||||
File helperPackageLockFile,
|
||||
File sourcePackagePubspecFile,
|
||||
) async {
|
||||
if (appBundleDirectory.directory.existsSync()) {
|
||||
try {
|
||||
appBundleDirectory.directory.deleteSync(recursive: true);
|
||||
@@ -359,10 +372,13 @@ You can specify three different values for the <package> argument:
|
||||
}
|
||||
}
|
||||
appBundleDirectory.directory.createSync(recursive: true);
|
||||
final bundleDirectory =
|
||||
Directory.fromUri(buildDirectory.uri.resolve('bundle/'));
|
||||
final bundleDirectory = Directory.fromUri(
|
||||
buildDirectory.uri.resolve('bundle/'),
|
||||
);
|
||||
await _renameSafe(
|
||||
bundleDirectory, appBundleDirectory.directory.uri.resolve('bundle/'));
|
||||
bundleDirectory,
|
||||
appBundleDirectory.directory.uri.resolve('bundle/'),
|
||||
);
|
||||
await helperPackageLockFile.copy(appBundleDirectory.pubspecLock.path);
|
||||
await sourcePackagePubspecFile.copy(appBundleDirectory.pubspec.path);
|
||||
}
|
||||
@@ -390,24 +406,27 @@ You can specify three different values for the <package> argument:
|
||||
} else if (child is Directory) {
|
||||
await _renameSafeCopyAndDelete(child, Uri.parse('$newChildPath/'));
|
||||
} else {
|
||||
await Link.fromUri(newChildPath)
|
||||
.create(await (child as Link).resolveSymbolicLinks());
|
||||
await Link.fromUri(
|
||||
newChildPath,
|
||||
).create(await (child as Link).resolveSymbolicLinks());
|
||||
}
|
||||
await child.delete(recursive: false);
|
||||
}
|
||||
}
|
||||
|
||||
void _installExecutablesOnPath(
|
||||
DartBuildExecutables executables,
|
||||
AppBundleDirectory appBundleDirectory,
|
||||
String packageName,
|
||||
InstallCommandParsedArguments parsedArgs) {
|
||||
DartBuildExecutables executables,
|
||||
AppBundleDirectory appBundleDirectory,
|
||||
String packageName,
|
||||
InstallCommandParsedArguments parsedArgs,
|
||||
) {
|
||||
final errors = <String>[];
|
||||
for (final executable in executables) {
|
||||
final executableName = executable.name;
|
||||
final executableFile = appBundleDirectory.executable(executableName);
|
||||
final executableOnPath =
|
||||
DartInstallDirectory().bin.executable(executableName);
|
||||
final executableOnPath = DartInstallDirectory().bin.executable(
|
||||
executableName,
|
||||
);
|
||||
var createLink = true;
|
||||
|
||||
if (executableOnPath.existsSync()) {
|
||||
@@ -467,14 +486,10 @@ You can specify three different values for the <package> argument:
|
||||
//
|
||||
// The "command" builtin is more reliable than the "which" executable. See
|
||||
// http://unix.stackexchange.com/questions/85249/why-not-use-which-what-to-use-then
|
||||
final result = Process.runSync(
|
||||
'command',
|
||||
[
|
||||
'-v',
|
||||
installed,
|
||||
],
|
||||
runInShell: true,
|
||||
);
|
||||
final result = Process.runSync('command', [
|
||||
'-v',
|
||||
installed,
|
||||
], runInShell: true);
|
||||
if (result.exitCode == 0) return;
|
||||
|
||||
var binDir = binDirPath;
|
||||
@@ -506,8 +521,9 @@ You can specify three different values for the <package> argument:
|
||||
final packageName = await _findPackageName(parsedArgs);
|
||||
return await inTempDir((tempDirectory) async {
|
||||
try {
|
||||
final helperPackageDirectory =
|
||||
Directory.fromUri(tempDirectory.uri.resolve('helperPackage/'));
|
||||
final helperPackageDirectory = Directory.fromUri(
|
||||
tempDirectory.uri.resolve('helperPackage/'),
|
||||
);
|
||||
helperPackageDirectory.createSync();
|
||||
createHelperPackagePubspec(
|
||||
helperPackageDir: helperPackageDirectory,
|
||||
@@ -516,29 +532,33 @@ You can specify three different values for the <package> argument:
|
||||
);
|
||||
await resolveHelperPackage(helperPackageDirectory);
|
||||
|
||||
final helperPackageLockFile =
|
||||
File.fromUri(helperPackageDirectory.uri.resolve('pubspec.lock'));
|
||||
final helperPackageConfigFile = File.fromUri(helperPackageDirectory.uri
|
||||
.resolve('.dart_tool/package_config.json'));
|
||||
final helperPackageLockFile = File.fromUri(
|
||||
helperPackageDirectory.uri.resolve('pubspec.lock'),
|
||||
);
|
||||
final helperPackageConfigFile = File.fromUri(
|
||||
helperPackageDirectory.uri.resolve('.dart_tool/package_config.json'),
|
||||
);
|
||||
|
||||
final sourcePackageRootDirectory = Directory(Uri.parse(
|
||||
PackageConfigFile.loadSync(helperPackageConfigFile)
|
||||
.packages
|
||||
.firstWhere((e) => e.name == packageName)
|
||||
.rootUri,
|
||||
).toFilePath())
|
||||
.ensureEndWithSeparator;
|
||||
final sourcePackageRootDirectory = Directory(
|
||||
Uri.parse(
|
||||
PackageConfigFile.loadSync(
|
||||
helperPackageConfigFile,
|
||||
).packages.firstWhere((e) => e.name == packageName).rootUri,
|
||||
).toFilePath(),
|
||||
).ensureEndWithSeparator;
|
||||
|
||||
final sourcePackagePubspecFile = File.fromUri(
|
||||
sourcePackageRootDirectory.uri.resolve('pubspec.yaml'));
|
||||
sourcePackageRootDirectory.uri.resolve('pubspec.yaml'),
|
||||
);
|
||||
|
||||
final executables = loadDeclaredExecutables(
|
||||
sourcePackagePubspecFile,
|
||||
sourcePackageRootDirectory,
|
||||
);
|
||||
|
||||
final buildDirectory =
|
||||
Directory.fromUri(tempDirectory.uri.resolve('build/'));
|
||||
final buildDirectory = Directory.fromUri(
|
||||
tempDirectory.uri.resolve('build/'),
|
||||
);
|
||||
|
||||
await doBuild(
|
||||
executables,
|
||||
@@ -587,7 +607,8 @@ You can specify three different values for the <package> argument:
|
||||
throw InstallException(message, exitCode: exitCode);
|
||||
|
||||
static Future<T> inTempDir<T>(
|
||||
Future<T> Function(Directory tempDirectory) fun) async {
|
||||
Future<T> Function(Directory tempDirectory) fun,
|
||||
) async {
|
||||
final tempDir = await Directory.systemTemp.createTemp();
|
||||
// Deal with Windows temp folder aliases.
|
||||
final tempDirResolved = Directory.fromUri(
|
||||
@@ -630,11 +651,7 @@ final class InstallCommandParsedArguments {
|
||||
});
|
||||
}
|
||||
|
||||
enum RemoteSourceKind {
|
||||
git,
|
||||
hosted,
|
||||
path;
|
||||
}
|
||||
enum RemoteSourceKind { git, hosted, path }
|
||||
|
||||
RemoteSourceKind _soureKindFromArgument(String argument) {
|
||||
if (_packageNameRegExp.hasMatch(argument)) {
|
||||
@@ -720,10 +737,7 @@ class InstallException implements Exception {
|
||||
final String message;
|
||||
final int? exitCode;
|
||||
|
||||
InstallException(
|
||||
this.message, {
|
||||
this.exitCode,
|
||||
});
|
||||
InstallException(this.message, {this.exitCode});
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
|
||||
@@ -17,7 +17,7 @@ class InstalledCommand extends DartdevCommand {
|
||||
CommandCategory get commandCategory => CommandCategory.global;
|
||||
|
||||
InstalledCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
: super(cmdName, cmdDescription, verbose) {
|
||||
argParser.addFlag(
|
||||
'all',
|
||||
abbr: 'a',
|
||||
@@ -52,8 +52,10 @@ on `PATH` are non-active.''',
|
||||
final lockFile = appBundleDir.pubspecLock;
|
||||
final pubspecLock = PubspecLockFile.loadSync(lockFile);
|
||||
final lockInfo = pubspecLock.packages!.entries
|
||||
.where((entry) =>
|
||||
entry.value.dependency == DependencyTypeSyntax.directMain)
|
||||
.where(
|
||||
(entry) =>
|
||||
entry.value.dependency == DependencyTypeSyntax.directMain,
|
||||
)
|
||||
.single
|
||||
.value;
|
||||
final binaries = appBundleDir.executablesSync;
|
||||
@@ -72,17 +74,19 @@ on `PATH` are non-active.''',
|
||||
}
|
||||
}
|
||||
final lastModified = lockFile.lastModifiedSync();
|
||||
result.add(InstalledPackage(
|
||||
name: packageName,
|
||||
appBundle: appBundleDir.directory,
|
||||
installed: switch ((foundBinary, missingBinary)) {
|
||||
(_, false) => Installed.fully,
|
||||
(true, true) => Installed.partial,
|
||||
(false, true) => Installed.not,
|
||||
},
|
||||
lockInfo: lockInfo,
|
||||
lastModified: lastModified,
|
||||
));
|
||||
result.add(
|
||||
InstalledPackage(
|
||||
name: packageName,
|
||||
appBundle: appBundleDir.directory,
|
||||
installed: switch ((foundBinary, missingBinary)) {
|
||||
(_, false) => Installed.fully,
|
||||
(true, true) => Installed.partial,
|
||||
(false, true) => Installed.not,
|
||||
},
|
||||
lockInfo: lockInfo,
|
||||
lastModified: lastModified,
|
||||
),
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -108,16 +112,18 @@ class InstalledPackage {
|
||||
var result = '$name ${lockInfo.version}';
|
||||
switch (lockInfo.source) {
|
||||
case PackageSourceSyntax.git:
|
||||
final description =
|
||||
GitPackageDescriptionSyntax.fromJson(lockInfo.description.json);
|
||||
final description = GitPackageDescriptionSyntax.fromJson(
|
||||
lockInfo.description.json,
|
||||
);
|
||||
final url = description.url;
|
||||
final resolvedRef = description.resolvedRef.substring(0, 8);
|
||||
result += ' from Git repository "$url" at "$resolvedRef"';
|
||||
case PackageSourceSyntax.hosted:
|
||||
break;
|
||||
case PackageSourceSyntax.path$:
|
||||
final description =
|
||||
PathPackageDescriptionSyntax.fromJson(lockInfo.description.json);
|
||||
final description = PathPackageDescriptionSyntax.fromJson(
|
||||
lockInfo.description.json,
|
||||
);
|
||||
final path = description.path$;
|
||||
result += ' from "$path" at $lastModified';
|
||||
default:
|
||||
@@ -135,8 +141,4 @@ class InstalledPackage {
|
||||
}
|
||||
}
|
||||
|
||||
enum Installed {
|
||||
fully,
|
||||
partial,
|
||||
not;
|
||||
}
|
||||
enum Installed { fully, partial, not }
|
||||
|
||||
@@ -30,7 +30,7 @@ For more information about the server's capabilities and configuration, see:
|
||||
https://github.com/dart-lang/sdk/tree/main/pkg/analysis_server''';
|
||||
|
||||
LanguageServerCommand({bool verbose = false})
|
||||
: super(commandName, commandDescription, verbose, hidden: !verbose);
|
||||
: super(commandName, commandDescription, verbose, hidden: !verbose);
|
||||
|
||||
@override
|
||||
ArgParser createArgParser() {
|
||||
@@ -38,10 +38,12 @@ For more information about the server's capabilities and configuration, see:
|
||||
usageLineLength: dartdevUsageLineLength,
|
||||
includeHelpFlag: false,
|
||||
defaultToLsp: true,
|
||||
)..addFlag(useAotSnapshotFlag,
|
||||
help: 'Use the AOT analysis server snapshot',
|
||||
defaultsTo: true,
|
||||
hide: true);
|
||||
)..addFlag(
|
||||
useAotSnapshotFlag,
|
||||
help: 'Use the AOT analysis server snapshot',
|
||||
defaultsTo: true,
|
||||
hide: true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -70,11 +72,7 @@ For more information about the server's capabilities and configuration, see:
|
||||
script = sdk.analysisServerSnapshot;
|
||||
useExec = true;
|
||||
}
|
||||
VmInteropHandler.run(
|
||||
script,
|
||||
args,
|
||||
useExecProcess: useExec,
|
||||
);
|
||||
VmInteropHandler.run(script, args, useExecProcess: useExec);
|
||||
return 0;
|
||||
} catch (e, st) {
|
||||
log.stderr('Error: launching language analysis server failed');
|
||||
|
||||
@@ -56,9 +56,7 @@ class RunCommand extends DartdevCommand {
|
||||
bool verbose = false,
|
||||
this.nativeAssetsExperimentEnabled = false,
|
||||
this.dataAssetsExperimentEnabled = false,
|
||||
}) : super(
|
||||
cmdName,
|
||||
'''Run a Dart program from a file or a local package.
|
||||
}) : super(cmdName, '''Run a Dart program from a file or a local package.
|
||||
|
||||
Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
|
||||
@@ -68,15 +66,14 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
<local-package>
|
||||
An executable from a local package dependency, in the format <package>[:<executable>].
|
||||
For example, `test:test` runs the `test` executable from the `test` package.
|
||||
If the executable is not specified, the package name is used.''',
|
||||
verbose,
|
||||
) {
|
||||
If the executable is not specified, the package name is used.''', verbose) {
|
||||
argParser
|
||||
..addFlag(
|
||||
residentOption,
|
||||
abbr: 'r',
|
||||
negatable: false,
|
||||
help: 'Enable faster startup times by using a resident frontend '
|
||||
help:
|
||||
'Enable faster startup times by using a resident frontend '
|
||||
'compiler for compilation.\n'
|
||||
'If --$residentCompilerInfoFileOption is provided in conjunction with '
|
||||
'this flag, the specified info file will be used, otherwise the '
|
||||
@@ -89,7 +86,8 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
..addFlag(
|
||||
quietOption,
|
||||
hide: !verbose,
|
||||
help: 'Disable the printing of messages about the resident compiler '
|
||||
help:
|
||||
'Disable the printing of messages about the resident compiler '
|
||||
'starting up / shutting down.',
|
||||
)
|
||||
..addOption(
|
||||
@@ -107,35 +105,29 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
// the list of flags in Options::ProcessVMDebuggingOptions in
|
||||
// runtime/bin/main_options.cc. Failure to do so will result in those VM
|
||||
// options being ignored.
|
||||
argParser.addSeparator(
|
||||
'Debugging options:',
|
||||
);
|
||||
argParser.addSeparator('Debugging options:');
|
||||
argParser
|
||||
..addOption(
|
||||
'observe',
|
||||
help: 'The observe flag is a convenience flag used to run a program '
|
||||
help:
|
||||
'The observe flag is a convenience flag used to run a program '
|
||||
'with a set of common options useful for debugging. '
|
||||
'Run `dart help -v run` for details.',
|
||||
valueHelp: '[<port>[/<bind-address>]]',
|
||||
)
|
||||
..addFlag(
|
||||
'enable-asserts',
|
||||
help: 'Enable assert statements.',
|
||||
)
|
||||
..addOption(
|
||||
'launch-dds',
|
||||
hide: true,
|
||||
help: 'Launch DDS.',
|
||||
);
|
||||
..addFlag('enable-asserts', help: 'Enable assert statements.')
|
||||
..addOption('launch-dds', hide: true, help: 'Launch DDS.');
|
||||
|
||||
if (verbose) {
|
||||
argParser.addSeparator(
|
||||
verbose ? 'Options implied by --observe are currently:' : '');
|
||||
verbose ? 'Options implied by --observe are currently:' : '',
|
||||
);
|
||||
}
|
||||
argParser
|
||||
..addOption(
|
||||
'enable-vm-service',
|
||||
help: 'Enables the VM service and listens on the specified port for '
|
||||
help:
|
||||
'Enables the VM service and listens on the specified port for '
|
||||
'connections (default port number is 8181, default bind address '
|
||||
'is localhost).',
|
||||
valueHelp: '[<port>[/<bind-address>]]',
|
||||
@@ -143,32 +135,37 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
)
|
||||
..addFlag(
|
||||
'serve-devtools',
|
||||
help: 'Serves an instance of the Dart DevTools debugger and profiler '
|
||||
help:
|
||||
'Serves an instance of the Dart DevTools debugger and profiler '
|
||||
'via the VM service at <vm-service-uri>/devtools.',
|
||||
defaultsTo: true,
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag(
|
||||
'pause-isolates-on-exit',
|
||||
help: 'Pause isolates on exit when '
|
||||
help:
|
||||
'Pause isolates on exit when '
|
||||
'running with --enable-vm-service.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag(
|
||||
'pause-isolates-on-unhandled-exceptions',
|
||||
help: 'Pause isolates when an unhandled exception is encountered '
|
||||
help:
|
||||
'Pause isolates when an unhandled exception is encountered '
|
||||
'when running with --enable-vm-service.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag(
|
||||
'warn-on-pause-with-no-debugger',
|
||||
help: 'Print a warning when an isolate pauses with no attached debugger'
|
||||
help:
|
||||
'Print a warning when an isolate pauses with no attached debugger'
|
||||
' when running with --enable-vm-service.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addOption(
|
||||
'timeline-streams',
|
||||
help: 'Enables recording for specific timeline streams.\n'
|
||||
help:
|
||||
'Enables recording for specific timeline streams.\n'
|
||||
'Valid streams include: all, API, Compiler, CompilerVerbose, Dart, '
|
||||
'Debugger, Embedder, GC, Isolate, Microtask, VM.\n'
|
||||
'Defaults to "Compiler, Dart, GC, Microtask" when --observe is '
|
||||
@@ -183,13 +180,15 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
argParser
|
||||
..addFlag(
|
||||
'pause-isolates-on-start',
|
||||
help: 'Pause isolates on start when '
|
||||
help:
|
||||
'Pause isolates on start when '
|
||||
'running with --enable-vm-service.',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addOption(
|
||||
'timeline-recorder',
|
||||
help: 'Selects the timeline recorder to use.\n'
|
||||
help:
|
||||
'Selects the timeline recorder to use.\n'
|
||||
'Valid recorders include: none, ring, endless, startup, '
|
||||
'systrace, file, callback, perfettofile.\n'
|
||||
'Defaults to ring.',
|
||||
@@ -200,7 +199,8 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'profile-microtasks',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
help: 'Record information about each microtask. Information about '
|
||||
help:
|
||||
'Record information about each microtask. Information about '
|
||||
'completed microtasks will be written to the "Microtask" '
|
||||
'timeline stream.',
|
||||
)
|
||||
@@ -208,7 +208,8 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'profile-startup',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
help: 'Make the profiler discard new samples once the profiler '
|
||||
help:
|
||||
'Make the profiler discard new samples once the profiler '
|
||||
'sample buffer is full. When this flag is not set, the '
|
||||
'profiler sample buffer is used as a ring buffer, meaning that '
|
||||
'once it is full, new samples start overwriting the oldest '
|
||||
@@ -239,7 +240,8 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'disable-service-auth-codes',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
help: 'Disables the requirement for an authentication code to '
|
||||
help:
|
||||
'Disables the requirement for an authentication code to '
|
||||
'communicate with the VM service. Authentication codes help '
|
||||
'protect against CSRF attacks, so it is not recommended to '
|
||||
'disable them unless behind a firewall on a secure device.',
|
||||
@@ -248,7 +250,8 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'enable-service-port-fallback',
|
||||
hide: !verbose,
|
||||
negatable: false,
|
||||
help: 'When the VM service is told to bind to a particular port, '
|
||||
help:
|
||||
'When the VM service is told to bind to a particular port, '
|
||||
'fallback to 0 if it fails to bind instead of failing to '
|
||||
'start.',
|
||||
)
|
||||
@@ -256,21 +259,24 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'namespace',
|
||||
hide: !verbose,
|
||||
valueHelp: 'path',
|
||||
help: 'The path to a directory that dart:io calls will treat as the '
|
||||
help:
|
||||
'The path to a directory that dart:io calls will treat as the '
|
||||
'root of the filesystem.',
|
||||
)
|
||||
..addOption(
|
||||
'root-certs-file',
|
||||
hide: !verbose,
|
||||
valueHelp: 'path',
|
||||
help: 'The path to a file containing the trusted root certificates '
|
||||
help:
|
||||
'The path to a file containing the trusted root certificates '
|
||||
'to use for secure socket connections.',
|
||||
)
|
||||
..addOption(
|
||||
'root-certs-cache',
|
||||
hide: !verbose,
|
||||
valueHelp: 'path',
|
||||
help: 'The path to a cache directory containing the trusted root '
|
||||
help:
|
||||
'The path to a cache directory containing the trusted root '
|
||||
'certificates to use for secure socket connections.',
|
||||
)
|
||||
..addFlag(
|
||||
@@ -283,39 +289,44 @@ Usage: dart [vm-options] run [arguments] <dart-file>|<local-package> [args]
|
||||
'packages',
|
||||
hide: !verbose,
|
||||
valueHelp: 'path',
|
||||
help: 'The path to the package resolution configuration file, which '
|
||||
help:
|
||||
'The path to the package resolution configuration file, which '
|
||||
'supplies a mapping of package names\ninto paths.',
|
||||
)
|
||||
..addOption(
|
||||
'write-service-info',
|
||||
help: 'Outputs information necessary to connect to the VM service to '
|
||||
help:
|
||||
'Outputs information necessary to connect to the VM service to '
|
||||
'specified file in JSON format. Useful for clients which are '
|
||||
'unable to listen to stdout for the Dart VM service listening '
|
||||
'message.',
|
||||
valueHelp: 'file',
|
||||
hide: !verbose,
|
||||
)
|
||||
..addFlag('dds',
|
||||
hide: !verbose,
|
||||
help: 'Use the Dart Development Service (DDS) for enhanced debugging '
|
||||
'functionality. Note: Disabling DDS may break some '
|
||||
'functionality in IDEs and other tooling.',
|
||||
defaultsTo: true)
|
||||
..addFlag('serve-observatory',
|
||||
hide: !verbose,
|
||||
help: 'Enable hosting Observatory through the VM Service.',
|
||||
defaultsTo: true)
|
||||
..addFlag(
|
||||
'dds',
|
||||
hide: !verbose,
|
||||
help:
|
||||
'Use the Dart Development Service (DDS) for enhanced debugging '
|
||||
'functionality. Note: Disabling DDS may break some '
|
||||
'functionality in IDEs and other tooling.',
|
||||
defaultsTo: true,
|
||||
)
|
||||
..addFlag(
|
||||
'serve-observatory',
|
||||
hide: !verbose,
|
||||
help: 'Enable hosting Observatory through the VM Service.',
|
||||
defaultsTo: true,
|
||||
)
|
||||
..addFlag(
|
||||
'print-dtd',
|
||||
hide: !verbose,
|
||||
help: 'Prints connection details for the Dart Tooling Daemon (DTD).'
|
||||
help:
|
||||
'Prints connection details for the Dart Tooling Daemon (DTD).'
|
||||
'Useful for Dart DevTools extension authors working with DTD in the '
|
||||
'extension development environment.',
|
||||
)
|
||||
..addFlag(
|
||||
'debug-dds',
|
||||
hide: true,
|
||||
)
|
||||
..addFlag('debug-dds', hide: true)
|
||||
..addExperimentalFlags(verbose: verbose)
|
||||
..addFlag(
|
||||
'enable-experiment-remote-run',
|
||||
@@ -352,13 +363,15 @@ Enables running executables from remote packages.
|
||||
..addOption(
|
||||
hide: !verbose,
|
||||
gitPathOption,
|
||||
help: 'Path of git package in repository. '
|
||||
help:
|
||||
'Path of git package in repository. '
|
||||
'Only applies when using a git url for <remote-executable>.',
|
||||
)
|
||||
..addOption(
|
||||
hide: !verbose,
|
||||
gitRefOption,
|
||||
help: 'Git branch or commit to be retrieved. '
|
||||
help:
|
||||
'Git branch or commit to be retrieved. '
|
||||
'Only applies when using a git url for <remote-executable>.',
|
||||
);
|
||||
}
|
||||
@@ -378,7 +391,7 @@ Enables running executables from remote packages.
|
||||
/// retried. This method returns the compiled kernel file if compilation
|
||||
/// succeeds, otherwise it returns null.
|
||||
static Future<DartExecutableWithPackageConfig?>
|
||||
_compileToKernelUsingResidentCompiler({
|
||||
_compileToKernelUsingResidentCompiler({
|
||||
required DartExecutableWithPackageConfig executable,
|
||||
required File residentCompilerInfoFile,
|
||||
required ArgResults args,
|
||||
@@ -387,9 +400,11 @@ Enables running executables from remote packages.
|
||||
String? nativeAssetsYaml,
|
||||
}) async {
|
||||
final executableFile = File(executable.executable);
|
||||
assert(!await isFileKernelFile(executableFile) &&
|
||||
!await isFileAppJitSnapshot(executableFile) &&
|
||||
!await isFileAotSnapshot(executableFile));
|
||||
assert(
|
||||
!await isFileKernelFile(executableFile) &&
|
||||
!await isFileAppJitSnapshot(executableFile) &&
|
||||
!await isFileAotSnapshot(executableFile),
|
||||
);
|
||||
|
||||
try {
|
||||
return await generateKernel(
|
||||
@@ -434,7 +449,8 @@ Enables running executables from remote packages.
|
||||
}
|
||||
} else {
|
||||
log.stderr(
|
||||
'${ansi.yellow}Failed to build ${executable.executable}:${ansi.none}');
|
||||
'${ansi.yellow}Failed to build ${executable.executable}:${ansi.none}',
|
||||
);
|
||||
log.stderr(e.message);
|
||||
return null;
|
||||
}
|
||||
@@ -466,7 +482,7 @@ Enables running executables from remote packages.
|
||||
) async {
|
||||
final String? residentCompilerInfoFileArg =
|
||||
args[CompilationServerCommand.residentCompilerInfoFileFlag] ??
|
||||
args[CompilationServerCommand.legacyResidentServerInfoFileFlag];
|
||||
args[CompilationServerCommand.legacyResidentServerInfoFileFlag];
|
||||
final useResidentCompiler = args.wasParsed(residentOption);
|
||||
if (residentCompilerInfoFileArg != null && !useResidentCompiler) {
|
||||
log.stderr(
|
||||
@@ -494,18 +510,21 @@ Enables running executables from remote packages.
|
||||
Directory.current.uri,
|
||||
);
|
||||
if (packageConfigUri != null) {
|
||||
final packageConfig =
|
||||
await DartNativeAssetsBuilder.loadPackageConfig(packageConfigUri);
|
||||
final packageConfig = await DartNativeAssetsBuilder.loadPackageConfig(
|
||||
packageConfigUri,
|
||||
);
|
||||
if (packageConfig == null) {
|
||||
return compileErrorExitCode;
|
||||
}
|
||||
final runPackageName = getPackageForCommand(mainCommand) ??
|
||||
final runPackageName =
|
||||
getPackageForCommand(mainCommand) ??
|
||||
await DartNativeAssetsBuilder.findRootPackageName(
|
||||
Directory.current.uri,
|
||||
);
|
||||
if (runPackageName != null) {
|
||||
final pubspecUri = await DartNativeAssetsBuilder.findWorkspacePubspec(
|
||||
packageConfigUri);
|
||||
packageConfigUri,
|
||||
);
|
||||
final builder = DartNativeAssetsBuilder(
|
||||
pubspecUri: pubspecUri,
|
||||
packageConfigUri: packageConfigUri,
|
||||
@@ -624,8 +643,11 @@ Enables running executables from remote packages.
|
||||
if (argument.startsWith('git@')) {
|
||||
return RemoteSourceKind.git;
|
||||
}
|
||||
final potentialUri =
|
||||
argument.split(_colonButNoSlashes).first.split('@').first;
|
||||
final potentialUri = argument
|
||||
.split(_colonButNoSlashes)
|
||||
.first
|
||||
.split('@')
|
||||
.first;
|
||||
final endsWithDotGitRegex = RegExp(r'\.git[/\\]?$');
|
||||
if (endsWithDotGitRegex.hasMatch(potentialUri)) {
|
||||
return RemoteSourceKind.git;
|
||||
@@ -702,10 +724,12 @@ Enables running executables from remote packages.
|
||||
}
|
||||
case RemoteSourceKind.hosted:
|
||||
final parsedUri = Uri.parse(
|
||||
mainCommand.split('@').first.split(_colonButNoSlashes).first);
|
||||
mainCommand.split('@').first.split(_colonButNoSlashes).first,
|
||||
);
|
||||
hostedUrl = '${parsedUri.scheme}://${parsedUri.host}';
|
||||
source = parsedUri.path.replaceFirst('/', '');
|
||||
versionConstraint = mainCommand
|
||||
versionConstraint =
|
||||
mainCommand
|
||||
.split('@')
|
||||
.lastButNotFirstOrNull
|
||||
?.split(_colonButNoSlashes)
|
||||
@@ -765,8 +789,9 @@ Enables running executables from remote packages.
|
||||
try {
|
||||
// Create a helper package for running a pub-resolve and pulling in the
|
||||
// wanted package and its dependencies.
|
||||
final helperPackageDirectory =
|
||||
Directory.fromUri(tempDirectory.uri.resolve('helperPackage/'));
|
||||
final helperPackageDirectory = Directory.fromUri(
|
||||
tempDirectory.uri.resolve('helperPackage/'),
|
||||
);
|
||||
helperPackageDirectory.createSync();
|
||||
InstallCommand.createHelperPackagePubspec(
|
||||
helperPackageDir: helperPackageDirectory,
|
||||
@@ -774,8 +799,9 @@ Enables running executables from remote packages.
|
||||
parsedArgs: parsedArgs,
|
||||
);
|
||||
await InstallCommand.resolveHelperPackage(helperPackageDirectory);
|
||||
final helperPackageLockFile =
|
||||
File.fromUri(helperPackageDirectory.uri.resolve('pubspec.lock'));
|
||||
final helperPackageLockFile = File.fromUri(
|
||||
helperPackageDirectory.uri.resolve('pubspec.lock'),
|
||||
);
|
||||
|
||||
final appBundleDirectory = InstallCommand.selectAppBundleDirectory(
|
||||
parsedArgs,
|
||||
@@ -785,30 +811,35 @@ Enables running executables from remote packages.
|
||||
);
|
||||
|
||||
// If the pubspec lock file changed, re-build the executable.
|
||||
if (!appBundleDirectory
|
||||
.pubspecLockIsIdenticalTo(helperPackageLockFile)) {
|
||||
final helperPackageConfigFile = File.fromUri(helperPackageDirectory
|
||||
.uri
|
||||
.resolve('.dart_tool/package_config.json'));
|
||||
if (!appBundleDirectory.pubspecLockIsIdenticalTo(
|
||||
helperPackageLockFile,
|
||||
)) {
|
||||
final helperPackageConfigFile = File.fromUri(
|
||||
helperPackageDirectory.uri.resolve(
|
||||
'.dart_tool/package_config.json',
|
||||
),
|
||||
);
|
||||
|
||||
final sourcePackageRootDirectory = Directory(Uri.parse(
|
||||
PackageConfigFile.loadSync(helperPackageConfigFile)
|
||||
.packages
|
||||
.firstWhere((e) => e.name == packageName)
|
||||
.rootUri,
|
||||
).toFilePath())
|
||||
.ensureEndWithSeparator;
|
||||
final sourcePackageRootDirectory = Directory(
|
||||
Uri.parse(
|
||||
PackageConfigFile.loadSync(
|
||||
helperPackageConfigFile,
|
||||
).packages.firstWhere((e) => e.name == packageName).rootUri,
|
||||
).toFilePath(),
|
||||
).ensureEndWithSeparator;
|
||||
|
||||
final sourcePackagePubspecFile = File.fromUri(
|
||||
sourcePackageRootDirectory.uri.resolve('pubspec.yaml'));
|
||||
sourcePackageRootDirectory.uri.resolve('pubspec.yaml'),
|
||||
);
|
||||
|
||||
final executables = InstallCommand.loadDeclaredExecutables(
|
||||
sourcePackagePubspecFile,
|
||||
sourcePackageRootDirectory,
|
||||
);
|
||||
|
||||
final buildDirectory =
|
||||
Directory.fromUri(tempDirectory.uri.resolve('build/'));
|
||||
final buildDirectory = Directory.fromUri(
|
||||
tempDirectory.uri.resolve('build/'),
|
||||
);
|
||||
final verbosity = args.option('verbosity')!;
|
||||
await InstallCommand.doBuild(
|
||||
executables,
|
||||
@@ -827,14 +858,17 @@ Enables running executables from remote packages.
|
||||
);
|
||||
}
|
||||
|
||||
final mainCommandRemainder =
|
||||
mainCommand.substring(parsedArgs.source.length);
|
||||
final executable = mainCommandRemainder
|
||||
final mainCommandRemainder = mainCommand.substring(
|
||||
parsedArgs.source.length,
|
||||
);
|
||||
final executable =
|
||||
mainCommandRemainder
|
||||
.split(_colonButNoSlashes)
|
||||
.lastButNotFirstOrNull ??
|
||||
packageName;
|
||||
final executableUri =
|
||||
appBundleDirectory.directory.uri.resolve('bundle/bin/$executable');
|
||||
final executableUri = appBundleDirectory.directory.uri.resolve(
|
||||
'bundle/bin/$executable',
|
||||
);
|
||||
final arguments = args.rest.skip(1).toList();
|
||||
|
||||
// The app-bundle contains executables (not AOT snapshots) to make it
|
||||
|
||||
@@ -23,10 +23,10 @@ class TestCommand extends DartdevCommand {
|
||||
final bool nativeAssetsExperimentEnabled;
|
||||
final bool dataAssetsExperimentEnabled;
|
||||
|
||||
TestCommand(
|
||||
{this.nativeAssetsExperimentEnabled = false,
|
||||
this.dataAssetsExperimentEnabled = false})
|
||||
: super(cmdName, 'Run tests for a project.', false);
|
||||
TestCommand({
|
||||
this.nativeAssetsExperimentEnabled = false,
|
||||
this.dataAssetsExperimentEnabled = false,
|
||||
}) : super(cmdName, 'Run tests for a project.', false);
|
||||
|
||||
// This argument parser is here solely to ensure that VM specific flags are
|
||||
// provided before any command and to provide a more consistent help message
|
||||
@@ -58,8 +58,9 @@ Run "${runner!.executableName} help" to see global options.''');
|
||||
Directory.current.uri,
|
||||
);
|
||||
if (packageConfigUri != null) {
|
||||
final packageConfig =
|
||||
await DartNativeAssetsBuilder.loadPackageConfig(packageConfigUri);
|
||||
final packageConfig = await DartNativeAssetsBuilder.loadPackageConfig(
|
||||
packageConfigUri,
|
||||
);
|
||||
if (packageConfig == null) {
|
||||
return DartdevCommand.errorExitCode;
|
||||
}
|
||||
@@ -68,7 +69,8 @@ Run "${runner!.executableName} help" to see global options.''');
|
||||
);
|
||||
if (runPackageName != null) {
|
||||
final pubspecUri = await DartNativeAssetsBuilder.findWorkspacePubspec(
|
||||
packageConfigUri);
|
||||
packageConfigUri,
|
||||
);
|
||||
final builder = DartNativeAssetsBuilder(
|
||||
pubspecUri: pubspecUri,
|
||||
packageConfigUri: packageConfigUri,
|
||||
@@ -94,11 +96,13 @@ Run "${runner!.executableName} help" to see global options.''');
|
||||
// TODO(https://github.com/dart-lang/sdk/issues/60489): Add a way to
|
||||
// package:test to explicitly provide the native_assets.yaml path
|
||||
// instead of copying to the workspace .dart_tool.
|
||||
final expectedPackageTestLocation =
|
||||
packageConfigUri.resolve('native_assets.yaml');
|
||||
final expectedPackageTestLocation = packageConfigUri.resolve(
|
||||
'native_assets.yaml',
|
||||
);
|
||||
if (expectedPackageTestLocation != assetsYamlFileUri) {
|
||||
await File.fromUri(assetsYamlFileUri)
|
||||
.copy(expectedPackageTestLocation.toFilePath());
|
||||
await File.fromUri(
|
||||
assetsYamlFileUri,
|
||||
).copy(expectedPackageTestLocation.toFilePath());
|
||||
}
|
||||
nativeAssets = expectedPackageTestLocation.toFilePath();
|
||||
}
|
||||
@@ -106,15 +110,20 @@ Run "${runner!.executableName} help" to see global options.''');
|
||||
}
|
||||
|
||||
try {
|
||||
final testExecutable = await getExecutableForCommand('test:test',
|
||||
nativeAssets: nativeAssets);
|
||||
final testExecutable = await getExecutableForCommand(
|
||||
'test:test',
|
||||
nativeAssets: nativeAssets,
|
||||
);
|
||||
final argsRestNoExperimentOrSuppressAnalytics = args.rest
|
||||
.where((e) =>
|
||||
!e.startsWith('--$experimentFlagName=') &&
|
||||
e != '--suppress-analytics')
|
||||
.where(
|
||||
(e) =>
|
||||
!e.startsWith('--$experimentFlagName=') &&
|
||||
e != '--suppress-analytics',
|
||||
)
|
||||
.toList();
|
||||
log.trace(
|
||||
'dart $testExecutable ${argsRestNoExperimentOrSuppressAnalytics.join(' ')}');
|
||||
'dart $testExecutable ${argsRestNoExperimentOrSuppressAnalytics.join(' ')}',
|
||||
);
|
||||
VmInteropHandler.run(
|
||||
testExecutable.executable,
|
||||
argsRestNoExperimentOrSuppressAnalytics,
|
||||
@@ -137,7 +146,8 @@ Run "${runner!.executableName} help" to see global options.''');
|
||||
}
|
||||
} else {
|
||||
print(
|
||||
'No pubspec.yaml file found - run this command in your project folder.');
|
||||
'No pubspec.yaml file found - run this command in your project folder.',
|
||||
);
|
||||
}
|
||||
if (args.rest.contains('-h') || args.rest.contains('--help')) {
|
||||
print('');
|
||||
|
||||
@@ -16,12 +16,7 @@ class ToolingDaemonCommand extends DartdevCommand {
|
||||
static const String commandDescription = "Start Dart's tooling daemon.";
|
||||
|
||||
ToolingDaemonCommand({bool verbose = false})
|
||||
: super(
|
||||
commandName,
|
||||
commandDescription,
|
||||
verbose,
|
||||
hidden: !verbose,
|
||||
) {
|
||||
: super(commandName, commandDescription, verbose, hidden: !verbose) {
|
||||
dtd.DartToolingDaemonOptions.populateArgOptions(
|
||||
argParser,
|
||||
verbose: verbose,
|
||||
@@ -36,8 +31,10 @@ class ToolingDaemonCommand extends DartdevCommand {
|
||||
var snapshot = sdk.dtdAotSnapshot;
|
||||
final args = argResults!.arguments;
|
||||
if (!checkArtifactExists(sdk.dtdAotSnapshot, logError: false)) {
|
||||
log.stderr('Error: launching dart tooling daemon failed : '
|
||||
'Unable to find snapshot for the tooling daemon');
|
||||
log.stderr(
|
||||
'Error: launching dart tooling daemon failed : '
|
||||
'Unable to find snapshot for the tooling daemon',
|
||||
);
|
||||
return 255;
|
||||
}
|
||||
try {
|
||||
@@ -45,7 +42,7 @@ class ToolingDaemonCommand extends DartdevCommand {
|
||||
snapshot,
|
||||
args,
|
||||
packageConfigOverride: null,
|
||||
useExecProcess : false,
|
||||
useExecProcess: false,
|
||||
);
|
||||
return 0;
|
||||
} catch (e, st) {
|
||||
|
||||
@@ -24,7 +24,7 @@ Completely deletes all installed versions of <package> and all executables from
|
||||
CommandCategory get commandCategory => CommandCategory.global;
|
||||
|
||||
UninstallCommand({bool verbose = false})
|
||||
: super(cmdName, cmdDescription, verbose);
|
||||
: super(cmdName, cmdDescription, verbose);
|
||||
|
||||
@override
|
||||
Future<int> run() async {
|
||||
@@ -38,8 +38,9 @@ Completely deletes all installed versions of <package> and all executables from
|
||||
}
|
||||
final package = args.single;
|
||||
|
||||
final bundles =
|
||||
DartInstallDirectory().allAppBundlesSync(packageName: package);
|
||||
final bundles = DartInstallDirectory().allAppBundlesSync(
|
||||
packageName: package,
|
||||
);
|
||||
if (bundles.isEmpty) {
|
||||
print('Did not find any packages named "$package".');
|
||||
return 255;
|
||||
|
||||
@@ -36,8 +36,12 @@ abstract class DartdevCommand extends Command<int> {
|
||||
@override
|
||||
final bool hidden;
|
||||
|
||||
DartdevCommand(this._name, this._description, this._verbose,
|
||||
{this.hidden = false}) {
|
||||
DartdevCommand(
|
||||
this._name,
|
||||
this._description,
|
||||
this._verbose, {
|
||||
this.hidden = false,
|
||||
}) {
|
||||
flagContributor?.call(argParser, _name);
|
||||
}
|
||||
|
||||
@@ -133,7 +137,7 @@ Future<int> runProcess(
|
||||
final (_, _, exitCode) = await (
|
||||
forward(process.stdout, false),
|
||||
forward(process.stderr, true),
|
||||
process.exitCode
|
||||
process.exitCode,
|
||||
).wait;
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,8 @@ class DDSRunner {
|
||||
required bool debugDds,
|
||||
required bool enableServicePortFallback,
|
||||
}) async {
|
||||
void printError(String details) => stderr.writeln(
|
||||
'Could not start the VM service:\n$details',
|
||||
);
|
||||
void printError(String details) =>
|
||||
stderr.writeln('Could not start the VM service:\n$details');
|
||||
|
||||
final sdkDir = dirname(sdk.dart);
|
||||
final fullSdk = sdkDir.endsWith('bin');
|
||||
@@ -40,21 +39,17 @@ class DDSRunner {
|
||||
return false;
|
||||
}
|
||||
|
||||
final process = await Process.start(
|
||||
execName,
|
||||
[
|
||||
if (debugDds) '--enable-vm-service=0',
|
||||
snapshotName,
|
||||
'--vm-service-uri=$vmServiceUri',
|
||||
'--bind-address=$ddsHost',
|
||||
'--bind-port=$ddsPort',
|
||||
if (disableServiceAuthCodes) '--disable-service-auth-codes',
|
||||
if (enableDevTools) '--serve-devtools',
|
||||
if (debugDds) '--enable-logging',
|
||||
if (enableServicePortFallback) '--enable-service-port-fallback',
|
||||
],
|
||||
mode: ProcessStartMode.detachedWithStdio,
|
||||
);
|
||||
final process = await Process.start(execName, [
|
||||
if (debugDds) '--enable-vm-service=0',
|
||||
snapshotName,
|
||||
'--vm-service-uri=$vmServiceUri',
|
||||
'--bind-address=$ddsHost',
|
||||
'--bind-port=$ddsPort',
|
||||
if (disableServiceAuthCodes) '--disable-service-auth-codes',
|
||||
if (enableDevTools) '--serve-devtools',
|
||||
if (debugDds) '--enable-logging',
|
||||
if (enableServicePortFallback) '--enable-service-port-fallback',
|
||||
], mode: ProcessStartMode.detachedWithStdio);
|
||||
|
||||
// NOTE: update pkg/dartdev/lib/src/commands/run.dart if this message
|
||||
// is changed to ensure consistency.
|
||||
@@ -66,14 +61,14 @@ class DDSRunner {
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen((event) {
|
||||
if (event.startsWith(devToolsMessagePrefix)) {
|
||||
final ddsDebuggingUri = event.split(' ').last;
|
||||
print(
|
||||
'A DevTools debugger for DDS is available at: $ddsDebuggingUri',
|
||||
);
|
||||
stdoutSub.cancel();
|
||||
}
|
||||
});
|
||||
if (event.startsWith(devToolsMessagePrefix)) {
|
||||
final ddsDebuggingUri = event.split(' ').last;
|
||||
print(
|
||||
'A DevTools debugger for DDS is available at: $ddsDebuggingUri',
|
||||
);
|
||||
stdoutSub.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// DDS will close stderr once it's finished launching.
|
||||
@@ -81,11 +76,7 @@ class DDSRunner {
|
||||
|
||||
try {
|
||||
final result = json.decode(launchResult) as Map<String, dynamic>;
|
||||
if (result
|
||||
case {
|
||||
'state': 'started',
|
||||
'ddsUri': final String ddsUriStr,
|
||||
}) {
|
||||
if (result case {'state': 'started', 'ddsUri': final String ddsUriStr}) {
|
||||
ddsUri = Uri.parse(ddsUriStr);
|
||||
if (result case {'devToolsUri': String devToolsUri}) {
|
||||
print('$devToolsMessagePrefix $devToolsUri');
|
||||
|
||||
@@ -24,8 +24,9 @@ extension ArgParserExtensions on ArgParser {
|
||||
|
||||
Map<String, String> allowedHelp = {};
|
||||
for (ExperimentalFeature feature in features) {
|
||||
String suffix =
|
||||
feature.isEnabledByDefault ? ' (no-op - enabled by default)' : '';
|
||||
String suffix = feature.isEnabledByDefault
|
||||
? ' (no-op - enabled by default)'
|
||||
: '';
|
||||
allowedHelp[feature.enableString] = '${feature.documentation}$suffix';
|
||||
}
|
||||
|
||||
@@ -33,7 +34,8 @@ extension ArgParserExtensions on ArgParser {
|
||||
experimentFlagName,
|
||||
valueHelp: 'experiment',
|
||||
allowedHelp: verbose ? allowedHelp : null,
|
||||
help: 'Enable one or more experimental features '
|
||||
help:
|
||||
'Enable one or more experimental features '
|
||||
'(see dart.dev/go/experiments).',
|
||||
hide: !verbose,
|
||||
);
|
||||
@@ -70,8 +72,10 @@ extension ArgResultsExtensions on ArgResults {
|
||||
// We allow default true flags, but complain when they are passed in.
|
||||
if (feature.isEnabledByDefault &&
|
||||
enabledExperiments.contains(feature.enableString)) {
|
||||
stderr.writeln("'${feature.enableString}' is now enabled by default; "
|
||||
'this flag is no longer required.');
|
||||
stderr.writeln(
|
||||
"'${feature.enableString}' is now enabled by default; "
|
||||
'this flag is no longer required.',
|
||||
);
|
||||
}
|
||||
}
|
||||
return enabledExperiments;
|
||||
@@ -97,8 +101,9 @@ List<String> parseVmEnabledExperiments(List<String> vmArgs) {
|
||||
}
|
||||
|
||||
bool nativeAssetsEnabled(List<String> vmEnabledExperiments) =>
|
||||
vmEnabledExperiments
|
||||
.contains(ExperimentalFeatures.native_assets.enableString) ||
|
||||
vmEnabledExperiments.contains(
|
||||
ExperimentalFeatures.native_assets.enableString,
|
||||
) ||
|
||||
(_availableOnCurrentChannel(ExperimentalFeatures.native_assets.channels) &&
|
||||
ExperimentalFeatures.native_assets.isEnabledByDefault);
|
||||
|
||||
@@ -106,14 +111,16 @@ bool recordUseEnabled(List<String> vmEnabledExperiments) =>
|
||||
vmEnabledExperiments.contains(ExperimentalFeatures.record_use.enableString);
|
||||
|
||||
bool dataAssetsEnabled(List<String> vmEnabledExperiments) =>
|
||||
vmEnabledExperiments
|
||||
.contains(ExperimentalFeatures.data_assets.enableString);
|
||||
vmEnabledExperiments.contains(
|
||||
ExperimentalFeatures.data_assets.enableString,
|
||||
);
|
||||
|
||||
List<String> validateExperiments(List<String> vmEnabledExperiments) {
|
||||
final errors = <String>[];
|
||||
for (final enabledExperiment in vmEnabledExperiments) {
|
||||
final experiment = experimentalFeatures.firstWhereOrNull(
|
||||
(feature) => feature.enableString == enabledExperiment);
|
||||
(feature) => feature.enableString == enabledExperiment,
|
||||
);
|
||||
if (experiment == null) {
|
||||
errors.add('Unknown experiment: $enabledExperiment');
|
||||
} else if (!_availableOnCurrentChannel(experiment.channels)) {
|
||||
|
||||
@@ -20,13 +20,14 @@ import 'resident_frontend_utils.dart';
|
||||
import 'sdk.dart';
|
||||
import 'unified_analytics.dart';
|
||||
|
||||
typedef CompileRequestGeneratorCallback = String Function({
|
||||
required String executable,
|
||||
required String outputDill,
|
||||
required ArgResults args,
|
||||
String? packages,
|
||||
String? nativeAssetsYaml,
|
||||
});
|
||||
typedef CompileRequestGeneratorCallback =
|
||||
String Function({
|
||||
required String executable,
|
||||
required String outputDill,
|
||||
required ArgResults args,
|
||||
String? packages,
|
||||
String? nativeAssetsYaml,
|
||||
});
|
||||
|
||||
/// Uses the resident frontend compiler to compute a kernel file for
|
||||
/// [executable]. Throws a [FrontendCompilerException] if the compilation
|
||||
@@ -56,19 +57,17 @@ Future<DartExecutableWithPackageConfig> generateKernel(
|
||||
}) async {
|
||||
// Locates the package_config.json and cached kernel file, makes sure the
|
||||
// resident frontend server is up and running, and computes a kernel.
|
||||
await ensureCompilationServerIsRunning(
|
||||
serverInfoFile,
|
||||
quiet: quiet,
|
||||
);
|
||||
await ensureCompilationServerIsRunning(serverInfoFile, quiet: quiet);
|
||||
|
||||
final packageRoot = _packageRootFor(executable);
|
||||
final packageConfig =
|
||||
packageRoot != null ? p.join(packageRoot, packageConfigName) : null;
|
||||
final packageConfig = packageRoot != null
|
||||
? p.join(packageRoot, packageConfigName)
|
||||
: null;
|
||||
|
||||
final canonicalizedExecutablePath = p.canonicalize(executable.executable);
|
||||
final cachedDillPath =
|
||||
computeCachedDillAndCompilerOptionsPaths(canonicalizedExecutablePath)
|
||||
.cachedDillPath;
|
||||
final cachedDillPath = computeCachedDillAndCompilerOptionsPaths(
|
||||
canonicalizedExecutablePath,
|
||||
).cachedDillPath;
|
||||
|
||||
Map<String, dynamic> result;
|
||||
try {
|
||||
@@ -139,7 +138,7 @@ Future<void> ensureCompilationServerIsRunning(
|
||||
sdk.dartAotRuntime,
|
||||
[
|
||||
sdk.frontendServerAotSnapshot,
|
||||
'--resident-info-file-name=${serverInfoFile.absolute.path}'
|
||||
'--resident-info-file-name=${serverInfoFile.absolute.path}',
|
||||
],
|
||||
workingDirectory: homeDir?.path,
|
||||
mode: ProcessStartMode.detachedWithStdio,
|
||||
@@ -148,8 +147,9 @@ Future<void> ensureCompilationServerIsRunning(
|
||||
throw StateError('Unable to find snapshot for frontend server');
|
||||
}
|
||||
|
||||
final serverOutput =
|
||||
String.fromCharCodes(await frontendServerProcess.stdout.first).trim();
|
||||
final serverOutput = String.fromCharCodes(
|
||||
await frontendServerProcess.stdout.first,
|
||||
).trim();
|
||||
if (serverOutput.startsWith('Error')) {
|
||||
throw StateError(serverOutput);
|
||||
}
|
||||
@@ -172,8 +172,9 @@ Future<void> ensureCompilationServerIsRunning(
|
||||
/// Returns the path to the root of the [executable]'s package, or null
|
||||
/// if it is a standalone dart file.
|
||||
String? _packageRootFor(DartExecutableWithPackageConfig executable) {
|
||||
Directory currentDirectory =
|
||||
Directory(p.dirname(p.canonicalize(executable.executable)));
|
||||
Directory currentDirectory = Directory(
|
||||
p.dirname(p.canonicalize(executable.executable)),
|
||||
);
|
||||
|
||||
while (currentDirectory.parent.path != currentDirectory.path) {
|
||||
if (File(p.join(currentDirectory.path, packageConfigName)).existsSync()) {
|
||||
|
||||
@@ -30,58 +30,46 @@ import 'package:dartdev/src/utils.dart';
|
||||
/// └── [AppBundleDirectory] (e.g., 'my_package/local/')
|
||||
/// </pre>
|
||||
extension type DartInstallDirectory._(Directory directory) {
|
||||
static final DartInstallDirectory _singleton =
|
||||
DartInstallDirectory._(Directory(getDartDataHome('install')));
|
||||
static final DartInstallDirectory _singleton = DartInstallDirectory._(
|
||||
Directory(getDartDataHome('install')),
|
||||
);
|
||||
|
||||
factory DartInstallDirectory() {
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
BinOnPathDirectory get bin => BinOnPathDirectory._(
|
||||
Directory.fromUri(
|
||||
directory.uri.resolve('bin/'),
|
||||
),
|
||||
);
|
||||
BinOnPathDirectory get bin =>
|
||||
BinOnPathDirectory._(Directory.fromUri(directory.uri.resolve('bin/')));
|
||||
|
||||
Directory get _appBundles =>
|
||||
Directory.fromUri(directory.uri.resolve('app-bundles/'));
|
||||
|
||||
AppBundleDirectory gitAppBundle(
|
||||
String packageName,
|
||||
String gitHash,
|
||||
) =>
|
||||
AppBundleDirectory gitAppBundle(String packageName, String gitHash) =>
|
||||
AppBundleDirectory._(
|
||||
Directory.fromUri(
|
||||
_appBundles.uri.resolve('$packageName/git/$gitHash/'),
|
||||
),
|
||||
);
|
||||
|
||||
AppBundleDirectory hostedAppBundle(
|
||||
String packageName,
|
||||
String version,
|
||||
) =>
|
||||
AppBundleDirectory hostedAppBundle(String packageName, String version) =>
|
||||
AppBundleDirectory._(
|
||||
Directory.fromUri(
|
||||
_appBundles.uri.resolve('$packageName/hosted/$version/'),
|
||||
),
|
||||
);
|
||||
|
||||
AppBundleDirectory localAppBundle(
|
||||
String packageName,
|
||||
) =>
|
||||
AppBundleDirectory._(
|
||||
Directory.fromUri(
|
||||
_appBundles.uri.resolve('$packageName/local/'),
|
||||
),
|
||||
);
|
||||
AppBundleDirectory localAppBundle(String packageName) => AppBundleDirectory._(
|
||||
Directory.fromUri(_appBundles.uri.resolve('$packageName/local/')),
|
||||
);
|
||||
|
||||
List<AppBundleDirectory> allAppBundlesSync({String? packageName}) {
|
||||
final dartInstallAppbundlesDir = _appBundles;
|
||||
if (!dartInstallAppbundlesDir.existsSync()) {
|
||||
return [];
|
||||
}
|
||||
final packageDirs =
|
||||
dartInstallAppbundlesDir.listSync().whereType<Directory>();
|
||||
final packageDirs = dartInstallAppbundlesDir
|
||||
.listSync()
|
||||
.whereType<Directory>();
|
||||
final result = <AppBundleDirectory>[];
|
||||
for (final packageDir in packageDirs) {
|
||||
if (packageName != null && packageDir.name != packageName) {
|
||||
@@ -92,18 +80,16 @@ extension type DartInstallDirectory._(Directory directory) {
|
||||
final localDir = Directory.fromUri(packageDir.uri.resolve('local/'));
|
||||
if (gitDir.existsSync()) {
|
||||
result.addAll(
|
||||
gitDir
|
||||
.listSync()
|
||||
.whereType<Directory>()
|
||||
.map((d) => AppBundleDirectory._(d.ensureEndWithSeparator)),
|
||||
gitDir.listSync().whereType<Directory>().map(
|
||||
(d) => AppBundleDirectory._(d.ensureEndWithSeparator),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (hostedDir.existsSync()) {
|
||||
result.addAll(
|
||||
hostedDir
|
||||
.listSync()
|
||||
.whereType<Directory>()
|
||||
.map((d) => AppBundleDirectory._(d.ensureEndWithSeparator)),
|
||||
hostedDir.listSync().whereType<Directory>().map(
|
||||
(d) => AppBundleDirectory._(d.ensureEndWithSeparator),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (localDir.existsSync()) {
|
||||
@@ -130,7 +116,8 @@ extension type BinOnPathDirectory._(Directory directory) {
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
return ExecutableOnPath._windows(
|
||||
File.fromUri(directory.uri.resolve('$name.bat')));
|
||||
File.fromUri(directory.uri.resolve('$name.bat')),
|
||||
);
|
||||
}
|
||||
throw UnsupportedError('Unsupported OS: ${Platform.operatingSystem}.');
|
||||
}
|
||||
@@ -169,7 +156,8 @@ extension type ExecutableOnPath._(FileSystemEntity entity) {
|
||||
return unix.createSync(target.file.path, recursive: true);
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
final wrapperScriptContents = '''
|
||||
final wrapperScriptContents =
|
||||
'''
|
||||
@ECHO OFF
|
||||
REM $_marker
|
||||
"${target.file.path}" %*
|
||||
@@ -235,12 +223,11 @@ extension type AppBundleDirectory._(Directory directory) {
|
||||
// return null;
|
||||
}
|
||||
final relativeSegments = directory.uri.pathSegments
|
||||
.skip(DartInstallDirectory()
|
||||
._appBundles
|
||||
.uri
|
||||
.pathSegments
|
||||
.where((e) => e.isNotEmpty)
|
||||
.length)
|
||||
.skip(
|
||||
DartInstallDirectory()._appBundles.uri.pathSegments
|
||||
.where((e) => e.isNotEmpty)
|
||||
.length,
|
||||
)
|
||||
.toList();
|
||||
if (relativeSegments.length < 2) {
|
||||
throw StateError(
|
||||
@@ -287,11 +274,11 @@ extension type AppBundleDirectory._(Directory directory) {
|
||||
///
|
||||
/// The parameter [name] most not contain an extension.
|
||||
ExecutableInBundle executable(String name) {
|
||||
return ExecutableInBundle._(File.fromUri(
|
||||
_binDirectory.uri.resolve(
|
||||
Platform.isWindows ? '$name.exe' : name,
|
||||
return ExecutableInBundle._(
|
||||
File.fromUri(
|
||||
_binDirectory.uri.resolve(Platform.isWindows ? '$name.exe' : name),
|
||||
),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
File get pubspec => File.fromUri(directory.uri.resolve('pubspec.yaml'));
|
||||
@@ -315,9 +302,7 @@ extension type AppBundleDirectory._(Directory directory) {
|
||||
/// An executable inside an [AppBundleDirectory].
|
||||
extension type ExecutableInBundle._(File file) {
|
||||
AppBundleDirectory get appBundle {
|
||||
return AppBundleDirectory._(Directory.fromUri(
|
||||
file.uri.resolve('../../'),
|
||||
));
|
||||
return AppBundleDirectory._(Directory.fromUri(file.uri.resolve('../../')));
|
||||
}
|
||||
|
||||
ExecutableOnPath get onPath =>
|
||||
|
||||
@@ -56,7 +56,8 @@ Map<String, Object?> _convertYamlMapToJsonMap(YamlMap yamlMap) {
|
||||
yamlMap.forEach((key, value) {
|
||||
if (key is! String) {
|
||||
throw UnsupportedError(
|
||||
'YAML map keys must be strings for JSON conversion.');
|
||||
'YAML map keys must be strings for JSON conversion.',
|
||||
);
|
||||
}
|
||||
jsonMap[key] = _convertYamlValue(value);
|
||||
});
|
||||
|
||||
@@ -57,15 +57,15 @@ class DartNativeAssetsBuilder {
|
||||
|
||||
late final Future<NativeAssetsBuildRunner> _nativeAssetsBuildRunner =
|
||||
() async {
|
||||
return NativeAssetsBuildRunner(
|
||||
// This always runs in JIT mode.
|
||||
dartExecutable: Uri.file(sdk.dart),
|
||||
logger: _logger,
|
||||
fileSystem: const LocalFileSystem(),
|
||||
packageLayout: await _packageLayout,
|
||||
userDefines: UserDefines(workspacePubspec: pubspecUri),
|
||||
);
|
||||
}();
|
||||
return NativeAssetsBuildRunner(
|
||||
// This always runs in JIT mode.
|
||||
dartExecutable: Uri.file(sdk.dart),
|
||||
logger: _logger,
|
||||
fileSystem: const LocalFileSystem(),
|
||||
packageLayout: await _packageLayout,
|
||||
userDefines: UserDefines(workspacePubspec: pubspecUri),
|
||||
);
|
||||
}();
|
||||
|
||||
DartNativeAssetsBuilder({
|
||||
this.pubspecUri,
|
||||
@@ -181,8 +181,9 @@ class DartNativeAssetsBuilder {
|
||||
final builder = await _nativeAssetsBuildRunner;
|
||||
final linkResult = await builder.link(
|
||||
extensions: _extensions,
|
||||
resourceIdentifiers:
|
||||
recordedUsagesPath != null ? Uri.file(recordedUsagesPath) : null,
|
||||
resourceIdentifiers: recordedUsagesPath != null
|
||||
? Uri.file(recordedUsagesPath)
|
||||
: null,
|
||||
buildResult: buildResult,
|
||||
);
|
||||
if (linkResult.isFailure) return null;
|
||||
@@ -261,7 +262,8 @@ class DartNativeAssetsBuilder {
|
||||
///
|
||||
/// Returns null and writes to stderr if the package config is malformed.
|
||||
static Future<package_config.PackageConfig?> loadPackageConfig(
|
||||
Uri packageConfigUri) async {
|
||||
Uri packageConfigUri,
|
||||
) async {
|
||||
try {
|
||||
return await package_config.loadPackageConfigUri(packageConfigUri);
|
||||
} on FormatException catch (e) {
|
||||
@@ -282,10 +284,12 @@ class DartNativeAssetsBuilder {
|
||||
// logic in package:package_config.
|
||||
static Future<Uri?> _findPackageConfigUri(Uri uri) async {
|
||||
while (true) {
|
||||
final packageConfig =
|
||||
File.fromUri(uri.resolve('.dart_tool/package_config.json'));
|
||||
final packageGraph =
|
||||
File.fromUri(uri.resolve('.dart_tool/package_graph.json'));
|
||||
final packageConfig = File.fromUri(
|
||||
uri.resolve('.dart_tool/package_config.json'),
|
||||
);
|
||||
final packageGraph = File.fromUri(
|
||||
uri.resolve('.dart_tool/package_graph.json'),
|
||||
);
|
||||
if (await packageConfig.exists() && await packageGraph.exists()) {
|
||||
return packageConfig.uri;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ import 'package:data_assets/data_assets.dart';
|
||||
import 'package:hooks/hooks.dart';
|
||||
import 'package:hooks_runner/hooks_runner.dart';
|
||||
|
||||
final libOutputDirectoryUriFromBin =
|
||||
Uri.file('../').resolveUri(libOutputDirectoryUri);
|
||||
final libOutputDirectoryUriFromBin = Uri.file(
|
||||
'../',
|
||||
).resolveUri(libOutputDirectoryUri);
|
||||
final libOutputDirectoryUri = Uri.file('lib/');
|
||||
final dataOutputDirectoryUri = Uri.file('assets/');
|
||||
|
||||
@@ -64,18 +65,10 @@ Future<void> _copyAssets(
|
||||
|
||||
switch (asset) {
|
||||
case CodeAsset(:final file!):
|
||||
filesToCopy.add((
|
||||
id: asset.id,
|
||||
src: file,
|
||||
dest: targetUri,
|
||||
));
|
||||
filesToCopy.add((id: asset.id, src: file, dest: targetUri));
|
||||
codeAssetUris.add(targetUri);
|
||||
case DataAsset(:final file):
|
||||
filesToCopy.add((
|
||||
id: asset.id,
|
||||
src: file,
|
||||
dest: targetUri,
|
||||
));
|
||||
filesToCopy.add((id: asset.id, src: file, dest: targetUri));
|
||||
default:
|
||||
throw UnimplementedError();
|
||||
}
|
||||
@@ -105,21 +98,23 @@ List<({Object asset, KernelAsset target})> _targetMapping(
|
||||
Uri outputUri,
|
||||
bool relocatable,
|
||||
) {
|
||||
final codeAssets =
|
||||
assets.where((asset) => asset.isCodeAsset).map(CodeAsset.fromEncoded);
|
||||
final dataAssets =
|
||||
assets.where((asset) => asset.isDataAsset).map(DataAsset.fromEncoded);
|
||||
final codeAssets = assets
|
||||
.where((asset) => asset.isCodeAsset)
|
||||
.map(CodeAsset.fromEncoded);
|
||||
final dataAssets = assets
|
||||
.where((asset) => asset.isDataAsset)
|
||||
.map(DataAsset.fromEncoded);
|
||||
|
||||
return [
|
||||
for (final asset in codeAssets)
|
||||
(
|
||||
asset: asset,
|
||||
target: asset.targetLocation(target, outputUri, relocatable)
|
||||
target: asset.targetLocation(target, outputUri, relocatable),
|
||||
),
|
||||
for (final asset in dataAssets)
|
||||
(
|
||||
asset: asset,
|
||||
target: asset.targetLocation(target, outputUri, relocatable)
|
||||
target: asset.targetLocation(target, outputUri, relocatable),
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -131,21 +126,18 @@ extension on CodeAsset {
|
||||
LookupInExecutable() => KernelAssetInExecutable(),
|
||||
LookupInProcess() => KernelAssetInProcess(),
|
||||
DynamicLoadingBundled() => () {
|
||||
final relativeUri =
|
||||
libOutputDirectoryUriFromBin.resolve(file!.pathSegments.last);
|
||||
return relocatable
|
||||
? KernelAssetRelativePath(relativeUri)
|
||||
: KernelAssetAbsolutePath(outputUri.resolveUri(relativeUri));
|
||||
}(),
|
||||
final relativeUri = libOutputDirectoryUriFromBin.resolve(
|
||||
file!.pathSegments.last,
|
||||
);
|
||||
return relocatable
|
||||
? KernelAssetRelativePath(relativeUri)
|
||||
: KernelAssetAbsolutePath(outputUri.resolveUri(relativeUri));
|
||||
}(),
|
||||
_ => throw UnsupportedError(
|
||||
'Unsupported NativeCodeAsset linkMode ${linkMode.runtimeType} in asset $this',
|
||||
),
|
||||
'Unsupported NativeCodeAsset linkMode ${linkMode.runtimeType} in asset $this',
|
||||
),
|
||||
};
|
||||
return KernelAsset(
|
||||
id: id,
|
||||
target: target,
|
||||
path: kernelAssetPath,
|
||||
);
|
||||
return KernelAsset(id: id, target: target, path: kernelAssetPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,40 +16,39 @@ Future<void> rewriteInstallNames(
|
||||
final oldToNewInstallNames = <String, String>{};
|
||||
final dylibInfos = <(Uri, String)>[];
|
||||
|
||||
await Future.wait(dylibs.map((dylib) async {
|
||||
final newInstallName = relocatable
|
||||
? _rpathUri
|
||||
.resolveUri(libOutputDirectoryUri)
|
||||
.resolve(dylib.pathSegments.last)
|
||||
.toFilePath()
|
||||
: dylib.toFilePath();
|
||||
final oldInstallName = await _getInstallName(dylib);
|
||||
oldToNewInstallNames[oldInstallName] = newInstallName;
|
||||
dylibInfos.add((dylib, newInstallName));
|
||||
}));
|
||||
await Future.wait(
|
||||
dylibs.map((dylib) async {
|
||||
final newInstallName = relocatable
|
||||
? _rpathUri
|
||||
.resolveUri(libOutputDirectoryUri)
|
||||
.resolve(dylib.pathSegments.last)
|
||||
.toFilePath()
|
||||
: dylib.toFilePath();
|
||||
final oldInstallName = await _getInstallName(dylib);
|
||||
oldToNewInstallNames[oldInstallName] = newInstallName;
|
||||
dylibInfos.add((dylib, newInstallName));
|
||||
}),
|
||||
);
|
||||
|
||||
await Future.wait(dylibInfos.map((info) async {
|
||||
final (dylib, newInstallName) = info;
|
||||
await _setInstallNames(dylib, newInstallName, oldToNewInstallNames);
|
||||
await _codeSignDylib(dylib);
|
||||
}));
|
||||
await Future.wait(
|
||||
dylibInfos.map((info) async {
|
||||
final (dylib, newInstallName) = info;
|
||||
await _setInstallNames(dylib, newInstallName, oldToNewInstallNames);
|
||||
await _codeSignDylib(dylib);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _getInstallName(Uri dylib) async {
|
||||
final otoolResult = await Process.run(
|
||||
'otool',
|
||||
[
|
||||
'-D',
|
||||
dylib.toFilePath(),
|
||||
],
|
||||
);
|
||||
final otoolResult = await Process.run('otool', ['-D', dylib.toFilePath()]);
|
||||
if (otoolResult.exitCode != 0) {
|
||||
throw Exception(
|
||||
'Failed to get install name for dylib $dylib: ${otoolResult.stderr}',
|
||||
);
|
||||
}
|
||||
final architectureSections =
|
||||
parseOtoolArchitectureSections(otoolResult.stdout);
|
||||
final architectureSections = parseOtoolArchitectureSections(
|
||||
otoolResult.stdout,
|
||||
);
|
||||
if (architectureSections.length != 1) {
|
||||
throw Exception(
|
||||
'Expected a single architecture section in otool output: $otoolResult',
|
||||
@@ -63,19 +62,16 @@ Future<void> _setInstallNames(
|
||||
String newInstallName,
|
||||
Map<String, String> oldToNewInstallNames,
|
||||
) async {
|
||||
final installNameToolResult = await Process.run(
|
||||
'install_name_tool',
|
||||
[
|
||||
'-id',
|
||||
newInstallName,
|
||||
for (final entry in oldToNewInstallNames.entries) ...[
|
||||
'-change',
|
||||
entry.key,
|
||||
entry.value,
|
||||
],
|
||||
dylib.toFilePath(),
|
||||
final installNameToolResult = await Process.run('install_name_tool', [
|
||||
'-id',
|
||||
newInstallName,
|
||||
for (final entry in oldToNewInstallNames.entries) ...[
|
||||
'-change',
|
||||
entry.key,
|
||||
entry.value,
|
||||
],
|
||||
);
|
||||
dylib.toFilePath(),
|
||||
]);
|
||||
if (installNameToolResult.exitCode != 0) {
|
||||
throw Exception(
|
||||
'Failed to set install names for dylib $dylib:\n'
|
||||
@@ -87,15 +83,12 @@ Future<void> _setInstallNames(
|
||||
}
|
||||
|
||||
Future<void> _codeSignDylib(Uri dylib) async {
|
||||
final codesignResult = await Process.run(
|
||||
'codesign',
|
||||
[
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
dylib.toFilePath(),
|
||||
],
|
||||
);
|
||||
final codesignResult = await Process.run('codesign', [
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
dylib.toFilePath(),
|
||||
]);
|
||||
if (codesignResult.exitCode != 0) {
|
||||
throw Exception(
|
||||
'Failed to codesign dylib $dylib: ${codesignResult.stderr}',
|
||||
@@ -123,8 +116,9 @@ Map<Architecture?, List<String>> parseOtoolArchitectureSections(String output) {
|
||||
'arm64': Architecture.arm64,
|
||||
'x86_64': Architecture.x64,
|
||||
};
|
||||
final RegExp architectureHeaderPattern =
|
||||
RegExp(r'^[^(]+( \(architecture (.+)\))?:$');
|
||||
final RegExp architectureHeaderPattern = RegExp(
|
||||
r'^[^(]+( \(architecture (.+)\))?:$',
|
||||
);
|
||||
final Iterator<String> lines = output.trim().split('\n').iterator;
|
||||
Architecture? currentArchitecture;
|
||||
final Map<Architecture?, List<String>> architectureSections =
|
||||
@@ -132,8 +126,9 @@ Map<Architecture?, List<String>> parseOtoolArchitectureSections(String output) {
|
||||
|
||||
while (lines.moveNext()) {
|
||||
final String line = lines.current;
|
||||
final Match? architectureHeader =
|
||||
architectureHeaderPattern.firstMatch(line);
|
||||
final Match? architectureHeader = architectureHeaderPattern.firstMatch(
|
||||
line,
|
||||
);
|
||||
if (architectureHeader != null) {
|
||||
if (architectureSections.containsKey(null)) {
|
||||
throw Exception(
|
||||
@@ -174,26 +169,22 @@ Map<Architecture?, List<String>> parseOtoolArchitectureSections(String output) {
|
||||
/// So, the `bundle/` directory must be added to the include path to allow for
|
||||
/// loading dylibs.
|
||||
Future<void> rewriteInstallPath(Uri executable) async {
|
||||
final result = await Process.run(
|
||||
'install_name_tool',
|
||||
['-add_rpath', '@executable_path/..', executable.toFilePath()],
|
||||
);
|
||||
final result = await Process.run('install_name_tool', [
|
||||
'-add_rpath',
|
||||
'@executable_path/..',
|
||||
executable.toFilePath(),
|
||||
]);
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception(
|
||||
'Failed to add rpath: ${result.stderr}',
|
||||
);
|
||||
throw Exception('Failed to add rpath: ${result.stderr}');
|
||||
}
|
||||
|
||||
// Resign after modifying.
|
||||
final codesignResult = await Process.run(
|
||||
'codesign',
|
||||
[
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
executable.toFilePath(),
|
||||
],
|
||||
);
|
||||
final codesignResult = await Process.run('codesign', [
|
||||
'--force',
|
||||
'--sign',
|
||||
'-',
|
||||
executable.toFilePath(),
|
||||
]);
|
||||
if (codesignResult.exitCode != 0) {
|
||||
throw Exception(
|
||||
'Failed to codesign dylib $executable: ${codesignResult.stderr}',
|
||||
|
||||
@@ -241,8 +241,9 @@ List<ProcessInfo> _getProcessInfoMacOS({bool elideFilePaths = true}) {
|
||||
.skip(1)
|
||||
.map((line) => line.trim())
|
||||
.where((line) => line.isNotEmpty)
|
||||
.map((line) =>
|
||||
ProcessInfo.parseMacos(line, elideFilePaths: elideFilePaths))
|
||||
.map(
|
||||
(line) => ProcessInfo.parseMacos(line, elideFilePaths: elideFilePaths),
|
||||
)
|
||||
.where(_isProcessDartRelated)
|
||||
.toList();
|
||||
}
|
||||
@@ -258,8 +259,9 @@ List<ProcessInfo> _getProcessInfoLinux({bool elideFilePaths = true}) {
|
||||
.skip(1)
|
||||
.map((line) => line.trim())
|
||||
.where((line) => line.isNotEmpty)
|
||||
.map((line) =>
|
||||
ProcessInfo._parseLinux(line, elideFilePaths: elideFilePaths))
|
||||
.map(
|
||||
(line) => ProcessInfo._parseLinux(line, elideFilePaths: elideFilePaths),
|
||||
)
|
||||
.whereType<ProcessInfo>()
|
||||
.where(_isProcessDartRelated)
|
||||
.toList();
|
||||
@@ -289,8 +291,10 @@ List<ProcessInfo> _getProcessInfoWindows() {
|
||||
}
|
||||
|
||||
bool _isProcessDartRelated(ProcessInfo process) {
|
||||
return process.command == 'dart' || process.command == 'dart.exe' ||
|
||||
process.command == 'dartvm' || process.command == 'dartvm.exe';
|
||||
return process.command == 'dart' ||
|
||||
process.command == 'dart.exe' ||
|
||||
process.command == 'dartvm' ||
|
||||
process.command == 'dartvm.exe';
|
||||
}
|
||||
|
||||
String _getCommandFrom(String commandLine) {
|
||||
|
||||
@@ -17,10 +17,7 @@ import 'dart:io';
|
||||
/// The progress indicator is only animated if output is going to a terminal.
|
||||
/// When the [callback] completes, the progress indicator is stopped and the
|
||||
/// final time is shown.
|
||||
Future<T> progress<T>(
|
||||
String message,
|
||||
Future<T> Function() callback,
|
||||
) async {
|
||||
Future<T> progress<T>(String message, Future<T> Function() callback) async {
|
||||
final progress = _Progress(message);
|
||||
return callback().whenComplete(progress._stop);
|
||||
}
|
||||
|
||||
@@ -15,16 +15,15 @@ import 'commands/compilation_server.dart' show CompilationServerCommand;
|
||||
import 'resident_frontend_constants.dart';
|
||||
|
||||
/// The Resident Frontend Compiler's shutdown command.
|
||||
final residentServerShutdownCommand = jsonEncode(
|
||||
<String, Object>{
|
||||
commandString: shutdownString,
|
||||
},
|
||||
);
|
||||
final residentServerShutdownCommand = jsonEncode(<String, Object>{
|
||||
commandString: shutdownString,
|
||||
});
|
||||
|
||||
File? getResidentCompilerInfoFileConsideringArgs(final ArgResults args) =>
|
||||
getResidentCompilerInfoFileConsideringArgsImpl(
|
||||
args[CompilationServerCommand.residentCompilerInfoFileFlag] ??
|
||||
args[CompilationServerCommand.legacyResidentServerInfoFileFlag]);
|
||||
args[CompilationServerCommand.residentCompilerInfoFileFlag] ??
|
||||
args[CompilationServerCommand.legacyResidentServerInfoFileFlag],
|
||||
);
|
||||
|
||||
final String packageConfigName = p.join('.dart_tool', 'package_config.json');
|
||||
|
||||
@@ -48,10 +47,7 @@ Future<void> shutDownOrForgetResidentFrontendCompiler(File infoFile) async {
|
||||
try {
|
||||
// As explained in the doc comment above, this function ignores errors. So,
|
||||
// we ignore the return value of [sendAndReceiveResponse].
|
||||
await sendAndReceiveResponse(
|
||||
residentServerShutdownCommand,
|
||||
infoFile,
|
||||
);
|
||||
await sendAndReceiveResponse(residentServerShutdownCommand, infoFile);
|
||||
} on FileSystemException catch (_) {
|
||||
// As explained in the doc comment above, this function ignores errors. We
|
||||
// only catch [FileSystemException]s because [sendAndReceiveResponse] cannot
|
||||
@@ -100,7 +96,7 @@ Future<bool> isFileAotSnapshot(final File file) async {
|
||||
if (bytes[0] == 0x01 && bytes[1] == 0xc0 || // arm32
|
||||
bytes[0] == 0xaa && bytes[1] == 0x64 || // arm64
|
||||
bytes[0] == 0x50 && bytes[1] == 0x32 || // riscv32
|
||||
bytes[0] == 0x50 && bytes[1] == 0x64 /* riscv64 */) {
|
||||
bytes[0] == 0x50 && bytes[1] == 0x64 /* riscv64 */ ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -151,25 +147,22 @@ String createCompileJitJson({
|
||||
bool verbose = false,
|
||||
String? nativeAssetsYaml,
|
||||
}) {
|
||||
return jsonEncode(
|
||||
<String, Object?>{
|
||||
commandString: compileString,
|
||||
sourceString: executable,
|
||||
outputString: outputDill,
|
||||
if (args.wasParsed(defineOption))
|
||||
defineOption: args.multiOption(defineOption),
|
||||
if (args.options.contains(enableAssertsOption) &&
|
||||
args.wasParsed(enableAssertsOption))
|
||||
enableAssertsOption: true,
|
||||
if (args.wasParsed(enableExperimentOption))
|
||||
enableExperimentOption: args
|
||||
.multiOption(enableExperimentOption)
|
||||
.map((e) => '--enable-experiment=$e')
|
||||
.toList(),
|
||||
if (packages != null) packageString: packages,
|
||||
if (args.wasParsed(verbosityOption))
|
||||
verbosityOption: args[verbosityOption],
|
||||
if (nativeAssetsYaml != null) nativeAssetsOption: nativeAssetsYaml,
|
||||
},
|
||||
);
|
||||
return jsonEncode(<String, Object?>{
|
||||
commandString: compileString,
|
||||
sourceString: executable,
|
||||
outputString: outputDill,
|
||||
if (args.wasParsed(defineOption))
|
||||
defineOption: args.multiOption(defineOption),
|
||||
if (args.options.contains(enableAssertsOption) &&
|
||||
args.wasParsed(enableAssertsOption))
|
||||
enableAssertsOption: true,
|
||||
if (args.wasParsed(enableExperimentOption))
|
||||
enableExperimentOption: args
|
||||
.multiOption(enableExperimentOption)
|
||||
.map((e) => '--enable-experiment=$e')
|
||||
.toList(),
|
||||
packageString: ?packages,
|
||||
if (args.wasParsed(verbosityOption)) verbosityOption: args[verbosityOption],
|
||||
nativeAssetsOption: ?nativeAssetsYaml,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@ import 'core.dart';
|
||||
// Moved to dart2native so it can be used there without causing a cycle.
|
||||
export 'package:dart2native/sdk.dart';
|
||||
|
||||
bool checkArtifactExists(String path,
|
||||
{bool logError = true, bool warnIfBuildRoot = false}) {
|
||||
bool checkArtifactExists(
|
||||
String path, {
|
||||
bool logError = true,
|
||||
bool warnIfBuildRoot = false,
|
||||
}) {
|
||||
if (warnIfBuildRoot && Sdk().runFromBuildRoot) {
|
||||
final file = p.basename(path);
|
||||
log.stderr(
|
||||
@@ -24,9 +27,7 @@ bool checkArtifactExists(String path,
|
||||
}
|
||||
if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound) {
|
||||
if (logError) {
|
||||
log.stderr(
|
||||
'Could not find $path. Have you built the full Dart SDK?',
|
||||
);
|
||||
log.stderr('Could not find $path. Have you built the full Dart SDK?');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,17 @@ class ArchiveFolder {
|
||||
final Channel channel;
|
||||
|
||||
Uri fileUri(String path, {required Stage stage}) => SdkCache.archiveUri(
|
||||
channel: channel, version: 'hash/$revision', stage: stage, path: path);
|
||||
channel: channel,
|
||||
version: 'hash/$revision',
|
||||
stage: stage,
|
||||
path: path,
|
||||
);
|
||||
|
||||
ArchiveFolder(
|
||||
{required this.version, required this.revision, required this.channel});
|
||||
ArchiveFolder({
|
||||
required this.version,
|
||||
required this.revision,
|
||||
required this.channel,
|
||||
});
|
||||
}
|
||||
|
||||
/// Cache for retrieving artifacts that are not shipped with the Dart SDK.
|
||||
@@ -45,18 +52,18 @@ class SdkCache {
|
||||
final StringSink _stderr;
|
||||
final io.ProcessResult Function(String) _setUserExecutable;
|
||||
|
||||
SdkCache(
|
||||
{required String directory,
|
||||
required this.verbose,
|
||||
http.Client Function()? createHttpClient,
|
||||
FileSystem? fs,
|
||||
StringSink? stderr,
|
||||
io.ProcessResult Function(String)? chmod,
|
||||
http.Client? httpClient})
|
||||
: _setUserExecutable = chmod ?? _defaultSetUserExecutable,
|
||||
_httpClient = httpClient ?? http.Client(),
|
||||
_stderr = stderr ?? io.stderr,
|
||||
fs = fs ?? LocalFileSystem() {
|
||||
SdkCache({
|
||||
required String directory,
|
||||
required this.verbose,
|
||||
http.Client Function()? createHttpClient,
|
||||
FileSystem? fs,
|
||||
StringSink? stderr,
|
||||
io.ProcessResult Function(String)? chmod,
|
||||
http.Client? httpClient,
|
||||
}) : _setUserExecutable = chmod ?? _defaultSetUserExecutable,
|
||||
_httpClient = httpClient ?? http.Client(),
|
||||
_stderr = stderr ?? io.stderr,
|
||||
fs = fs ?? LocalFileSystem() {
|
||||
this.directory = this.fs.directory(directory);
|
||||
}
|
||||
|
||||
@@ -69,25 +76,30 @@ class SdkCache {
|
||||
/// exists in the remote archive, or falls back to the latest revision if it
|
||||
/// does not (this may happen when Dart SDK is built locally from a local
|
||||
/// revision, or built with RBE, in which case there's no revision at all).
|
||||
Future<ArchiveFolder> resolveVersion(
|
||||
{required String version,
|
||||
required String revision,
|
||||
required String channelName,
|
||||
Target? host}) async {
|
||||
Future<ArchiveFolder> resolveVersion({
|
||||
required String version,
|
||||
required String revision,
|
||||
required String channelName,
|
||||
Target? host,
|
||||
}) async {
|
||||
host ??= Target.current;
|
||||
final channel = Channel.fromString(channelName);
|
||||
if (channel == null) {
|
||||
throw ArgumentError('Unsupported channel: "$channelName".');
|
||||
}
|
||||
|
||||
final folderFromArgs =
|
||||
ArchiveFolder(version: version, revision: revision, channel: channel);
|
||||
final folderFromArgs = ArchiveFolder(
|
||||
version: version,
|
||||
revision: revision,
|
||||
channel: channel,
|
||||
);
|
||||
if (channel != Channel.main) {
|
||||
// Past main channel, we always assume that given version and revision
|
||||
// must exist on the server.
|
||||
if (revision.isEmpty) {
|
||||
throw ArgumentError(
|
||||
'Channel "${channel.name}" requires valid revision.');
|
||||
'Channel "${channel.name}" requires valid revision.',
|
||||
);
|
||||
}
|
||||
|
||||
return folderFromArgs;
|
||||
@@ -104,12 +116,16 @@ class SdkCache {
|
||||
// commit revision, which does not exist on storage.
|
||||
if (revision.isNotEmpty) {
|
||||
// Check that the given revision exists.
|
||||
var exists =
|
||||
await _exists(folderFromArgs.fileUri('VERSION', stage: stage));
|
||||
var exists = await _exists(
|
||||
folderFromArgs.fileUri('VERSION', stage: stage),
|
||||
);
|
||||
|
||||
if (exists) {
|
||||
return ArchiveFolder(
|
||||
version: version, revision: revision, channel: channel);
|
||||
version: version,
|
||||
revision: revision,
|
||||
channel: channel,
|
||||
);
|
||||
} else {
|
||||
if (verbose) {
|
||||
_stderr.writeln('Cannot find revision $revision in an archive.');
|
||||
@@ -119,13 +135,18 @@ class SdkCache {
|
||||
|
||||
// No revision or invalid revision, checking the latest version.
|
||||
_stderr.writeln('Checking the latest available revision...');
|
||||
(version, revision) =
|
||||
await _getLatestVersion(channel: channel, stage: stage);
|
||||
(version, revision) = await _getLatestVersion(
|
||||
channel: channel,
|
||||
stage: stage,
|
||||
);
|
||||
if (verbose) {
|
||||
_stderr.writeln('Using revision $revision.');
|
||||
}
|
||||
return ArchiveFolder(
|
||||
version: version, revision: revision, channel: channel);
|
||||
version: version,
|
||||
revision: revision,
|
||||
channel: channel,
|
||||
);
|
||||
}
|
||||
|
||||
void _ensureExecutable(File destinationFile, OS hostOS) {
|
||||
@@ -141,16 +162,18 @@ class SdkCache {
|
||||
final chmodResult = _setUserExecutable(destinationFile.path);
|
||||
if (chmodResult.exitCode != 0) {
|
||||
throw SdkCacheException(
|
||||
'Cannot make ${destinationFile.path} executable, chmod failed.\n'
|
||||
'exitCode: ${chmodResult.exitCode}\n'
|
||||
'stderr: ${chmodResult.stderr}');
|
||||
'Cannot make ${destinationFile.path} executable, chmod failed.\n'
|
||||
'exitCode: ${chmodResult.exitCode}\n'
|
||||
'stderr: ${chmodResult.stderr}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> ensureGenSnapshot(
|
||||
{required ArchiveFolder archiveFolder,
|
||||
required Target target,
|
||||
Target? host}) {
|
||||
Future<String> ensureGenSnapshot({
|
||||
required ArchiveFolder archiveFolder,
|
||||
required Target target,
|
||||
Target? host,
|
||||
}) {
|
||||
host ??= Target.current;
|
||||
// Determine a file base name.
|
||||
var basename = 'gen_snapshot_${host}_$target';
|
||||
@@ -158,11 +181,12 @@ class SdkCache {
|
||||
basename = '$basename.exe';
|
||||
}
|
||||
return ensureArtifact(
|
||||
archiveFolder: archiveFolder,
|
||||
host: host,
|
||||
target: target,
|
||||
basename: basename,
|
||||
isExecutable: true);
|
||||
archiveFolder: archiveFolder,
|
||||
host: host,
|
||||
target: target,
|
||||
basename: basename,
|
||||
isExecutable: true,
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> ensureDartAotRuntime({
|
||||
@@ -172,11 +196,12 @@ class SdkCache {
|
||||
}) {
|
||||
host ??= Target.current;
|
||||
return ensureArtifact(
|
||||
archiveFolder: archiveFolder,
|
||||
basename: 'dartaotruntime_$target',
|
||||
target: target,
|
||||
host: host,
|
||||
isExecutable: false);
|
||||
archiveFolder: archiveFolder,
|
||||
basename: 'dartaotruntime_$target',
|
||||
target: target,
|
||||
host: host,
|
||||
isExecutable: false,
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> ensureArtifact({
|
||||
@@ -187,8 +212,9 @@ class SdkCache {
|
||||
required bool isExecutable,
|
||||
}) async {
|
||||
// Calculate the local path.
|
||||
var localFile =
|
||||
directory.childDirectory(archiveFolder.version).childFile(basename);
|
||||
var localFile = directory
|
||||
.childDirectory(archiveFolder.version)
|
||||
.childFile(basename);
|
||||
if (localFile.existsSync()) {
|
||||
if (isExecutable) {
|
||||
_ensureExecutable(localFile, host.os);
|
||||
@@ -197,11 +223,14 @@ class SdkCache {
|
||||
}
|
||||
|
||||
localFile.parent.createSync(recursive: true);
|
||||
final uri = archiveFolder.fileUri('sdk/$basename',
|
||||
stage: resolveStage(
|
||||
channel: archiveFolder.channel,
|
||||
isExecutable: isExecutable,
|
||||
hostOS: host.os));
|
||||
final uri = archiveFolder.fileUri(
|
||||
'sdk/$basename',
|
||||
stage: resolveStage(
|
||||
channel: archiveFolder.channel,
|
||||
isExecutable: isExecutable,
|
||||
hostOS: host.os,
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
localFile.writeAsBytesSync(await _download(uri));
|
||||
@@ -218,10 +247,22 @@ class SdkCache {
|
||||
}
|
||||
|
||||
/// For a given channel, find the latest available revision.
|
||||
Future<(String, String)> _getLatestVersion(
|
||||
{required Channel channel, required Stage stage}) async {
|
||||
final json = jsonDecode(utf8.decode(await _download(archiveUri(
|
||||
channel: channel, stage: stage, version: 'latest', path: 'VERSION'))));
|
||||
Future<(String, String)> _getLatestVersion({
|
||||
required Channel channel,
|
||||
required Stage stage,
|
||||
}) async {
|
||||
final json = jsonDecode(
|
||||
utf8.decode(
|
||||
await _download(
|
||||
archiveUri(
|
||||
channel: channel,
|
||||
stage: stage,
|
||||
version: 'latest',
|
||||
path: 'VERSION',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return (json['version'] as String, json['revision'] as String);
|
||||
}
|
||||
|
||||
@@ -250,10 +291,11 @@ class SdkCache {
|
||||
return response.bodyBytes;
|
||||
}
|
||||
|
||||
static Stage resolveStage(
|
||||
{required Channel channel,
|
||||
required bool isExecutable,
|
||||
required OS hostOS}) {
|
||||
static Stage resolveStage({
|
||||
required Channel channel,
|
||||
required bool isExecutable,
|
||||
required OS hostOS,
|
||||
}) {
|
||||
if (channel == Channel.main || !isExecutable) {
|
||||
return Stage.raw;
|
||||
}
|
||||
@@ -261,13 +303,15 @@ class SdkCache {
|
||||
return hostOS == OS.macOS ? Stage.signed : Stage.raw;
|
||||
}
|
||||
|
||||
static Uri archiveUri(
|
||||
{required Channel channel,
|
||||
required Stage stage,
|
||||
required String version,
|
||||
required String path}) =>
|
||||
Uri.https('storage.googleapis.com',
|
||||
'dart-archive/channels/${channel.name}/${stage.name}/$version/$path');
|
||||
static Uri archiveUri({
|
||||
required Channel channel,
|
||||
required Stage stage,
|
||||
required String version,
|
||||
required String path,
|
||||
}) => Uri.https(
|
||||
'storage.googleapis.com',
|
||||
'dart-archive/channels/${channel.name}/${stage.name}/$version/$path',
|
||||
);
|
||||
|
||||
/// Default implementation fdor making a [path] executable.
|
||||
///
|
||||
|
||||
@@ -121,10 +121,7 @@ abstract class Generator implements Comparable<Generator> {
|
||||
/// [scriptPath] is the path of the default target script
|
||||
/// (e.g., bin/foo.dart) **without** an extension. If null, the implicit run
|
||||
/// command will be output by default (e.g., dart run).
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) {
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln(' cd ${p.relative(directory)}');
|
||||
if (scriptPath != null) {
|
||||
@@ -217,9 +214,14 @@ class FileContents {
|
||||
String substituteVars(String str, Map<String, String> vars) {
|
||||
if (vars.keys.any((element) => element.contains(_nonValidSubstituteRegExp))) {
|
||||
throw ArgumentError.value(
|
||||
vars, 'vars', 'vars.keys can only contain letters.');
|
||||
vars,
|
||||
'vars',
|
||||
'vars.keys can only contain letters.',
|
||||
);
|
||||
}
|
||||
|
||||
return str.replaceAllMapped(
|
||||
_substituteRegExp, (match) => vars[match[1]!] ?? match[0]!);
|
||||
_substituteRegExp,
|
||||
(match) => vars[match[1]!] ?? match[0]!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,32 +8,28 @@ import 'common.dart' as common;
|
||||
/// A generator for a simple command-line application with argument parsing.
|
||||
class CliGenerator extends DefaultGenerator {
|
||||
CliGenerator()
|
||||
: super(
|
||||
'cli',
|
||||
'CLI Application',
|
||||
'A command-line application with basic argument parsing.',
|
||||
alternateId: 'console-cli',
|
||||
categories: const ['dart', 'cli'],
|
||||
) {
|
||||
: super(
|
||||
'cli',
|
||||
'CLI Application',
|
||||
'A command-line application with basic argument parsing.',
|
||||
alternateId: 'console-cli',
|
||||
categories: const ['dart', 'cli'],
|
||||
) {
|
||||
addFile('.gitignore', common.gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
addFile('pubspec.yaml', _pubspec);
|
||||
addFile('README.md', _readme);
|
||||
setEntrypoint(
|
||||
addFile('bin/__projectName__.dart', _mainDart),
|
||||
);
|
||||
setEntrypoint(addFile('bin/__projectName__.dart', _mainDart));
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
super.getInstallInstructions(directory, scriptPath: 'bin/$scriptPath');
|
||||
}
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: A sample command-line application with basic argument parsing.
|
||||
version: 0.0.1
|
||||
|
||||
@@ -8,34 +8,30 @@ import 'common.dart' as common;
|
||||
/// A generator for a hello world command-line application.
|
||||
class ConsoleGenerator extends DefaultGenerator {
|
||||
ConsoleGenerator()
|
||||
: super(
|
||||
'console',
|
||||
'Console Application',
|
||||
'A command-line application.',
|
||||
alternateId: 'console-full',
|
||||
categories: const ['dart', 'console'],
|
||||
) {
|
||||
: super(
|
||||
'console',
|
||||
'Console Application',
|
||||
'A command-line application.',
|
||||
alternateId: 'console-full',
|
||||
categories: const ['dart', 'console'],
|
||||
) {
|
||||
addFile('.gitignore', common.gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
addFile('pubspec.yaml', _pubspec);
|
||||
addFile('README.md', _readme);
|
||||
setEntrypoint(
|
||||
addFile('bin/__projectName__.dart', _mainDart),
|
||||
);
|
||||
setEntrypoint(addFile('bin/__projectName__.dart', _mainDart));
|
||||
addFile('lib/__projectName__.dart', _libDart);
|
||||
addFile('test/__projectName___test.dart', _testDart);
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
super.getInstallInstructions(directory);
|
||||
}
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: A sample command-line application.
|
||||
version: 1.0.0
|
||||
|
||||
@@ -8,32 +8,28 @@ import 'common.dart' as common;
|
||||
/// A generator for a simple command-line application.
|
||||
class ConsoleSimpleGenerator extends DefaultGenerator {
|
||||
ConsoleSimpleGenerator()
|
||||
: super(
|
||||
'console-simple',
|
||||
'Simple Console Application',
|
||||
'A simple command-line application.',
|
||||
deprecated: true,
|
||||
categories: const ['dart', 'console'],
|
||||
) {
|
||||
: super(
|
||||
'console-simple',
|
||||
'Simple Console Application',
|
||||
'A simple command-line application.',
|
||||
deprecated: true,
|
||||
categories: const ['dart', 'console'],
|
||||
) {
|
||||
addFile('.gitignore', common.gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
addFile('pubspec.yaml', _pubspec);
|
||||
addFile('README.md', _readme);
|
||||
setEntrypoint(
|
||||
addFile('bin/__projectName__.dart', mainSrc),
|
||||
);
|
||||
setEntrypoint(addFile('bin/__projectName__.dart', mainSrc));
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
super.getInstallInstructions(directory);
|
||||
}
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: A simple command-line application.
|
||||
version: 1.0.0
|
||||
|
||||
@@ -8,31 +8,26 @@ import 'common.dart' as common;
|
||||
/// A generator for a simple command-line application.
|
||||
class PackageGenerator extends DefaultGenerator {
|
||||
PackageGenerator()
|
||||
: super(
|
||||
'package',
|
||||
'Dart Package',
|
||||
'A package containing shared Dart libraries.',
|
||||
categories: const ['dart'],
|
||||
alternateId: 'package-simple',
|
||||
) {
|
||||
: super(
|
||||
'package',
|
||||
'Dart Package',
|
||||
'A package containing shared Dart libraries.',
|
||||
categories: const ['dart'],
|
||||
alternateId: 'package-simple',
|
||||
) {
|
||||
addFile('.gitignore', _gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
addFile('pubspec.yaml', _pubspec);
|
||||
addFile('README.md', _readme);
|
||||
addFile('example/__projectName___example.dart', _exampleDart);
|
||||
setEntrypoint(
|
||||
addFile('lib/__projectName__.dart', _libDart),
|
||||
);
|
||||
setEntrypoint(addFile('lib/__projectName__.dart', _libDart));
|
||||
addFile('lib/src/__projectName___base.dart', _libSrcDart);
|
||||
addFile('test/__projectName___test.dart', _testDart);
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
super.getInstallInstructions(
|
||||
directory,
|
||||
scriptPath: 'example/${scriptPath}_example',
|
||||
@@ -49,7 +44,8 @@ final String _gitignore = '''
|
||||
pubspec.lock
|
||||
''';
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: A starting point for Dart libraries or applications.
|
||||
version: 1.0.0
|
||||
|
||||
@@ -8,12 +8,12 @@ import 'common.dart' as common;
|
||||
/// A generator for a server app using `package:shelf`.
|
||||
class ServerShelfGenerator extends DefaultGenerator {
|
||||
ServerShelfGenerator()
|
||||
: super(
|
||||
'server-shelf',
|
||||
'Server app',
|
||||
'A server app using package:shelf.',
|
||||
categories: const ['dart', 'server'],
|
||||
) {
|
||||
: super(
|
||||
'server-shelf',
|
||||
'Server app',
|
||||
'A server app using package:shelf.',
|
||||
categories: const ['dart', 'server'],
|
||||
) {
|
||||
addFile('.gitignore', common.gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
@@ -22,23 +22,16 @@ class ServerShelfGenerator extends DefaultGenerator {
|
||||
addFile('Dockerfile', _dockerfile);
|
||||
addFile('.dockerignore', _dockerignore);
|
||||
addFile('test/server_test.dart', _test);
|
||||
setEntrypoint(
|
||||
addFile('bin/server.dart', _main),
|
||||
);
|
||||
setEntrypoint(addFile('bin/server.dart', _main));
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
super.getInstallInstructions(
|
||||
directory,
|
||||
scriptPath: 'bin/server',
|
||||
);
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
super.getInstallInstructions(directory, scriptPath: 'bin/server');
|
||||
}
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: A server app using the shelf package and Docker.
|
||||
version: 1.0.0
|
||||
|
||||
@@ -10,36 +10,32 @@ import 'common.dart' as common;
|
||||
/// A generator for a uber-simple web application.
|
||||
class WebGenerator extends DefaultGenerator {
|
||||
WebGenerator()
|
||||
: super(
|
||||
'web',
|
||||
'Bare-bones Web App',
|
||||
'A web app that uses only core Dart libraries.',
|
||||
alternateId: 'web-simple',
|
||||
categories: const ['dart', 'web'],
|
||||
) {
|
||||
: super(
|
||||
'web',
|
||||
'Bare-bones Web App',
|
||||
'A web app that uses only core Dart libraries.',
|
||||
alternateId: 'web-simple',
|
||||
categories: const ['dart', 'web'],
|
||||
) {
|
||||
addFile('.gitignore', common.gitignore);
|
||||
addFile('analysis_options.yaml', common.analysisOptions);
|
||||
addFile('CHANGELOG.md', common.changelog);
|
||||
addFile('pubspec.yaml', _pubspec);
|
||||
addFile('README.md', _readme);
|
||||
addFile('web/index.html', _index);
|
||||
setEntrypoint(
|
||||
addFile('web/main.dart', _main),
|
||||
);
|
||||
setEntrypoint(addFile('web/main.dart', _main));
|
||||
addFile('web/styles.css', _styles);
|
||||
}
|
||||
|
||||
@override
|
||||
String getInstallInstructions(
|
||||
String directory, {
|
||||
String? scriptPath,
|
||||
}) =>
|
||||
String getInstallInstructions(String directory, {String? scriptPath}) =>
|
||||
' cd ${p.relative(directory)}\n'
|
||||
' dart pub global activate webdev\n'
|
||||
' webdev serve';
|
||||
}
|
||||
|
||||
final String _pubspec = '''
|
||||
final String _pubspec =
|
||||
'''
|
||||
name: __projectName__
|
||||
description: An absolute bare-bones web app.
|
||||
version: 1.0.0
|
||||
|
||||
@@ -11,7 +11,8 @@ import 'sdk.dart';
|
||||
|
||||
const String _dartDirectoryName = '.dart';
|
||||
|
||||
const String analyticsDisabledNoticeMessage = 'Analytics reporting disabled. '
|
||||
const String analyticsDisabledNoticeMessage =
|
||||
'Analytics reporting disabled. '
|
||||
'In order to enable it, run: dart --enable-analytics';
|
||||
|
||||
/// Create the `Analytics` instance to be used to report analytics.
|
||||
@@ -101,16 +102,16 @@ bool _isRunningOnBot() {
|
||||
final Map<String, String> env = Platform.environment;
|
||||
|
||||
if (
|
||||
// Explicitly stated to not be a bot.
|
||||
env['BOT'] == 'false'
|
||||
// Set by the IDEs to the IDE name, so a strong signal that this is
|
||||
// not a bot.
|
||||
||
|
||||
env.containsKey('FLUTTER_HOST')
|
||||
// When set, GA logs to a local file (normally for tests) so we don't
|
||||
// need to filter.
|
||||
||
|
||||
env.containsKey('FLUTTER_ANALYTICS_LOG_FILE')) {
|
||||
// Explicitly stated to not be a bot.
|
||||
env['BOT'] == 'false'
|
||||
// Set by the IDEs to the IDE name, so a strong signal that this is
|
||||
// not a bot.
|
||||
||
|
||||
env.containsKey('FLUTTER_HOST')
|
||||
// When set, GA logs to a local file (normally for tests) so we don't
|
||||
// need to filter.
|
||||
||
|
||||
env.containsKey('FLUTTER_ANALYTICS_LOG_FILE')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,33 +127,26 @@ bool _isRunningOnBot() {
|
||||
env['TRAVIS'] == 'true' ||
|
||||
env['CONTINUOUS_INTEGRATION'] == 'true' ||
|
||||
env.containsKey('CI') // Travis and AppVeyor
|
||||
|
||||
// https://www.appveyor.com/docs/environment-variables/
|
||||
||
|
||||
env.containsKey('APPVEYOR')
|
||||
|
||||
// https://cirrus-ci.org/guide/writing-tasks/#environment-variables
|
||||
||
|
||||
env.containsKey('CIRRUS_CI')
|
||||
|
||||
// https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
|
||||
||
|
||||
(env.containsKey('AWS_REGION') && env.containsKey('CODEBUILD_INITIATOR'))
|
||||
|
||||
// https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-belowJenkinsSetEnvironmentVariables
|
||||
||
|
||||
env.containsKey('JENKINS_URL')
|
||||
|
||||
// https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
|
||||
||
|
||||
env.containsKey('GITHUB_ACTIONS')
|
||||
|
||||
// Properties on Flutter's Chrome Infra bots.
|
||||
||
|
||||
env['CHROME_HEADLESS'] == '1' ||
|
||||
env.containsKey('BUILDBOT_BUILDERNAME') ||
|
||||
env.containsKey('SWARMING_TASK_ID')
|
||||
|
||||
// Property when running on borg.
|
||||
||
|
||||
env.containsKey('BORG_ALLOC_DIR');
|
||||
|
||||
@@ -76,25 +76,47 @@ ArgParser globalDartdevOptionsParser({bool verbose = false}) {
|
||||
usageLineLength: dartdevUsageLineLength,
|
||||
allowTrailingOptions: false,
|
||||
);
|
||||
argParser.addFlag('verbose',
|
||||
abbr: 'v', negatable: false, help: 'Show additional command output.');
|
||||
argParser.addFlag('version',
|
||||
negatable: false, help: 'Print the Dart SDK version.');
|
||||
argParser.addFlag('enable-analytics',
|
||||
negatable: false, help: 'Enable analytics.');
|
||||
argParser.addFlag('disable-analytics',
|
||||
negatable: false, help: 'Disable analytics.');
|
||||
argParser.addFlag('disable-telemetry',
|
||||
negatable: false, help: 'Disable telemetry.', hide: true);
|
||||
argParser.addFlag(
|
||||
'verbose',
|
||||
abbr: 'v',
|
||||
negatable: false,
|
||||
help: 'Show additional command output.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'version',
|
||||
negatable: false,
|
||||
help: 'Print the Dart SDK version.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'enable-analytics',
|
||||
negatable: false,
|
||||
help: 'Enable analytics.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'disable-analytics',
|
||||
negatable: false,
|
||||
help: 'Disable analytics.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'disable-telemetry',
|
||||
negatable: false,
|
||||
help: 'Disable telemetry.',
|
||||
hide: true,
|
||||
);
|
||||
|
||||
argParser.addFlag('diagnostics',
|
||||
negatable: false, help: 'Show tool diagnostic output.', hide: !verbose);
|
||||
argParser.addFlag(
|
||||
'diagnostics',
|
||||
negatable: false,
|
||||
help: 'Show tool diagnostic output.',
|
||||
hide: !verbose,
|
||||
);
|
||||
|
||||
argParser.addFlag(
|
||||
'analytics',
|
||||
defaultsTo: true,
|
||||
negatable: true,
|
||||
help: 'Allow or disallow analytics for this `dart *` run without '
|
||||
help:
|
||||
'Allow or disallow analytics for this `dart *` run without '
|
||||
'changing the analytics configuration. '
|
||||
'Deprecated: use `--suppress-analytics` instead.',
|
||||
hide: true,
|
||||
@@ -103,7 +125,8 @@ ArgParser globalDartdevOptionsParser({bool verbose = false}) {
|
||||
argParser.addFlag(
|
||||
'suppress-analytics',
|
||||
negatable: false,
|
||||
help: 'Disallow analytics for this `dart *` run without changing the '
|
||||
help:
|
||||
'Disallow analytics for this `dart *` run without changing the '
|
||||
'analytics configuration.',
|
||||
);
|
||||
return argParser;
|
||||
@@ -336,10 +359,12 @@ class MarkdownTable {
|
||||
var widths = <int>[];
|
||||
|
||||
for (int col = 0; col < header.length; col++) {
|
||||
var width = _data.map((row) {
|
||||
var item = row.length >= col ? row[col] : null;
|
||||
return item?.value.length ?? 0;
|
||||
}).reduce(math.max);
|
||||
var width = _data
|
||||
.map((row) {
|
||||
var item = row.length >= col ? row[col] : null;
|
||||
return item?.value.length ?? 0;
|
||||
})
|
||||
.reduce(math.max);
|
||||
widths.add(math.max(width, _minWidth));
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ abstract class VmInteropHandler {
|
||||
script,
|
||||
packageConfigOverride,
|
||||
markMainIsolateAsSystemIsolate,
|
||||
argsList
|
||||
argsList,
|
||||
];
|
||||
port.send(message);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ name: dartdev
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
sdk: ^3.11.0
|
||||
|
||||
resolution: workspace
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ import 'experiment_util.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
List<Map<String, Object?>> extractAnalytics(io.ProcessResult result) {
|
||||
return LineSplitter.split(result.stderr)
|
||||
.where((line) => line.startsWith('[analytics]: '))
|
||||
.map((line) {
|
||||
return LineSplitter.split(
|
||||
result.stderr,
|
||||
).where((line) => line.startsWith('[analytics]: ')).map((line) {
|
||||
return (json.decode(line.substring('[analytics]: '.length)) as Map)
|
||||
.cast<String, Object?>();
|
||||
}).toList();
|
||||
@@ -35,27 +35,24 @@ void main() {
|
||||
});
|
||||
|
||||
test('--no-analytics', () async {
|
||||
final result =
|
||||
await command.runCommand(command.parse(['--no-analytics']));
|
||||
final result = await command.runCommand(
|
||||
command.parse(['--no-analytics']),
|
||||
);
|
||||
expect(result, 0);
|
||||
expect(command.unifiedAnalytics.telemetryEnabled, false);
|
||||
});
|
||||
|
||||
test('--suppress-analytics', () async {
|
||||
final result =
|
||||
await command.runCommand(command.parse(['--suppress-analytics']));
|
||||
final result = await command.runCommand(
|
||||
command.parse(['--suppress-analytics']),
|
||||
);
|
||||
expect(result, 0);
|
||||
expect(command.unifiedAnalytics.telemetryEnabled, false);
|
||||
});
|
||||
|
||||
test('--suppress-analytics and --disable-analytics', () async {
|
||||
final result = await command.runCommand(
|
||||
command.parse(
|
||||
[
|
||||
'--suppress-analytics',
|
||||
'--disable-analytics',
|
||||
],
|
||||
),
|
||||
command.parse(['--suppress-analytics', '--disable-analytics']),
|
||||
);
|
||||
// --suppress-analytics and --disable-analytics can't be provided
|
||||
// together to ensure analytics state properly sticks.
|
||||
@@ -64,12 +61,7 @@ void main() {
|
||||
|
||||
test('--suppress-analytics and --enable-analytics', () async {
|
||||
final result = await command.runCommand(
|
||||
command.parse(
|
||||
[
|
||||
'--suppress-analytics',
|
||||
'--enable-analytics',
|
||||
],
|
||||
),
|
||||
command.parse(['--suppress-analytics', '--enable-analytics']),
|
||||
);
|
||||
// --suppress-analytics and --enable-analytics can't be provided
|
||||
// together to ensure analytics state properly sticks.
|
||||
@@ -82,10 +74,7 @@ void main() {
|
||||
final p = project();
|
||||
final analytics = await p.runLocalWithFakeAnalytics(['help']);
|
||||
expect(analytics.sentEvents, [
|
||||
Event.dartCliCommandExecuted(
|
||||
name: 'help',
|
||||
enabledExperiments: '',
|
||||
)
|
||||
Event.dartCliCommandExecuted(name: 'help', enabledExperiments: ''),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -98,10 +87,7 @@ void main() {
|
||||
path.join(io.Directory.systemTemp.createTempSync().path, 'name'),
|
||||
]);
|
||||
expect(analytics.sentEvents, [
|
||||
Event.dartCliCommandExecuted(
|
||||
name: 'create',
|
||||
enabledExperiments: '',
|
||||
),
|
||||
Event.dartCliCommandExecuted(name: 'create', enabledExperiments: ''),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -116,7 +102,7 @@ void main() {
|
||||
() async {
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dependencies': {'lints': '2.0.1'}
|
||||
'dependencies': {'lints': '2.0.1'},
|
||||
},
|
||||
);
|
||||
final analytics = await p.runLocalWithFakeAnalytics(['pub', 'get']);
|
||||
@@ -138,13 +124,13 @@ void main() {
|
||||
|
||||
test('format', () async {
|
||||
final p = project();
|
||||
final analytics =
|
||||
await p.runLocalWithFakeAnalytics(['format', '-l80', '.']);
|
||||
final analytics = await p.runLocalWithFakeAnalytics([
|
||||
'format',
|
||||
'-l80',
|
||||
'.',
|
||||
]);
|
||||
expect(analytics.sentEvents, [
|
||||
Event.dartCliCommandExecuted(
|
||||
name: 'format',
|
||||
enabledExperiments: '',
|
||||
),
|
||||
Event.dartCliCommandExecuted(name: 'format', enabledExperiments: ''),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -155,13 +141,10 @@ void main() {
|
||||
'--no-pause-isolates-on-exit',
|
||||
'--enable-asserts',
|
||||
'lib/main.dart',
|
||||
'--argument'
|
||||
'--argument',
|
||||
]);
|
||||
expect(analytics.sentEvents, [
|
||||
Event.dartCliCommandExecuted(
|
||||
name: 'run',
|
||||
enabledExperiments: '',
|
||||
),
|
||||
Event.dartCliCommandExecuted(name: 'run', enabledExperiments: ''),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -83,22 +83,16 @@ void defineAnalysisError() {
|
||||
var errors = <AnalysisError>[
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {
|
||||
'file': 'a.dart',
|
||||
}
|
||||
'location': {'file': 'a.dart'},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'WARNING',
|
||||
'location': {
|
||||
'file': 'a.dart',
|
||||
}
|
||||
'location': {'file': 'a.dart'},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'ERROR',
|
||||
'location': {
|
||||
'file': 'a.dart',
|
||||
}
|
||||
})
|
||||
'location': {'file': 'a.dart'},
|
||||
}),
|
||||
];
|
||||
|
||||
errors.sort();
|
||||
@@ -113,22 +107,16 @@ void defineAnalysisError() {
|
||||
var errors = <AnalysisError>[
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {
|
||||
'file': 'c.dart',
|
||||
}
|
||||
'location': {'file': 'c.dart'},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {
|
||||
'file': 'b.dart',
|
||||
}
|
||||
'location': {'file': 'b.dart'},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {
|
||||
'file': 'a.dart',
|
||||
}
|
||||
})
|
||||
'location': {'file': 'a.dart'},
|
||||
}),
|
||||
];
|
||||
|
||||
errors.sort();
|
||||
@@ -143,16 +131,16 @@ void defineAnalysisError() {
|
||||
var errors = <AnalysisError>[
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 8}
|
||||
'location': {'file': 'a.dart', 'offset': 8},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 6}
|
||||
'location': {'file': 'a.dart', 'offset': 6},
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 4}
|
||||
})
|
||||
'location': {'file': 'a.dart', 'offset': 4},
|
||||
}),
|
||||
];
|
||||
|
||||
errors.sort();
|
||||
@@ -168,18 +156,18 @@ void defineAnalysisError() {
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 8},
|
||||
'message': 'C'
|
||||
'message': 'C',
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 6},
|
||||
'message': 'B'
|
||||
'message': 'B',
|
||||
}),
|
||||
AnalysisError({
|
||||
'severity': 'INFO',
|
||||
'location': {'file': 'a.dart', 'offset': 4},
|
||||
'message': 'A'
|
||||
})
|
||||
'message': 'A',
|
||||
}),
|
||||
];
|
||||
|
||||
errors.sort();
|
||||
@@ -251,8 +239,10 @@ void defineAnalyze() {
|
||||
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.stderr,
|
||||
contains("Directory or file doesn't exist: /no/such/dir1/"));
|
||||
expect(
|
||||
result.stderr,
|
||||
contains("Directory or file doesn't exist: /no/such/dir1/"),
|
||||
);
|
||||
expect(result.stderr, contains(_analyzeUsageText));
|
||||
});
|
||||
|
||||
@@ -321,14 +311,16 @@ void defineAnalyze() {
|
||||
});
|
||||
|
||||
test('error with context message', () async {
|
||||
p = project(mainSrc: '''
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
part 'a.dart';
|
||||
|
||||
class B extends A {
|
||||
@override
|
||||
void m(String p) {}
|
||||
}
|
||||
''');
|
||||
''',
|
||||
);
|
||||
p.file('lib${path.separator}a.dart', '''
|
||||
part of 'main.dart';
|
||||
|
||||
@@ -348,8 +340,9 @@ class A {
|
||||
|
||||
test('warning --fatal-warnings', () async {
|
||||
p = project(
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions);
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions,
|
||||
);
|
||||
var result = await p.runAnalyze(['--fatal-warnings', p.dirPath]);
|
||||
|
||||
expect(result.exitCode, equals(2));
|
||||
@@ -359,8 +352,9 @@ class A {
|
||||
|
||||
test('warning implicit --fatal-warnings', () async {
|
||||
p = project(
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions);
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions,
|
||||
);
|
||||
var result = await p.runAnalyze([p.dirPath]);
|
||||
|
||||
expect(result.exitCode, equals(2));
|
||||
@@ -370,8 +364,9 @@ class A {
|
||||
|
||||
test('warning --no-fatal-warnings', () async {
|
||||
p = project(
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions);
|
||||
mainSrc: _unusedImportCodeSnippet,
|
||||
analysisOptions: _unusedImportAnalysisOptions,
|
||||
);
|
||||
var result = await p.runAnalyze(['--no-fatal-warnings', p.dirPath]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
@@ -412,9 +407,7 @@ analyzer:
|
||||
});
|
||||
|
||||
test('TODOs hidden by default', () async {
|
||||
p = project(
|
||||
mainSrc: _todoAsWarningCodeSnippet,
|
||||
);
|
||||
p = project(mainSrc: _todoAsWarningCodeSnippet);
|
||||
var result = await p.runAnalyze([p.dirPath]);
|
||||
|
||||
expect(result.exitCode, equals(0));
|
||||
@@ -466,22 +459,28 @@ analyzer:
|
||||
expect(result.stderr, contains("Unknown experiment(s): 'bad'"));
|
||||
});
|
||||
|
||||
test('--enable-experiment with a non-experimental feature', () async {
|
||||
p = project();
|
||||
var result = await p.runAnalyze(['--enable-experiment=records']);
|
||||
test(
|
||||
'--enable-experiment with a non-experimental feature',
|
||||
() async {
|
||||
p = project();
|
||||
var result = await p.runAnalyze(['--enable-experiment=records']);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, contains('No issues found!'));
|
||||
expect(result.stderr, contains("'records' is now enabled by default"));
|
||||
}, skip: 'records are enabled by default in 3.0');
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, contains('No issues found!'));
|
||||
expect(result.stderr, contains("'records' is now enabled by default"));
|
||||
},
|
||||
skip: 'records are enabled by default in 3.0',
|
||||
);
|
||||
|
||||
test('--verbose', () async {
|
||||
p = project(mainSrc: '''
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
int f() {
|
||||
var result = one + 2;
|
||||
var one = 1;
|
||||
return result;
|
||||
}''');
|
||||
}''',
|
||||
);
|
||||
var result = await p.runAnalyze(['--verbose', p.dirPath]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
@@ -489,7 +488,9 @@ int f() {
|
||||
var stdout = result.stdout;
|
||||
expect(stdout, contains("The declaration of 'one' is here"));
|
||||
expect(
|
||||
stdout, contains('Try moving the declaration to before the first use'));
|
||||
stdout,
|
||||
contains('Try moving the declaration to before the first use'),
|
||||
);
|
||||
expect(stdout, contains('https://dart.dev'));
|
||||
expect(stdout, contains('referenced_before_declaration'));
|
||||
});
|
||||
@@ -499,11 +500,13 @@ int f() {
|
||||
final foo = project(name: 'foo');
|
||||
foo.file('lib${path.separator}foo.dart', 'var my_foo = 0;');
|
||||
|
||||
p = project(mainSrc: '''
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
import 'package:foo/foo.dart';
|
||||
void f() {
|
||||
my_foo;
|
||||
}''');
|
||||
}''',
|
||||
);
|
||||
p.file('my_packages.json', '''
|
||||
{
|
||||
"configVersion": 2,
|
||||
@@ -529,10 +532,7 @@ void f() {
|
||||
|
||||
test('not existing', () async {
|
||||
p = project();
|
||||
var result = await p.runAnalyze([
|
||||
'--packages=no.such.file',
|
||||
p.dirPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--packages=no.such.file', p.dirPath]);
|
||||
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stderr, contains("The file doesn't exist: no.such.file"));
|
||||
@@ -544,10 +544,7 @@ void f() {
|
||||
var cache = project(name: 'cache');
|
||||
|
||||
p = project(mainSrc: 'var v = 0;');
|
||||
var result = await p.runAnalyze([
|
||||
'--cache=${cache.dirPath}',
|
||||
p.mainPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--cache=${cache.dirPath}', p.mainPath]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -567,7 +564,7 @@ void f() {
|
||||
'offset': 362,
|
||||
'length': 72,
|
||||
'startLine': 15,
|
||||
'startColumn': 4
|
||||
'startColumn': 4,
|
||||
},
|
||||
'message': 'Foo bar baz.',
|
||||
'hasFix': false,
|
||||
@@ -580,7 +577,7 @@ void f() {
|
||||
'offset': 19,
|
||||
'length': 1,
|
||||
'startLine': 2,
|
||||
'startColumn': 9
|
||||
'startColumn': 9,
|
||||
},
|
||||
'message':
|
||||
"Local variable 's' can't be referenced before it is declared.",
|
||||
@@ -596,11 +593,11 @@ void f() {
|
||||
'offset': 29,
|
||||
'length': 1,
|
||||
'startLine': 3,
|
||||
'startColumn': 7
|
||||
}
|
||||
}
|
||||
'startColumn': 7,
|
||||
},
|
||||
},
|
||||
],
|
||||
'hasFix': false
|
||||
'hasFix': false,
|
||||
};
|
||||
|
||||
group('default', () {
|
||||
@@ -618,18 +615,21 @@ void f() {
|
||||
expect(stdout, contains('dead_code'));
|
||||
});
|
||||
|
||||
test('prioritizes errors in analysis_options.yaml (with other errors)',
|
||||
() async {
|
||||
p = project(
|
||||
test(
|
||||
'prioritizes errors in analysis_options.yaml (with other errors)',
|
||||
() async {
|
||||
p = project(
|
||||
mainSrc: 'int get foo => null;\n',
|
||||
analysisOptions: 'include: package:lints/recommended.yaml\nf');
|
||||
var result = await p.runAnalyze([]);
|
||||
analysisOptions: 'include: package:lints/recommended.yaml\nf',
|
||||
);
|
||||
var result = await p.runAnalyze([]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
|
||||
final stdout = result.stdout;
|
||||
final expectedOutput = '''
|
||||
final stdout = result.stdout;
|
||||
final expectedOutput =
|
||||
'''
|
||||
Analyzing myapp...
|
||||
|
||||
Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might result in either invalid diagnostics being produced or valid diagnostics being missed.
|
||||
@@ -642,21 +642,24 @@ Errors in remaining files.
|
||||
|
||||
2 issues found.
|
||||
''';
|
||||
expect(stdout.trim(), expectedOutput.trim());
|
||||
});
|
||||
expect(stdout.trim(), expectedOutput.trim());
|
||||
},
|
||||
);
|
||||
|
||||
test('prioritizes errors in analysis_options.yaml (without other errors)',
|
||||
() async {
|
||||
p = project(
|
||||
test(
|
||||
'prioritizes errors in analysis_options.yaml (without other errors)',
|
||||
() async {
|
||||
p = project(
|
||||
mainSrc: 'int get foo => 1;\n',
|
||||
analysisOptions: 'include: package:lints/recommended.yaml\nf');
|
||||
var result = await p.runAnalyze([]);
|
||||
analysisOptions: 'include: package:lints/recommended.yaml\nf',
|
||||
);
|
||||
var result = await p.runAnalyze([]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
|
||||
final stdout = result.stdout;
|
||||
final expectedOutput = '''
|
||||
final stdout = result.stdout;
|
||||
final expectedOutput = '''
|
||||
Analyzing myapp...
|
||||
|
||||
Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might result in either invalid diagnostics being produced or valid diagnostics being missed.
|
||||
@@ -665,13 +668,15 @@ Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might r
|
||||
|
||||
1 issue found.
|
||||
''';
|
||||
expect(stdout.trim(), expectedOutput.trim());
|
||||
});
|
||||
expect(stdout.trim(), expectedOutput.trim());
|
||||
},
|
||||
);
|
||||
|
||||
test('does not prioritize warnings in analysis_options.yaml', () async {
|
||||
p = project(
|
||||
mainSrc: 'int get foo => null;\n',
|
||||
analysisOptions: 'include: package:lints/recommended.yaml');
|
||||
mainSrc: 'int get foo => null;\n',
|
||||
analysisOptions: 'include: package:lints/recommended.yaml',
|
||||
);
|
||||
var result = await p.runAnalyze([]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
@@ -681,7 +686,8 @@ Errors were found in 'pubspec.yaml' and/or 'analysis_options.yaml' which might r
|
||||
result.stdout.toString(),
|
||||
filePath: p.dirPath,
|
||||
);
|
||||
final expectedOutput = '''
|
||||
final expectedOutput =
|
||||
'''
|
||||
Analyzing myapp...
|
||||
|
||||
error - lib${path.separator}main.dart:1:16 - A value of type 'Null' can't be returned from the function 'foo' because it has a return type of 'int'. - return_of_invalid_type
|
||||
@@ -697,10 +703,7 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
group('--format=json', () {
|
||||
test('no errors', () async {
|
||||
p = project(mainSrc: 'int get foo => 1;\n');
|
||||
var result = await p.runAnalyze([
|
||||
'--format=json',
|
||||
p.mainPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--format=json', p.mainPath]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -710,10 +713,7 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
});
|
||||
test('one error', () async {
|
||||
p = project(mainSrc: "int get foo => 'str';\n");
|
||||
var result = await p.runAnalyze([
|
||||
'--format=json',
|
||||
p.mainPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--format=json', p.mainPath]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -721,9 +721,11 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
final escapedSeparator = path.separator.replaceAll('\\', '\\\\');
|
||||
final stdout = result.stdout.trim();
|
||||
expect(
|
||||
stdout,
|
||||
startsWith(
|
||||
'{"version":1,"diagnostics":[{"code":"return_of_invalid_type",'));
|
||||
stdout,
|
||||
startsWith(
|
||||
'{"version":1,"diagnostics":[{"code":"return_of_invalid_type",',
|
||||
),
|
||||
);
|
||||
expect(stdout, endsWith('}'));
|
||||
expect(stdout, contains('lib${escapedSeparator}main.dart'));
|
||||
expect(stdout, contains('"line":1,"column":16'));
|
||||
@@ -749,11 +751,12 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
expect(logger.stderrBuffer, isEmpty);
|
||||
final stdout = logger.stdoutBuffer.toString().trim();
|
||||
expect(
|
||||
stdout,
|
||||
'{"version":1,"diagnostics":[{"code":"dead_code","severity":"INFO",'
|
||||
'"type":"TODO","location":{"file":"lib/test.dart","range":{'
|
||||
'"start":{"offset":362,"line":15,"column":4},"end":{"offset":434,'
|
||||
'"line":16,"column":12}}},"problemMessage":"Foo bar baz."}]}');
|
||||
stdout,
|
||||
'{"version":1,"diagnostics":[{"code":"dead_code","severity":"INFO",'
|
||||
'"type":"TODO","location":{"file":"lib/test.dart","range":{'
|
||||
'"start":{"offset":362,"line":15,"column":4},"end":{"offset":434,'
|
||||
'"line":16,"column":12}}},"problemMessage":"Foo bar baz."}]}',
|
||||
);
|
||||
});
|
||||
test('full', () {
|
||||
final logger = TestLogger(false);
|
||||
@@ -764,31 +767,29 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
expect(logger.stderrBuffer, isEmpty);
|
||||
final stdout = logger.stdoutBuffer.toString().trim();
|
||||
expect(
|
||||
stdout,
|
||||
'{"version":1,"diagnostics":[{'
|
||||
'"code":"referenced_before_declaration","severity":"ERROR",'
|
||||
'"type":"COMPILE_TIME_ERROR","location":{"file":"lib/test.dart",'
|
||||
'"range":{"start":{"offset":19,"line":2,"column":9},"end":{'
|
||||
'"offset":20,"line":null,"column":null}}},"problemMessage":'
|
||||
'"Local variable \'s\' can\'t be referenced before it is declared.",'
|
||||
'"correctionMessage":"Try moving the declaration to before the'
|
||||
' first use, or renaming the local variable so that it doesn\'t hide'
|
||||
' a name from an enclosing scope.","contextMessages":[{"location":{'
|
||||
'"file":"lib/test.dart","range":{"start":{"offset":29,"line":3,'
|
||||
'"column":7},"end":{"offset":30,"line":null,"column":null}}},'
|
||||
'"message":"The declaration of \'s\' is on line 3."}],'
|
||||
'"documentation":'
|
||||
'"https:://dart.dev/diagnostics/referenced_before_declaration"}]}');
|
||||
stdout,
|
||||
'{"version":1,"diagnostics":[{'
|
||||
'"code":"referenced_before_declaration","severity":"ERROR",'
|
||||
'"type":"COMPILE_TIME_ERROR","location":{"file":"lib/test.dart",'
|
||||
'"range":{"start":{"offset":19,"line":2,"column":9},"end":{'
|
||||
'"offset":20,"line":null,"column":null}}},"problemMessage":'
|
||||
'"Local variable \'s\' can\'t be referenced before it is declared.",'
|
||||
'"correctionMessage":"Try moving the declaration to before the'
|
||||
' first use, or renaming the local variable so that it doesn\'t hide'
|
||||
' a name from an enclosing scope.","contextMessages":[{"location":{'
|
||||
'"file":"lib/test.dart","range":{"start":{"offset":29,"line":3,'
|
||||
'"column":7},"end":{"offset":30,"line":null,"column":null}}},'
|
||||
'"message":"The declaration of \'s\' is on line 3."}],'
|
||||
'"documentation":'
|
||||
'"https:://dart.dev/diagnostics/referenced_before_declaration"}]}',
|
||||
);
|
||||
});
|
||||
});
|
||||
group('machine', () {
|
||||
group('--format=machine', () {
|
||||
test('no errors', () async {
|
||||
p = project(mainSrc: 'int get foo => 1;\n');
|
||||
var result = await p.runAnalyze([
|
||||
'--format=machine',
|
||||
p.mainPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--format=machine', p.mainPath]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -798,10 +799,7 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
});
|
||||
test('one error', () async {
|
||||
p = project(mainSrc: "int get foo => 'str';\n");
|
||||
var result = await p.runAnalyze([
|
||||
'--format=machine',
|
||||
p.mainPath,
|
||||
]);
|
||||
var result = await p.runAnalyze(['--format=machine', p.mainPath]);
|
||||
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -831,8 +829,9 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
test('--use-aot-snapshot', () async {
|
||||
p = project(mainSrc: 'int get foo => 1;\n');
|
||||
|
||||
var result =
|
||||
await p.runAnalyze(['--use-aot-snapshot'], workingDir: p.dirPath);
|
||||
var result = await p.runAnalyze([
|
||||
'--use-aot-snapshot',
|
||||
], workingDir: p.dirPath);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -842,8 +841,9 @@ warning - analysis_options.yaml:1:10 - The URI 'package:lints/recommended.yaml'
|
||||
test('--no-use-aot-snapshot', () async {
|
||||
p = project(mainSrc: 'int get foo => 1;\n');
|
||||
|
||||
var result =
|
||||
await p.runAnalyze(['--no-use-aot-snapshot'], workingDir: p.dirPath);
|
||||
var result = await p.runAnalyze([
|
||||
'--no-use-aot-snapshot',
|
||||
], workingDir: p.dirPath);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
|
||||
@@ -40,28 +40,29 @@ void main() {
|
||||
});
|
||||
|
||||
test(
|
||||
'when a compiler cannot receive a shutdown request due to a connection error',
|
||||
() async {
|
||||
// When this occurs, the info file associated with the running compiler
|
||||
// should be deleted, and the shutdown command should appear to have
|
||||
// succeeded, because there's nothing actionable the user can do to fix
|
||||
// the connection error.
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
// Create a [serverInfoFile] with an invalid port to guarantee that a
|
||||
// connection will not be established.
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
File(serverInfoFile).writeAsStringSync('address:127.0.0.1 port:-12 ');
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption=$serverInfoFile',
|
||||
]);
|
||||
'when a compiler cannot receive a shutdown request due to a connection error',
|
||||
() async {
|
||||
// When this occurs, the info file associated with the running compiler
|
||||
// should be deleted, and the shutdown command should appear to have
|
||||
// succeeded, because there's nothing actionable the user can do to fix
|
||||
// the connection error.
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
// Create a [serverInfoFile] with an invalid port to guarantee that a
|
||||
// connection will not be established.
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
File(serverInfoFile).writeAsStringSync('address:127.0.0.1 port:-12 ');
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption=$serverInfoFile',
|
||||
]);
|
||||
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
});
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
},
|
||||
);
|
||||
|
||||
test('run and shutdown', () async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
@@ -117,61 +118,63 @@ void main() {
|
||||
});
|
||||
|
||||
test(
|
||||
'start and shutdown when using legacy --resident-server-info-file option',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
final runResult = await p.run([
|
||||
'compilation-server',
|
||||
'start',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
]);
|
||||
'start and shutdown when using legacy --resident-server-info-file option',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
final runResult = await p.run([
|
||||
'compilation-server',
|
||||
'start',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
]);
|
||||
|
||||
expect(runResult.stdout, matches(compilationServerStartRegExp));
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), true);
|
||||
expect(runResult.stdout, matches(compilationServerStartRegExp));
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), true);
|
||||
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
]);
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
]);
|
||||
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
});
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'start and shutdown when passing a relative path to --resident-compiler-info-file',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
final runResult = await p.run([
|
||||
'compilation-server',
|
||||
'start',
|
||||
'--$residentCompilerInfoFileOption',
|
||||
path.relative(serverInfoFile, from: p.dirPath),
|
||||
]);
|
||||
'start and shutdown when passing a relative path to --resident-compiler-info-file',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final serverInfoFile = path.join(p.dirPath, 'info');
|
||||
final runResult = await p.run([
|
||||
'compilation-server',
|
||||
'start',
|
||||
'--$residentCompilerInfoFileOption',
|
||||
path.relative(serverInfoFile, from: p.dirPath),
|
||||
]);
|
||||
|
||||
expect(runResult.stdout, matches(compilationServerStartRegExp));
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), true);
|
||||
expect(runResult.stdout, matches(compilationServerStartRegExp));
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), true);
|
||||
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption',
|
||||
path.relative(serverInfoFile, from: p.dirPath),
|
||||
]);
|
||||
final result = await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption',
|
||||
path.relative(serverInfoFile, from: p.dirPath),
|
||||
]);
|
||||
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
});
|
||||
expect(result.stdout, matches(compilationServerShutdownRegExp));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(serverInfoFile).existsSync(), false);
|
||||
},
|
||||
);
|
||||
}, timeout: longTimeout);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,9 @@ void main() {
|
||||
|
||||
void defineCreateTests() {
|
||||
// Create tests for each template.
|
||||
for (String templateId
|
||||
in CreateCommand.legalTemplateIds(includeDeprecated: true)) {
|
||||
for (String templateId in CreateCommand.legalTemplateIds(
|
||||
includeDeprecated: true,
|
||||
)) {
|
||||
test(templateId, () async {
|
||||
const projectName = 'template_project';
|
||||
final p = project();
|
||||
@@ -42,10 +43,10 @@ void defineCreateTests() {
|
||||
|
||||
// Validate that the project analyzes cleanly.
|
||||
print('$templateId: analyzing generated project');
|
||||
ProcessResult analyzeResult = await p.runAnalyze(
|
||||
['--fatal-infos', projectName],
|
||||
workingDir: p.dir.path,
|
||||
);
|
||||
ProcessResult analyzeResult = await p.runAnalyze([
|
||||
'--fatal-infos',
|
||||
projectName,
|
||||
], workingDir: p.dir.path);
|
||||
expect(analyzeResult.exitCode, 0, reason: analyzeResult.stdout);
|
||||
|
||||
// Validate that the code is well formatted.
|
||||
@@ -61,21 +62,19 @@ void defineCreateTests() {
|
||||
|
||||
// Process the execution instructions provided by the template.
|
||||
final runCommands = templateGenerator
|
||||
.getInstallInstructions(
|
||||
projectName,
|
||||
scriptPath: projectName,
|
||||
)
|
||||
.getInstallInstructions(projectName, scriptPath: projectName)
|
||||
.split('\n')
|
||||
// Remove directory change instructions.
|
||||
.sublist(1)
|
||||
.map((command) => command.trim())
|
||||
.map((command) {
|
||||
final commandParts = command.split(' ');
|
||||
if (command.startsWith('dart ')) {
|
||||
return commandParts.sublist(1);
|
||||
}
|
||||
return commandParts;
|
||||
}).toList();
|
||||
final commandParts = command.split(' ');
|
||||
if (command.startsWith('dart ')) {
|
||||
return commandParts.sublist(1);
|
||||
}
|
||||
return commandParts;
|
||||
})
|
||||
.toList();
|
||||
|
||||
print('$templateId: running the following commands:');
|
||||
for (final command in runCommands) {
|
||||
@@ -98,26 +97,25 @@ void defineCreateTests() {
|
||||
// The web template uses `webdev` to execute, not `dart`, so don't
|
||||
// run the test through the project utility method.
|
||||
process = await Process.start(
|
||||
path.join(
|
||||
p.pubCacheBinPath,
|
||||
Platform.isWindows ? '${command.first}.bat' : command.first,
|
||||
),
|
||||
[
|
||||
...command.sublist(1),
|
||||
'web:0', // Allow for binding to a random available port.
|
||||
],
|
||||
workingDirectory: workingDir,
|
||||
environment: {
|
||||
'PUB_CACHE': p.pubCachePath,
|
||||
'PATH': path.dirname(Platform.resolvedExecutable) +
|
||||
(Platform.isWindows ? ';' : ':') +
|
||||
Platform.environment['PATH']!,
|
||||
});
|
||||
} else {
|
||||
process = await p.start(
|
||||
command,
|
||||
workingDir: workingDir,
|
||||
path.join(
|
||||
p.pubCacheBinPath,
|
||||
Platform.isWindows ? '${command.first}.bat' : command.first,
|
||||
),
|
||||
[
|
||||
...command.sublist(1),
|
||||
'web:0', // Allow for binding to a random available port.
|
||||
],
|
||||
workingDirectory: workingDir,
|
||||
environment: {
|
||||
'PUB_CACHE': p.pubCachePath,
|
||||
'PATH':
|
||||
path.dirname(Platform.resolvedExecutable) +
|
||||
(Platform.isWindows ? ';' : ':') +
|
||||
Platform.environment['PATH']!,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
process = await p.start(command, workingDir: workingDir);
|
||||
}
|
||||
|
||||
if (isLastCommand && (isServerTemplate || isWebTemplate)) {
|
||||
@@ -168,11 +166,13 @@ void defineCreateTests() {
|
||||
// If the sample should exit on its own, it should always result in
|
||||
// an exit code of 0.
|
||||
final duration = const Duration(seconds: 60);
|
||||
final exitCode =
|
||||
await process.exitCode.timeout(duration, onTimeout: () {
|
||||
print('Command $command timed out');
|
||||
return -1;
|
||||
});
|
||||
final exitCode = await process.exitCode.timeout(
|
||||
duration,
|
||||
onTimeout: () {
|
||||
print('Command $command timed out');
|
||||
return -1;
|
||||
},
|
||||
);
|
||||
if (exitCode != 0) {
|
||||
print('Command $command exited with code $exitCode');
|
||||
print('Output: \n${output.join('\n')}');
|
||||
|
||||
@@ -26,9 +26,7 @@ void defineCreateTests() {
|
||||
expect(result.stdout, contains('Create a new Dart project.'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Usage: dart create [arguments] <directory>',
|
||||
),
|
||||
contains('Usage: dart create [arguments] <directory>'),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
@@ -41,17 +39,17 @@ void defineCreateTests() {
|
||||
expect(result.stdout, contains('Create a new Dart project.'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Usage: dart [vm-options] create [arguments] <directory>',
|
||||
),
|
||||
contains('Usage: dart [vm-options] create [arguments] <directory>'),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
test('default template exists', () async {
|
||||
expect(CreateCommand.legalTemplateIds(),
|
||||
contains(CreateCommand.defaultTemplateId));
|
||||
expect(
|
||||
CreateCommand.legalTemplateIds(),
|
||||
contains(CreateCommand.defaultTemplateId),
|
||||
);
|
||||
});
|
||||
|
||||
test('no templates IDs overlap', () async {
|
||||
@@ -91,8 +89,12 @@ void defineCreateTests() {
|
||||
test('directory already exists', () async {
|
||||
final p = project();
|
||||
|
||||
ProcessResult result = await p.run(
|
||||
['create', '--template', CreateCommand.defaultTemplateId, p.dir.path]);
|
||||
ProcessResult result = await p.run([
|
||||
'create',
|
||||
'--template',
|
||||
CreateCommand.defaultTemplateId,
|
||||
p.dir.path,
|
||||
]);
|
||||
expect(result.exitCode, 73);
|
||||
});
|
||||
|
||||
@@ -102,10 +104,11 @@ void defineCreateTests() {
|
||||
final p = project();
|
||||
final projectDir = Directory.fromUri(tempDir.uri.resolve('foo/'))
|
||||
..createSync();
|
||||
final result = await p.run(
|
||||
['create', '--force', '.'],
|
||||
workingDir: projectDir.path,
|
||||
);
|
||||
final result = await p.run([
|
||||
'create',
|
||||
'--force',
|
||||
'.',
|
||||
], workingDir: projectDir.path);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Created project foo in .!'));
|
||||
expect(result.exitCode, 0);
|
||||
@@ -116,13 +119,18 @@ void defineCreateTests() {
|
||||
|
||||
test('project with normalized package name, with -', () async {
|
||||
final p = project();
|
||||
final result =
|
||||
await p.run(['create', '--no-pub', 'requires-normalization']);
|
||||
final result = await p.run([
|
||||
'create',
|
||||
'--no-pub',
|
||||
'requires-normalization',
|
||||
]);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Created project requires_normalization in requires-normalization!'));
|
||||
result.stdout,
|
||||
contains(
|
||||
'Created project requires_normalization in requires-normalization!',
|
||||
),
|
||||
);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
@@ -131,9 +139,11 @@ void defineCreateTests() {
|
||||
final result = await p.run(['create', '--no-pub', 'RequiresNormalization']);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Created project requires_normalization in RequiresNormalization!'));
|
||||
result.stdout,
|
||||
contains(
|
||||
'Created project requires_normalization in RequiresNormalization!',
|
||||
),
|
||||
);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
@@ -177,14 +187,20 @@ void defineCreateTests() {
|
||||
test('bad template id', () async {
|
||||
final p = project();
|
||||
|
||||
ProcessResult result = await p
|
||||
.run(['create', '--no-pub', '--template', 'foo-bar', p.dir.path]);
|
||||
ProcessResult result = await p.run([
|
||||
'create',
|
||||
'--no-pub',
|
||||
'--template',
|
||||
'foo-bar',
|
||||
p.dir.path,
|
||||
]);
|
||||
expect(result.exitCode, isNot(0));
|
||||
});
|
||||
|
||||
// Create tests for each template.
|
||||
for (String templateId
|
||||
in CreateCommand.legalTemplateIds(includeDeprecated: true)) {
|
||||
for (String templateId in CreateCommand.legalTemplateIds(
|
||||
includeDeprecated: true,
|
||||
)) {
|
||||
test(templateId, () async {
|
||||
final p = project();
|
||||
const projectName = 'template_project';
|
||||
@@ -202,8 +218,11 @@ void defineCreateTests() {
|
||||
entry = entry.replaceAll('__projectName__', projectName);
|
||||
File entryFile = File(path.join(p.dir.path, projectName, entry));
|
||||
|
||||
expect(entryFile.existsSync(), true,
|
||||
reason: 'File not found: ${entryFile.path}');
|
||||
expect(
|
||||
entryFile.existsSync(),
|
||||
true,
|
||||
reason: 'File not found: ${entryFile.path}',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,17 @@ void main() {
|
||||
|
||||
// Cross compilation is not available on 32-bit architectures.
|
||||
final hostArch = Target.current.architecture;
|
||||
final bool isRunningOn32Bit = hostArch == Architecture.ia32 ||
|
||||
final bool isRunningOn32Bit =
|
||||
hostArch == Architecture.ia32 ||
|
||||
hostArch == Architecture.arm ||
|
||||
hostArch == Architecture.riscv32;
|
||||
|
||||
group('cross compile -', defineCrossCompileTests,
|
||||
timeout: longTimeout, skip: isRunningOn32Bit);
|
||||
group(
|
||||
'cross compile -',
|
||||
defineCrossCompileTests,
|
||||
timeout: longTimeout,
|
||||
skip: isRunningOn32Bit,
|
||||
);
|
||||
}
|
||||
|
||||
String unsupportedTargetMessage(Target target) =>
|
||||
@@ -40,31 +45,34 @@ void defineCrossCompileTests() {
|
||||
String mainMessage(Target target) => 'I love ${target.os}';
|
||||
|
||||
Future<(ProcessResult, String)> crossCompile(
|
||||
String subcommand, Target target) async {
|
||||
final p =
|
||||
project(mainSrc: 'void main() {print("${mainMessage(target)}");}');
|
||||
String subcommand,
|
||||
Target target,
|
||||
) async {
|
||||
final p = project(
|
||||
mainSrc: 'void main() {print("${mainMessage(target)}");}',
|
||||
);
|
||||
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
|
||||
final filename = subcommand == CompileNativeCommand.exeCmdName
|
||||
? 'myexe'
|
||||
: subcommand == CompileNativeCommand.aotSnapshotCmdName
|
||||
? 'out.so'
|
||||
: throw ArgumentError(
|
||||
'Unexpected subcommand $subcommand', 'subcommand');
|
||||
? 'out.so'
|
||||
: throw ArgumentError(
|
||||
'Unexpected subcommand $subcommand',
|
||||
'subcommand',
|
||||
);
|
||||
final outFile = path.canonicalize(path.join(p.dirPath, filename));
|
||||
final result = await p.run(
|
||||
[
|
||||
'compile',
|
||||
subcommand,
|
||||
'-v',
|
||||
'--target-os',
|
||||
target.os.name,
|
||||
'--target-arch',
|
||||
target.architecture.name,
|
||||
'-o',
|
||||
outFile,
|
||||
inFile,
|
||||
],
|
||||
);
|
||||
final result = await p.run([
|
||||
'compile',
|
||||
subcommand,
|
||||
'-v',
|
||||
'--target-os',
|
||||
target.os.name,
|
||||
'--target-arch',
|
||||
target.architecture.name,
|
||||
'-o',
|
||||
outFile,
|
||||
inFile,
|
||||
]);
|
||||
|
||||
print('Subcommand terminated with exit code ${result.exitCode}.');
|
||||
if (result.stdout.isNotEmpty) {
|
||||
@@ -80,34 +88,35 @@ void defineCrossCompileTests() {
|
||||
}
|
||||
|
||||
TestFunction crossCompileTest(String subcommand, Target target) => () async {
|
||||
expect(subcommand, isIn(subcommands));
|
||||
expect(target, isIn(crossCompileTargets));
|
||||
var (result, outFile) = await crossCompile(subcommand, target);
|
||||
expect(subcommand, isIn(subcommands));
|
||||
expect(target, isIn(crossCompileTargets));
|
||||
var (result, outFile) = await crossCompile(subcommand, target);
|
||||
|
||||
expect(result.stdout, contains(usingTargetOSMessage(target.os)));
|
||||
expect(
|
||||
result.stderr, isNot(contains(unsupportedTargetMessage(target))));
|
||||
expect(result.exitCode, 0);
|
||||
expect(File(outFile).existsSync(), true,
|
||||
reason: 'File not found: $outFile');
|
||||
expect(result.stdout, contains(usingTargetOSMessage(target.os)));
|
||||
expect(result.stderr, isNot(contains(unsupportedTargetMessage(target))));
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
File(outFile).existsSync(),
|
||||
true,
|
||||
reason: 'File not found: $outFile',
|
||||
);
|
||||
|
||||
if (target != Target.current) return;
|
||||
if (target != Target.current) return;
|
||||
|
||||
if (subcommand == CompileNativeCommand.exeCmdName) {
|
||||
result = Process.runSync(outFile, const []);
|
||||
} else {
|
||||
expect(subcommand, CompileNativeCommand.aotSnapshotCmdName);
|
||||
final Directory binDir = File(Platform.resolvedExecutable).parent;
|
||||
result = Process.runSync(
|
||||
path.join(binDir.path, 'dartaotruntime'),
|
||||
[outFile],
|
||||
);
|
||||
}
|
||||
if (subcommand == CompileNativeCommand.exeCmdName) {
|
||||
result = Process.runSync(outFile, const []);
|
||||
} else {
|
||||
expect(subcommand, CompileNativeCommand.aotSnapshotCmdName);
|
||||
final Directory binDir = File(Platform.resolvedExecutable).parent;
|
||||
result = Process.runSync(path.join(binDir.path, 'dartaotruntime'), [
|
||||
outFile,
|
||||
]);
|
||||
}
|
||||
|
||||
expect(result.stdout, contains(mainMessage(target)));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
};
|
||||
expect(result.stdout, contains(mainMessage(target)));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
};
|
||||
|
||||
TestFunction crossCompileFailureTest(String subcommand, Target target) =>
|
||||
() async {
|
||||
@@ -120,25 +129,34 @@ void defineCrossCompileTests() {
|
||||
expect(result.stdout, isNot(contains(usingTargetOSMessage(target.os))));
|
||||
expect(result.stderr, contains(unsupportedTargetMessage(target)));
|
||||
expect(result.exitCode, crossCompileErrorExitCode);
|
||||
expect(File(outFile).existsSync(), false,
|
||||
reason: 'File created despite failure: $outFile');
|
||||
expect(
|
||||
File(outFile).existsSync(),
|
||||
false,
|
||||
reason: 'File created despite failure: $outFile',
|
||||
);
|
||||
};
|
||||
|
||||
for (final subcommand in subcommands) {
|
||||
for (final target in crossCompileTargets) {
|
||||
test('Compile $subcommand can cross compile to $target',
|
||||
crossCompileTest(subcommand, target));
|
||||
test(
|
||||
'Compile $subcommand can cross compile to $target',
|
||||
crossCompileTest(subcommand, target),
|
||||
);
|
||||
}
|
||||
var targetOS = Platform.isWindows ? OS.macOS : OS.windows;
|
||||
var targetArch = Architecture.arm64;
|
||||
var target = Target.fromArchitectureAndOS(targetArch, targetOS);
|
||||
test('Compile $subcommand fails on invalid target OS',
|
||||
crossCompileFailureTest(subcommand, target));
|
||||
test(
|
||||
'Compile $subcommand fails on invalid target OS',
|
||||
crossCompileFailureTest(subcommand, target),
|
||||
);
|
||||
|
||||
targetOS = OS.linux;
|
||||
targetArch = Architecture.riscv32;
|
||||
target = Target.fromArchitectureAndOS(targetArch, targetOS);
|
||||
test('Compile $subcommand fails on invalid target architecture',
|
||||
crossCompileFailureTest(subcommand, target));
|
||||
test(
|
||||
'Compile $subcommand fails on invalid target architecture',
|
||||
crossCompileFailureTest(subcommand, target),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,15 @@ void debugAdapter() {
|
||||
var result = await p.run(['debug_adapter', '--help']);
|
||||
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Start a debug adapter that conforms to the Debug Adapter Protocol.'));
|
||||
expect(result.stdout,
|
||||
contains('Whether to use the "dart test" debug adapter to run tests'));
|
||||
result.stdout,
|
||||
contains(
|
||||
'Start a debug adapter that conforms to the Debug Adapter Protocol.',
|
||||
),
|
||||
);
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Whether to use the "dart test" debug adapter to run tests'),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
@@ -42,11 +46,12 @@ void debugAdapter() {
|
||||
await process.exitCode;
|
||||
|
||||
expect(
|
||||
errorOutput.toString(),
|
||||
allOf(
|
||||
contains('Input could not be parsed'),
|
||||
contains('is intended for use by tooling'),
|
||||
contains('foo\r\nbar'),
|
||||
));
|
||||
errorOutput.toString(),
|
||||
allOf(
|
||||
contains('Input could not be parsed'),
|
||||
contains('is intended for use by tooling'),
|
||||
contains('foo\r\nbar'),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ void devtools() {
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Open DevTools'));
|
||||
expect(result.stdout,
|
||||
contains('Usage: dart devtools [arguments] [service protocol uri]'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Usage: dart devtools [arguments] [service protocol uri]'),
|
||||
);
|
||||
|
||||
// Does not show verbose help.
|
||||
expect(result.stdout.contains('--try-ports'), isFalse);
|
||||
@@ -52,9 +54,11 @@ void devtools() {
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Open DevTools'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Usage: dart [vm-options] devtools [arguments] [service protocol uri]'));
|
||||
result.stdout,
|
||||
contains(
|
||||
'Usage: dart [vm-options] devtools [arguments] [service protocol uri]',
|
||||
),
|
||||
);
|
||||
|
||||
// Shows verbose help.
|
||||
expect(result.stdout, contains('--try-ports'));
|
||||
@@ -84,32 +88,32 @@ void devtools() {
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen((line) async {
|
||||
final json = jsonDecode(line);
|
||||
final eventName = json['event'] as String?;
|
||||
final params = (json['params'] as Map?)?.cast<String, Object?>();
|
||||
switch (eventName) {
|
||||
case 'server.dtdStarted':
|
||||
// {"event":"server.dtdStarted","params":{
|
||||
// "uri":"ws://127.0.0.1:50882/nQf49D0YcbONeKVq"
|
||||
// }}
|
||||
expect(params!['uri'], isA<String>());
|
||||
dtdServedCompleter.complete();
|
||||
case 'server.started':
|
||||
// {"event":"server.started","method":"server.started","params":{
|
||||
// "host":"127.0.0.1","port":9100,"pid":93508,"protocolVersion":"1.1.0"
|
||||
// }}
|
||||
expect(params!['host'], isA<String>());
|
||||
expect(params['port'], isA<int>());
|
||||
devToolsHost = params['host'] as String;
|
||||
devToolsPort = params['port'] as int;
|
||||
final json = jsonDecode(line);
|
||||
final eventName = json['event'] as String?;
|
||||
final params = (json['params'] as Map?)?.cast<String, Object?>();
|
||||
switch (eventName) {
|
||||
case 'server.dtdStarted':
|
||||
// {"event":"server.dtdStarted","params":{
|
||||
// "uri":"ws://127.0.0.1:50882/nQf49D0YcbONeKVq"
|
||||
// }}
|
||||
expect(params!['uri'], isA<String>());
|
||||
dtdServedCompleter.complete();
|
||||
case 'server.started':
|
||||
// {"event":"server.started","method":"server.started","params":{
|
||||
// "host":"127.0.0.1","port":9100,"pid":93508,"protocolVersion":"1.1.0"
|
||||
// }}
|
||||
expect(params!['host'], isA<String>());
|
||||
expect(params['port'], isA<int>());
|
||||
devToolsHost = params['host'] as String;
|
||||
devToolsPort = params['port'] as int;
|
||||
|
||||
// We can cancel the subscription because the 'server.started' event
|
||||
// is expected after the 'server.dtdStarted' event.
|
||||
await sub.cancel();
|
||||
devToolsServedCompleter.complete();
|
||||
default:
|
||||
}
|
||||
});
|
||||
// We can cancel the subscription because the 'server.started' event
|
||||
// is expected after the 'server.dtdStarted' event.
|
||||
await sub.cancel();
|
||||
devToolsServedCompleter.complete();
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
await Future.wait([
|
||||
dtdServedCompleter.future,
|
||||
@@ -125,12 +129,15 @@ void devtools() {
|
||||
HttpClient client = HttpClient();
|
||||
expect(devToolsHost, isNotNull);
|
||||
expect(devToolsPort, isNotNull);
|
||||
final httpRequest =
|
||||
await client.get(devToolsHost!, devToolsPort!, 'index.html');
|
||||
final httpRequest = await client.get(
|
||||
devToolsHost!,
|
||||
devToolsPort!,
|
||||
'index.html',
|
||||
);
|
||||
final httpResponse = await httpRequest.close();
|
||||
|
||||
final contents =
|
||||
(await httpResponse.transform(utf8.decoder).toList()).join();
|
||||
final contents = (await httpResponse.transform(utf8.decoder).toList())
|
||||
.join();
|
||||
client.close();
|
||||
|
||||
expect(contents, contains('DevTools'));
|
||||
@@ -150,7 +157,7 @@ void devtools() {
|
||||
'devtools',
|
||||
'--no-launch-browser',
|
||||
if (shouldPrintDtd) '--print-dtd',
|
||||
if (vmServiceUri != null) vmServiceUri,
|
||||
?vmServiceUri,
|
||||
]);
|
||||
process.stderr.transform(utf8.decoder).listen(print);
|
||||
|
||||
@@ -162,16 +169,16 @@ void devtools() {
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter())
|
||||
.listen((event) async {
|
||||
print(event);
|
||||
if (event.contains(ddsStartedRegExp)) {
|
||||
startedDds = true;
|
||||
} else if (event.contains(dtdStartedRegExp)) {
|
||||
startedDtd = true;
|
||||
} else if (event.contains(servingDevToolsRegExp)) {
|
||||
await sub.cancel();
|
||||
devToolsServedCompleter.complete();
|
||||
}
|
||||
});
|
||||
print(event);
|
||||
if (event.contains(ddsStartedRegExp)) {
|
||||
startedDds = true;
|
||||
} else if (event.contains(dtdStartedRegExp)) {
|
||||
startedDtd = true;
|
||||
} else if (event.contains(servingDevToolsRegExp)) {
|
||||
await sub.cancel();
|
||||
devToolsServedCompleter.complete();
|
||||
}
|
||||
});
|
||||
|
||||
await devToolsServedCompleter.future;
|
||||
expect(startedDds, shouldStartDds);
|
||||
@@ -218,14 +225,12 @@ Future<void> main() async {
|
||||
Future<String> startTargetProject({
|
||||
required bool disableServiceAuthCodes,
|
||||
}) async {
|
||||
targetProjectInstance = await targetProject.start(
|
||||
[
|
||||
'--no-dds',
|
||||
'--observe=0',
|
||||
if (disableServiceAuthCodes) '--disable-service-auth-codes',
|
||||
targetProject.relativeFilePath,
|
||||
],
|
||||
);
|
||||
targetProjectInstance = await targetProject.start([
|
||||
'--no-dds',
|
||||
'--observe=0',
|
||||
if (disableServiceAuthCodes) '--disable-service-auth-codes',
|
||||
targetProject.relativeFilePath,
|
||||
]);
|
||||
|
||||
final serviceUriCompleter = Completer<String>();
|
||||
late final StreamSubscription<String> sub;
|
||||
@@ -233,13 +238,13 @@ Future<void> main() async {
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen((event) async {
|
||||
if (event.contains(dartVMServiceRegExp)) {
|
||||
await sub.cancel();
|
||||
serviceUriCompleter.complete(
|
||||
dartVMServiceRegExp.firstMatch(event)!.group(1),
|
||||
);
|
||||
}
|
||||
});
|
||||
if (event.contains(dartVMServiceRegExp)) {
|
||||
await sub.cancel();
|
||||
serviceUriCompleter.complete(
|
||||
dartVMServiceRegExp.firstMatch(event)!.group(1),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return await serviceUriCompleter.future;
|
||||
}
|
||||
@@ -260,14 +265,12 @@ Future<void> main() async {
|
||||
|
||||
test('check for redirect with auth codes $authCodesEnabledStr', () async {
|
||||
final vmServiceUri = Uri.parse(
|
||||
await startTargetProject(
|
||||
disableServiceAuthCodes: disableAuthCodes,
|
||||
),
|
||||
await startTargetProject(disableServiceAuthCodes: disableAuthCodes),
|
||||
);
|
||||
var updatedUri =
|
||||
await DevToolsCommand.checkForRedirectToExistingDDSInstance(
|
||||
vmServiceUri,
|
||||
);
|
||||
vmServiceUri,
|
||||
);
|
||||
// We should not have followed a redirect since DDS isn't running.
|
||||
expect(vmServiceUri, updatedUri);
|
||||
|
||||
@@ -282,8 +285,8 @@ Future<void> main() async {
|
||||
// DDS URI.
|
||||
updatedUri =
|
||||
await DevToolsCommand.checkForRedirectToExistingDDSInstance(
|
||||
vmServiceUri,
|
||||
);
|
||||
vmServiceUri,
|
||||
);
|
||||
expect(updatedUri, ddsUri);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,8 +27,12 @@ void defineDocTests() {
|
||||
|
||||
test('Passing conflicting options fails', () async {
|
||||
final p = project();
|
||||
final result =
|
||||
await p.run(['doc', '--validate-links', '--dry-run', p.dirPath]);
|
||||
final result = await p.run([
|
||||
'doc',
|
||||
'--validate-links',
|
||||
'--dry-run',
|
||||
p.dirPath,
|
||||
]);
|
||||
expect(
|
||||
result.stderr,
|
||||
contains("'dart doc' can not validate links when dry-running."),
|
||||
@@ -39,8 +43,10 @@ void defineDocTests() {
|
||||
test('Passing multiple directories fails', () async {
|
||||
final p = project();
|
||||
final result = await p.run(['doc', 'foo', 'bar']);
|
||||
expect(result.stderr,
|
||||
contains("'dart doc' only supports one input directory.'"));
|
||||
expect(
|
||||
result.stderr,
|
||||
contains("'dart doc' only supports one input directory.'"),
|
||||
);
|
||||
expect(result.exitCode, errorExitCode);
|
||||
});
|
||||
|
||||
|
||||
@@ -54,9 +54,7 @@ ${result.stderr}
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Apply automated fixes to Dart source code.',
|
||||
),
|
||||
contains('Apply automated fixes to Dart source code.'),
|
||||
);
|
||||
expect(result.stdout, contains('Usage: dart fix [arguments]'));
|
||||
});
|
||||
@@ -70,9 +68,7 @@ ${result.stderr}
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'Apply automated fixes to Dart source code.',
|
||||
),
|
||||
contains('Apply automated fixes to Dart source code.'),
|
||||
);
|
||||
expect(
|
||||
result.stdout,
|
||||
@@ -87,16 +83,20 @@ ${result.stderr}
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout,
|
||||
contains('Apply automated fixes to Dart source code.'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Apply automated fixes to Dart source code.'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('--enable-experiment is accepted', () async {
|
||||
p = project(mainSrc: 'int get foo => 1;\n');
|
||||
|
||||
var result =
|
||||
await p!.runFix(['--enable-experiment=test-experiment', '--apply']);
|
||||
var result = await p!.runFix([
|
||||
'--enable-experiment=test-experiment',
|
||||
'--apply',
|
||||
]);
|
||||
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
@@ -130,12 +130,13 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--dry-run', () async {
|
||||
@@ -160,18 +161,19 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'3 proposed fixes in 1 file.',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' annotate_overrides $bullet 1 fix',
|
||||
' prefer_single_quotes $bullet 2 fixes',
|
||||
'To fix an individual diagnostic, run one of:',
|
||||
' dart fix --apply --code=annotate_overrides .',
|
||||
' dart fix --apply --code=prefer_single_quotes .',
|
||||
'To fix all diagnostics, run:',
|
||||
' dart fix --apply .',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'3 proposed fixes in 1 file.',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' annotate_overrides $bullet 1 fix',
|
||||
' prefer_single_quotes $bullet 2 fixes',
|
||||
'To fix an individual diagnostic, run one of:',
|
||||
' dart fix --apply --code=annotate_overrides .',
|
||||
' dart fix --apply --code=prefer_single_quotes .',
|
||||
'To fix all diagnostics, run:',
|
||||
' dart fix --apply .',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--dry-run --code=(single)', () async {
|
||||
@@ -189,18 +191,22 @@ linter:
|
||||
- unnecessary_new
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(
|
||||
['--dry-run', '--code', 'prefer_single_quotes', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--dry-run',
|
||||
'--code',
|
||||
'prefer_single_quotes',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'1 proposed fix in 1 file.',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'1 proposed fix in 1 file.',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--dry-run --code=(single: undefined)', () async {
|
||||
@@ -218,15 +224,20 @@ linter:
|
||||
- unnecessary_new
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(['--dry-run', '--code', '_undefined_', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--dry-run',
|
||||
'--code',
|
||||
'_undefined_',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply lib/main.dart', () async {
|
||||
@@ -240,17 +251,20 @@ linter:
|
||||
- prefer_single_quotes
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(['--apply', path.join('lib', 'main.dart')],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
path.join('lib', 'main.dart'),
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]),
|
||||
);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
@@ -269,34 +283,41 @@ linter:
|
||||
- unnecessary_new
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(
|
||||
['--apply', '--code', 'prefer_single_quotes', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'prefer_single_quotes',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply --code=(undefined)', () async {
|
||||
p = project(
|
||||
mainSrc: '',
|
||||
);
|
||||
var result = await p!.runFix(['--apply', '--code', '_undefined_', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
p = project(mainSrc: '');
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'_undefined_',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply --code=(not enabled)', () async {
|
||||
@@ -313,13 +334,18 @@ linter:
|
||||
- unnecessary_new
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(
|
||||
['--apply', '--code', 'prefer_single_quotes', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'prefer_single_quotes',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout,
|
||||
stringContainsInOrderWithVariableBullets(['Nothing to fix!']));
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets(['Nothing to fix!']),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply --code=(multiple: one undefined)', () async {
|
||||
@@ -343,15 +369,16 @@ linter:
|
||||
'_undefined_',
|
||||
'--code',
|
||||
'unnecessary_new',
|
||||
'.'
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 3);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
"Unable to compute fixes: The diagnostic '_undefined_' is not defined by the analyzer.",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply --code=(multiple)', () async {
|
||||
@@ -375,69 +402,66 @@ linter:
|
||||
'prefer_single_quotes',
|
||||
'--code',
|
||||
'unnecessary_new',
|
||||
'.'
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unnecessary_new $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unnecessary_new $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'--apply part.dart',
|
||||
() async {
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
test('--apply part.dart', () async {
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
part 'part.dart';
|
||||
void a() {
|
||||
b();
|
||||
}
|
||||
''',
|
||||
analysisOptions: '''
|
||||
analysisOptions: '''
|
||||
linter:
|
||||
rules:
|
||||
- prefer_const_constructors
|
||||
''',
|
||||
);
|
||||
p!.file('lib/part.dart', '''
|
||||
);
|
||||
p!.file('lib/part.dart', '''
|
||||
part of 'main.dart';
|
||||
Stream<String> b() {
|
||||
return Stream.empty();
|
||||
}
|
||||
''');
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'empty_statements',
|
||||
'--code',
|
||||
'prefer_const_constructors',
|
||||
'./lib/part.dart'
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'part.dart',
|
||||
' prefer_const_constructors $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]));
|
||||
},
|
||||
);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'empty_statements',
|
||||
'--code',
|
||||
'prefer_const_constructors',
|
||||
'./lib/part.dart',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'part.dart',
|
||||
' prefer_const_constructors $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'--apply --code=(multiple) [part file]',
|
||||
() async {
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
test('--apply --code=(multiple) [part file]', () async {
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
part 'part.dart';
|
||||
void a() {
|
||||
// need to trigger a lint in main.dart for the bug to happen
|
||||
@@ -445,42 +469,42 @@ void a() {
|
||||
b();
|
||||
}
|
||||
''',
|
||||
analysisOptions: '''
|
||||
analysisOptions: '''
|
||||
linter:
|
||||
rules:
|
||||
- empty_statements
|
||||
- prefer_const_constructors
|
||||
''',
|
||||
);
|
||||
p!.file('lib/part.dart', '''
|
||||
);
|
||||
p!.file('lib/part.dart', '''
|
||||
part of 'main.dart';
|
||||
Stream<String> b() {
|
||||
// dart fix should only add a single const
|
||||
return Stream.empty();
|
||||
}
|
||||
''');
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'empty_statements',
|
||||
'--code',
|
||||
'prefer_const_constructors',
|
||||
'.'
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' empty_statements $bullet 1 fix',
|
||||
'lib${Platform.pathSeparator}part.dart',
|
||||
' prefer_const_constructors $bullet 1 fix',
|
||||
'2 fixes made in 2 files.',
|
||||
]));
|
||||
},
|
||||
);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code',
|
||||
'empty_statements',
|
||||
'--code',
|
||||
'prefer_const_constructors',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' empty_statements $bullet 1 fix',
|
||||
'lib${Platform.pathSeparator}part.dart',
|
||||
' prefer_const_constructors $bullet 1 fix',
|
||||
'2 fixes made in 2 files.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply --code=(multiple: comma-delimited)', () async {
|
||||
p = project(
|
||||
@@ -497,20 +521,23 @@ linter:
|
||||
- unnecessary_new
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(
|
||||
['--apply', '--code=prefer_single_quotes,unnecessary_new', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--apply',
|
||||
'--code=prefer_single_quotes,unnecessary_new',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unnecessary_new $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unnecessary_new $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply (.)', () async {
|
||||
@@ -528,13 +555,14 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
'1 fix made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply (contradictory lints do not loop infinitely)', () async {
|
||||
@@ -553,14 +581,15 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_double_quotes $bullet 2 fixes',
|
||||
' prefer_single_quotes $bullet 2 fixes',
|
||||
'4 fixes made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_double_quotes $bullet 2 fixes',
|
||||
' prefer_single_quotes $bullet 2 fixes',
|
||||
'4 fixes made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('--apply (excludes)', () async {
|
||||
@@ -618,14 +647,15 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unused_import $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Applying fixes...',
|
||||
'lib${Platform.pathSeparator}main.dart',
|
||||
' prefer_single_quotes $bullet 1 fix',
|
||||
' unused_import $bullet 1 fix',
|
||||
'2 fixes made in 1 file.',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
group('AOT mode', () {
|
||||
@@ -638,8 +668,11 @@ linter:
|
||||
- prefer_single_quotes
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(['--use-aot-snapshot', '--dry-run', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--use-aot-snapshot',
|
||||
'--dry-run',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('1 proposed fix in 1 file.'));
|
||||
@@ -654,9 +687,11 @@ linter:
|
||||
- prefer_single_quotes
|
||||
''',
|
||||
);
|
||||
var result = await p!.runFix(
|
||||
['--no-use-aot-snapshot', '--dry-run', '.'],
|
||||
workingDir: p!.dirPath);
|
||||
var result = await p!.runFix([
|
||||
'--no-use-aot-snapshot',
|
||||
'--dry-run',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('1 proposed fix in 1 file.'));
|
||||
@@ -683,11 +718,12 @@ linter:
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Computing fixes in myapp...',
|
||||
'Nothing to fix!',
|
||||
]));
|
||||
result.stdout,
|
||||
stringContainsInOrderWithVariableBullets([
|
||||
'Computing fixes in myapp...',
|
||||
'Nothing to fix!',
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -720,11 +756,15 @@ class B extends A {
|
||||
String a() => '';
|
||||
}
|
||||
''');
|
||||
result = await p!.runFix(['--compare-to-golden', 'lib/main.dart.expect'],
|
||||
workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'lib/main.dart.expect',
|
||||
], workingDir: p!.dirPath);
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stderr,
|
||||
startsWith('Golden comparison requires a directory argument.'));
|
||||
expect(
|
||||
result.stderr,
|
||||
startsWith('Golden comparison requires a directory argument.'),
|
||||
);
|
||||
});
|
||||
|
||||
test('applied fixes do not match expected', () async {
|
||||
@@ -754,8 +794,10 @@ class B extends A {
|
||||
String a() => '';
|
||||
}
|
||||
''');
|
||||
result =
|
||||
await p!.runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
assertResult(exitCode: 1);
|
||||
});
|
||||
|
||||
@@ -787,8 +829,10 @@ class B extends A {
|
||||
String a() => '';
|
||||
}
|
||||
''');
|
||||
result =
|
||||
await p!.runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
assertResult();
|
||||
});
|
||||
|
||||
@@ -810,23 +854,29 @@ linter:
|
||||
- prefer_single_quotes
|
||||
''',
|
||||
);
|
||||
result =
|
||||
await p!.runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
assertResult(exitCode: 1);
|
||||
});
|
||||
|
||||
test('missing original', () async {
|
||||
p = project(mainSrc: '''
|
||||
p = project(
|
||||
mainSrc: '''
|
||||
class C {}
|
||||
''');
|
||||
''',
|
||||
);
|
||||
p!.file('lib/main.dart.expect', '''
|
||||
class C {}
|
||||
''');
|
||||
p!.file('lib/secondary.dart.expect', '''
|
||||
class A {}
|
||||
''');
|
||||
result =
|
||||
await p!.runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
assertResult(exitCode: 1);
|
||||
});
|
||||
|
||||
@@ -848,8 +898,10 @@ class A {
|
||||
String a() => '';
|
||||
}
|
||||
''');
|
||||
result =
|
||||
await p!.runFix(['--compare-to-golden', '.'], workingDir: p!.dirPath);
|
||||
result = await p!.runFix([
|
||||
'--compare-to-golden',
|
||||
'.',
|
||||
], workingDir: p!.dirPath);
|
||||
assertResult(exitCode: 1);
|
||||
});
|
||||
});
|
||||
@@ -862,7 +914,7 @@ Matcher stringContainsInOrderWithVariableBullets(List<String> substrings) {
|
||||
var substringMatcher = stringContainsInOrder(substrings);
|
||||
if (substrings.any((s) => s.contains(bullet))) {
|
||||
var alternatives = [
|
||||
for (var s in substrings) s.replaceAll(bullet, nonAnsiBullet)
|
||||
for (var s in substrings) s.replaceAll(bullet, nonAnsiBullet),
|
||||
];
|
||||
return anyOf(substringMatcher, stringContainsInOrder(alternatives));
|
||||
}
|
||||
|
||||
@@ -31,9 +31,10 @@ void command() {
|
||||
// For each command description, assert that the values are not empty, don't
|
||||
// have trailing white space and end with a period.
|
||||
test('description formatting', () {
|
||||
DartdevRunner(['--suppress-analytics'])
|
||||
.commands
|
||||
.forEach((String commandKey, Command<int> command) {
|
||||
DartdevRunner(['--suppress-analytics']).commands.forEach((
|
||||
String commandKey,
|
||||
Command<int> command,
|
||||
) {
|
||||
expect(commandKey, isNotEmpty);
|
||||
expect(command.description, isNotEmpty);
|
||||
expect(command.description.split('\n').first, endsWith('.'));
|
||||
@@ -43,20 +44,25 @@ void command() {
|
||||
|
||||
// Assert that all found usageLineLengths are the same and null
|
||||
test('argParser usageLineLength', () {
|
||||
DartdevRunner(['--suppress-analytics'])
|
||||
.commands
|
||||
.forEach((String commandKey, Command<int> command) {
|
||||
DartdevRunner(['--suppress-analytics']).commands.forEach((
|
||||
String commandKey,
|
||||
Command<int> command,
|
||||
) {
|
||||
if (command.name != 'help' &&
|
||||
command.name != 'format' &&
|
||||
command.name != 'pub' &&
|
||||
command.name != 'test') {
|
||||
expect(command.argParser.usageLineLength,
|
||||
stdout.hasTerminal ? stdout.terminalColumns : null);
|
||||
expect(
|
||||
command.argParser.usageLineLength,
|
||||
stdout.hasTerminal ? stdout.terminalColumns : null,
|
||||
);
|
||||
} else if (command.name == 'pub') {
|
||||
// TODO(sigurdm): Avoid special casing here.
|
||||
// https://github.com/dart-lang/pub/issues/2700
|
||||
expect(command.argParser.usageLineLength,
|
||||
stdout.hasTerminal ? stdout.terminalColumns : 80);
|
||||
expect(
|
||||
command.argParser.usageLineLength,
|
||||
stdout.hasTerminal ? stdout.terminalColumns : 80,
|
||||
);
|
||||
} else {
|
||||
expect(command.argParser.usageLineLength, isNull);
|
||||
}
|
||||
@@ -83,8 +89,10 @@ void help() {
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout,
|
||||
contains('The following options are only used for VM development'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('The following options are only used for VM development'),
|
||||
);
|
||||
});
|
||||
|
||||
test('--help -v', () async {
|
||||
@@ -93,8 +101,10 @@ void help() {
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout,
|
||||
contains('The following options are only used for VM development'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('The following options are only used for VM development'),
|
||||
);
|
||||
});
|
||||
|
||||
test('print Dart CLI help on usage error', () async {
|
||||
@@ -121,8 +131,10 @@ void help() {
|
||||
var result = await p.run(['help', '--verbose']);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout,
|
||||
contains('Usage: dart [vm-options] <command|dart-file> [arguments]'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Usage: dart [vm-options] <command|dart-file> [arguments]'),
|
||||
);
|
||||
});
|
||||
|
||||
test('help -v', () async {
|
||||
@@ -130,8 +142,10 @@ void help() {
|
||||
var result = await p.run(['help', '-v']);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout,
|
||||
contains('Usage: dart [vm-options] <command|dart-file> [arguments]'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Usage: dart [vm-options] <command|dart-file> [arguments]'),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ void format() {
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Idiomatically format Dart source code.'));
|
||||
expect(result.stdout,
|
||||
contains('Usage: dart format [options...] <files or directories...>'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Usage: dart format [options...] <files or directories...>'),
|
||||
);
|
||||
|
||||
// Does not show verbose help.
|
||||
expect(result.stdout.contains('--stdin-name'), isFalse);
|
||||
@@ -35,8 +37,10 @@ void format() {
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Idiomatically format Dart source code.'));
|
||||
expect(result.stdout,
|
||||
contains('Usage: dart format [options...] <files or directories...>'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Usage: dart format [options...] <files or directories...>'),
|
||||
);
|
||||
|
||||
// Shows verbose help.
|
||||
expect(result.stdout, contains('--stdin-name'));
|
||||
@@ -56,9 +60,9 @@ void format() {
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
startsWith(
|
||||
'Formatted lib/main.dart\nFormatted 1 file (1 changed) in '));
|
||||
result.stdout,
|
||||
startsWith('Formatted lib/main.dart\nFormatted 1 file (1 changed) in '),
|
||||
);
|
||||
});
|
||||
|
||||
test('formatted with exit code set', () async {
|
||||
@@ -71,9 +75,9 @@ void format() {
|
||||
expect(result.exitCode, isNot(0));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
startsWith(
|
||||
'Formatted lib/main.dart\nFormatted 1 file (1 changed) in '));
|
||||
result.stdout,
|
||||
startsWith('Formatted lib/main.dart\nFormatted 1 file (1 changed) in '),
|
||||
);
|
||||
});
|
||||
|
||||
test('not formatted with exit code set', () async {
|
||||
@@ -93,8 +97,10 @@ void format() {
|
||||
var unknownFilePath = '${p.relativeFilePath}-unknown-file.dart';
|
||||
ProcessResult result = await p.run(['format', unknownFilePath]);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr,
|
||||
startsWith('No file or directory found at "$unknownFilePath".'));
|
||||
expect(
|
||||
result.stderr,
|
||||
startsWith('No file or directory found at "$unknownFilePath".'),
|
||||
);
|
||||
expect(result.stdout, startsWith('Formatted no files in '));
|
||||
});
|
||||
|
||||
|
||||
@@ -20,9 +20,10 @@ void help() {
|
||||
'help', // `dart help help` is redundant
|
||||
'test', // `dart help test` does not call `test:test --help`.
|
||||
];
|
||||
DartdevRunner(['--suppress-analytics'])
|
||||
.commands
|
||||
.forEach((String commandKey, Command<int> command) {
|
||||
DartdevRunner(['--suppress-analytics']).commands.forEach((
|
||||
String commandKey,
|
||||
Command<int> command,
|
||||
) {
|
||||
if (!commandsNotTested.contains(commandKey)) {
|
||||
test('(help $commandKey == $commandKey --help)', () async {
|
||||
p = project();
|
||||
@@ -55,9 +56,10 @@ void help() {
|
||||
});
|
||||
|
||||
test('(--help flags also have -h abbr)', () {
|
||||
DartdevRunner(['--suppress-analytics'])
|
||||
.commands
|
||||
.forEach((String commandKey, Command<int> command) {
|
||||
DartdevRunner(['--suppress-analytics']).commands.forEach((
|
||||
String commandKey,
|
||||
Command<int> command,
|
||||
) {
|
||||
var helpOption = command.argParser.options['help'];
|
||||
// Some commands (like pub which use
|
||||
// "argParser = ArgParser.allowAnything()") may not have the help Option
|
||||
@@ -74,9 +76,8 @@ void help() {
|
||||
// Include the `Available commands:` with the empty line to ensure all
|
||||
// commands have a category.
|
||||
expect(
|
||||
result.stdout,
|
||||
contains(
|
||||
'''
|
||||
result.stdout,
|
||||
contains('''
|
||||
Available commands:
|
||||
|
||||
Global
|
||||
@@ -105,7 +106,7 @@ Tools
|
||||
info Show diagnostic information about the installed tooling.
|
||||
language-server Start Dart's analysis server.
|
||||
tooling-daemon Start Dart's tooling daemon.
|
||||
''',
|
||||
));
|
||||
'''),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ void main() {
|
||||
expect(process.elapsedTime, isNotEmpty);
|
||||
if (!(process.commandLine.startsWith('dart') ||
|
||||
process.commandLine.contains('snapshot'))) {
|
||||
print("Expected ${process.commandLine} to start with 'dart' or"
|
||||
" contain 'snapshot'.");
|
||||
print(
|
||||
"Expected ${process.commandLine} to start with 'dart' or"
|
||||
" contain 'snapshot'.",
|
||||
);
|
||||
expect(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ void main() {
|
||||
expect(process.elapsedTime, isNotEmpty);
|
||||
if (!(process.commandLine.startsWith('dart') ||
|
||||
process.commandLine.contains('snapshot'))) {
|
||||
print("Expected ${process.commandLine} to start with 'dart' or"
|
||||
" contain 'snapshot'.");
|
||||
print(
|
||||
"Expected ${process.commandLine} to start with 'dart' or"
|
||||
" contain 'snapshot'.",
|
||||
);
|
||||
expect(true, false);
|
||||
}
|
||||
}
|
||||
@@ -34,7 +36,8 @@ void main() {
|
||||
test('parseMacos', () {
|
||||
// Regression test for https://github.com/dart-lang/sdk/issues/51385.
|
||||
|
||||
const line = '35472 0,0 20:41:58 <path>/dart --disable-dart-dev '
|
||||
const line =
|
||||
'35472 0,0 20:41:58 <path>/dart --disable-dart-dev '
|
||||
'/Users/foo/flutter_tools.snapshot daemon';
|
||||
|
||||
var result = ProcessInfo.parseMacos(line);
|
||||
|
||||
@@ -17,8 +17,10 @@ void main() {
|
||||
final result = await p.run(['info', '--help']);
|
||||
|
||||
expect(result.stdout, isNotEmpty);
|
||||
expect(result.stdout,
|
||||
contains('Show diagnostic information about the installed tooling'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Show diagnostic information about the installed tooling'),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
|
||||
@@ -40,22 +40,27 @@ void main() {
|
||||
});
|
||||
}, skip: !Platform.isWindows);
|
||||
|
||||
group('info windows', () {
|
||||
late TestProject p;
|
||||
group(
|
||||
'info windows',
|
||||
() {
|
||||
late TestProject p;
|
||||
|
||||
test('shows process info', () async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final runResult = await p.run(['info']);
|
||||
test('shows process info', () async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final runResult = await p.run(['info']);
|
||||
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
expect(runResult.stderr, isEmpty);
|
||||
expect(runResult.exitCode, 0);
|
||||
|
||||
var output = runResult.stdout as String;
|
||||
var output = runResult.stdout as String;
|
||||
|
||||
expect(output, contains('providing this information'));
|
||||
expect(output, contains('## Process info'));
|
||||
expect(output, contains(RegExp(r'\|\s+Memory')));
|
||||
expect(output, contains(RegExp(r'\|\s+dart.exe ')));
|
||||
});
|
||||
}, timeout: longTimeout, skip: !Platform.isWindows);
|
||||
expect(output, contains('providing this information'));
|
||||
expect(output, contains('## Process info'));
|
||||
expect(output, contains(RegExp(r'\|\s+Memory')));
|
||||
expect(output, contains(RegExp(r'\|\s+dart.exe ')));
|
||||
});
|
||||
},
|
||||
timeout: longTimeout,
|
||||
skip: !Platform.isWindows,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,38 +153,38 @@ Future<String> _readLspMessage(Stream<List<int>> stream) {
|
||||
final completer = Completer<String>();
|
||||
final buffer = StringBuffer();
|
||||
late final StreamSubscription<String> inSubscription;
|
||||
inSubscription = stream.transform<String>(utf8.decoder).listen(
|
||||
(data) {
|
||||
// Collect the output into the buffer.
|
||||
buffer.write(data);
|
||||
inSubscription = stream.transform<String>(utf8.decoder).listen((data) {
|
||||
// Collect the output into the buffer.
|
||||
buffer.write(data);
|
||||
|
||||
// Check whether the buffer has a complete message.
|
||||
final bufferString = buffer.toString();
|
||||
// Check whether the buffer has a complete message.
|
||||
final bufferString = buffer.toString();
|
||||
|
||||
// If the buffer has what looks like the legacy banner, then just fail
|
||||
// because we will never get an LSP message.
|
||||
if (bufferString.contains('"event":"server.connected"')) {
|
||||
completer.completeError(
|
||||
'Expected LSP message but got legacy message: $bufferString');
|
||||
// If the buffer has what looks like the legacy banner, then just fail
|
||||
// because we will never get an LSP message.
|
||||
if (bufferString.contains('"event":"server.connected"')) {
|
||||
completer.completeError(
|
||||
'Expected LSP message but got legacy message: $bufferString',
|
||||
);
|
||||
}
|
||||
|
||||
// To know if we have a complete message, we need to check we have the
|
||||
// headers, extract the content-length, then check we have that many
|
||||
// bytes in the body.
|
||||
if (bufferString.contains(lspHeaderBodySeparator)) {
|
||||
final parts = bufferString.split(lspHeaderBodySeparator);
|
||||
final headers = parts[0];
|
||||
final body = parts[1];
|
||||
final length = int.parse(
|
||||
contentLengthRegExp.firstMatch(headers)!.group(1)!,
|
||||
);
|
||||
// Check if we're already had the full payload.
|
||||
if (body.length >= length) {
|
||||
completer.complete(body.substring(0, length));
|
||||
inSubscription.cancel();
|
||||
}
|
||||
|
||||
// To know if we have a complete message, we need to check we have the
|
||||
// headers, extract the content-length, then check we have that many
|
||||
// bytes in the body.
|
||||
if (bufferString.contains(lspHeaderBodySeparator)) {
|
||||
final parts = bufferString.split(lspHeaderBodySeparator);
|
||||
final headers = parts[0];
|
||||
final body = parts[1];
|
||||
final length =
|
||||
int.parse(contentLengthRegExp.firstMatch(headers)!.group(1)!);
|
||||
// Check if we're already had the full payload.
|
||||
if (body.length >= length) {
|
||||
completer.complete(body.substring(0, length));
|
||||
inSubscription.cancel();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
@@ -12,39 +12,42 @@ void main() {
|
||||
group('dart mcp-server', () {
|
||||
for (var withExperiment in const [true, false]) {
|
||||
test(
|
||||
'can be connected with a client with${withExperiment ? '' : 'out'} the experiment flag',
|
||||
() async {
|
||||
final client = TestMCPClient();
|
||||
addTearDown(client.shutdown);
|
||||
final process = await Process.start(Platform.resolvedExecutable, [
|
||||
'mcp-server',
|
||||
if (withExperiment) '--experimental-mcp-server',
|
||||
]);
|
||||
'can be connected with a client with${withExperiment ? '' : 'out'} the experiment flag',
|
||||
() async {
|
||||
final client = TestMCPClient();
|
||||
addTearDown(client.shutdown);
|
||||
final process = await Process.start(Platform.resolvedExecutable, [
|
||||
'mcp-server',
|
||||
if (withExperiment) '--experimental-mcp-server',
|
||||
]);
|
||||
|
||||
final connection = client.connectServer(
|
||||
stdioChannel(input: process.stdout, output: process.stdin),
|
||||
);
|
||||
connection.done.then((_) => process.kill());
|
||||
final connection = client.connectServer(
|
||||
stdioChannel(input: process.stdout, output: process.stdin),
|
||||
);
|
||||
connection.done.then((_) => process.kill());
|
||||
|
||||
final initializeResult = await connection.initialize(
|
||||
InitializeRequest(
|
||||
protocolVersion: ProtocolVersion.latestSupported,
|
||||
capabilities: client.capabilities,
|
||||
clientInfo: client.implementation,
|
||||
),
|
||||
);
|
||||
final initializeResult = await connection.initialize(
|
||||
InitializeRequest(
|
||||
protocolVersion: ProtocolVersion.latestSupported,
|
||||
capabilities: client.capabilities,
|
||||
clientInfo: client.implementation,
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
initializeResult.protocolVersion, ProtocolVersion.latestSupported);
|
||||
connection.notifyInitialized();
|
||||
expect(
|
||||
initializeResult.protocolVersion,
|
||||
ProtocolVersion.latestSupported,
|
||||
);
|
||||
connection.notifyInitialized();
|
||||
|
||||
expect(await connection.listTools(ListToolsRequest()), isNotEmpty);
|
||||
});
|
||||
expect(await connection.listTools(ListToolsRequest()), isNotEmpty);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
base class TestMCPClient extends MCPClient {
|
||||
TestMCPClient()
|
||||
: super(Implementation(name: 'test client', version: '0.1.0'));
|
||||
: super(Implementation(name: 'test client', version: '0.1.0'));
|
||||
}
|
||||
|
||||
@@ -67,13 +67,15 @@ void pub() {
|
||||
});
|
||||
|
||||
test('solve failure', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'name': 'myapp',
|
||||
'environment': {'sdk': '^2.19.0'},
|
||||
'dependencies': {
|
||||
'foo': {'path': '../not_to_be_found'},
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'name': 'myapp',
|
||||
'environment': {'sdk': '^2.19.0'},
|
||||
'dependencies': {
|
||||
'foo': {'path': '../not_to_be_found'},
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
final s = Platform.pathSeparator;
|
||||
var result = await p.run(['pub', 'deps']);
|
||||
expect(result.exitCode, 66);
|
||||
@@ -92,6 +94,8 @@ void pub() {
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(
|
||||
result.stderr, startsWith('Could not find an option named "--foo".'));
|
||||
result.stderr,
|
||||
startsWith('Could not find an option named "--foo".'),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,8 +25,9 @@ const devToolsMessagePrefix =
|
||||
'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
|
||||
const dartVMServiceMessagePrefix =
|
||||
'The Dart VM service is listening on http://127.0.0.1:';
|
||||
final dartVMServiceRegExp =
|
||||
RegExp(r'The Dart VM service is listening on (http://127.0.0.1:.*)');
|
||||
final dartVMServiceRegExp = RegExp(
|
||||
r'The Dart VM service is listening on (http://127.0.0.1:.*)',
|
||||
);
|
||||
const residentFrontendCompilerPrefix =
|
||||
'The Resident Frontend Compiler is listening at 127.0.0.1:';
|
||||
const dtdMessagePrefix = 'The Dart Tooling Daemon (DTD) is available at:';
|
||||
@@ -104,8 +105,10 @@ void run() {
|
||||
p = project();
|
||||
var result = await p.run(['run', '--help']);
|
||||
|
||||
expect(result.stdout,
|
||||
contains('Run a Dart program from a file or a local package.'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Run a Dart program from a file or a local package.'),
|
||||
);
|
||||
expect(result.stdout, contains('Debugging options:'));
|
||||
expect(
|
||||
result.stdout,
|
||||
@@ -121,8 +124,10 @@ void run() {
|
||||
p = project();
|
||||
var result = await p.run(['run', '--help', '--verbose']);
|
||||
|
||||
expect(result.stdout,
|
||||
contains('Run a Dart program from a file or a local package.'));
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('Run a Dart program from a file or a local package.'),
|
||||
);
|
||||
expect(result.stdout, contains('Debugging options:'));
|
||||
expect(
|
||||
result.stdout,
|
||||
@@ -145,8 +150,10 @@ void run() {
|
||||
|
||||
test('no such file', () async {
|
||||
p = project(mainSrc: "void main() { print('Hello World'); }");
|
||||
ProcessResult result =
|
||||
await p.run(['run', 'no/such/file/${p.relativeFilePath}']);
|
||||
ProcessResult result = await p.run([
|
||||
'run',
|
||||
'no/such/file/${p.relativeFilePath}',
|
||||
]);
|
||||
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.exitCode, isNot(0));
|
||||
@@ -172,58 +179,61 @@ void run() {
|
||||
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(
|
||||
result.stderr,
|
||||
contains('Could not find `bin${path.separator}dartdev_temp.dart` in '
|
||||
'package `dartdev_temp`.'));
|
||||
result.stderr,
|
||||
contains(
|
||||
'Could not find `bin${path.separator}dartdev_temp.dart` in '
|
||||
'package `dartdev_temp`.',
|
||||
),
|
||||
);
|
||||
expect(result.exitCode, 255);
|
||||
});
|
||||
|
||||
test('experiments are enabled correctly', () async {
|
||||
// TODO(bkonyi): find a more robust way to test experiments by exposing
|
||||
// enabled experiments for an isolate (e.g., through dart:developer or the
|
||||
// VM service).
|
||||
//
|
||||
// See https://github.com/dart-lang/sdk/issues/50230
|
||||
p = project(sdkConstraint: VersionConstraint.parse('>=3.0.0-0 <4.0.0'));
|
||||
p.file('main.dart', 'void main(args) { print("Record: \${(1, 2)}"); }');
|
||||
ProcessResult result = await p.run([
|
||||
'run',
|
||||
'--enable-experiment=records',
|
||||
'main.dart',
|
||||
]);
|
||||
test(
|
||||
'experiments are enabled correctly',
|
||||
() async {
|
||||
// TODO(bkonyi): find a more robust way to test experiments by exposing
|
||||
// enabled experiments for an isolate (e.g., through dart:developer or the
|
||||
// VM service).
|
||||
//
|
||||
// See https://github.com/dart-lang/sdk/issues/50230
|
||||
p = project(sdkConstraint: VersionConstraint.parse('>=3.0.0-0 <4.0.0'));
|
||||
p.file('main.dart', 'void main(args) { print("Record: \${(1, 2)}"); }');
|
||||
ProcessResult result = await p.run([
|
||||
'run',
|
||||
'--enable-experiment=records',
|
||||
'main.dart',
|
||||
]);
|
||||
|
||||
// The records experiment should be enabled.
|
||||
expect(result.stdout, contains('Record: '));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
// The records experiment should be enabled.
|
||||
expect(result.stdout, contains('Record: '));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
// Run again with the experiment disabled to make sure the test is actually
|
||||
// working as expected.
|
||||
result = await p.run([
|
||||
'run',
|
||||
'main.dart',
|
||||
]);
|
||||
// Run again with the experiment disabled to make sure the test is actually
|
||||
// working as expected.
|
||||
result = await p.run(['run', 'main.dart']);
|
||||
|
||||
// The records experiment should not be enabled and the program should fail
|
||||
// to run.
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.exitCode, 254);
|
||||
// The records experiment should not be enabled and the program should fail
|
||||
// to run.
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.exitCode, 254);
|
||||
|
||||
p.file('bin/main.dart', 'void main(args) { print("Record: \${(1, 2)}"); }');
|
||||
// Run again with the package-syntax
|
||||
result = await p.run([
|
||||
'run',
|
||||
'--enable-experiment=records',
|
||||
':main',
|
||||
]);
|
||||
p.file(
|
||||
'bin/main.dart',
|
||||
'void main(args) { print("Record: \${(1, 2)}"); }',
|
||||
);
|
||||
// Run again with the package-syntax
|
||||
result = await p.run(['run', '--enable-experiment=records', ':main']);
|
||||
|
||||
// The records experiment should not be enabled and the program should fail
|
||||
// to run.
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Record: '));
|
||||
expect(result.exitCode, 0);
|
||||
}, skip: 'records are enabled by default in 3.0');
|
||||
// The records experiment should not be enabled and the program should fail
|
||||
// to run.
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Record: '));
|
||||
expect(result.exitCode, 0);
|
||||
},
|
||||
skip: 'records are enabled by default in 3.0',
|
||||
);
|
||||
|
||||
test('arguments are properly passed', () async {
|
||||
p = project();
|
||||
@@ -321,7 +331,8 @@ void main(List<String> args) => print("$b $args");
|
||||
void onData1(event) {
|
||||
if (event.contains('The Dart VM service is listening on')) {
|
||||
final re = RegExp(
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:\d+\/[a-zA-Z0-9_-]+=\/.*');
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:\d+\/[a-zA-Z0-9_-]+=\/.*',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
p.kill();
|
||||
}
|
||||
@@ -344,7 +355,8 @@ void main(List<String> args) => print("$b $args");
|
||||
void onData2(event) {
|
||||
if (event.contains('The Dart VM service is listening on')) {
|
||||
final re = RegExp(
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:\d+\/');
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:\d+\/',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
p.kill();
|
||||
}
|
||||
@@ -368,7 +380,8 @@ void main(List<String> args) => print("$b $args");
|
||||
void onData3(event) {
|
||||
if (event.contains('The Dart VM service is listening on')) {
|
||||
final re = RegExp(
|
||||
r'The Dart VM service is listening on http:\/\/\[::1\]:\d+\/[a-zA-Z0-9_-]+=\/.*');
|
||||
r'The Dart VM service is listening on http:\/\/\[::1\]:\d+\/[a-zA-Z0-9_-]+=\/.*',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
p.kill();
|
||||
}
|
||||
@@ -389,14 +402,19 @@ void main(List<String> args) => print("$b $args");
|
||||
});
|
||||
|
||||
test('with VM environment declaration options specified', () async {
|
||||
p = project(mainSrc: r'''
|
||||
p = project(
|
||||
mainSrc: r'''
|
||||
void main() {
|
||||
print(const bool.fromEnvironment('key'));
|
||||
}
|
||||
''');
|
||||
''',
|
||||
);
|
||||
|
||||
final result =
|
||||
await p.run(['run', '--define=key=true', p.relativeFilePath]);
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--define=key=true',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('true'));
|
||||
@@ -415,24 +433,28 @@ void main(List<String> args) => print("$b $args");
|
||||
|
||||
test('with accepted VM flags related to the timeline', () async {
|
||||
p = project(
|
||||
mainSrc: 'import "dart:developer";'
|
||||
'void main() {'
|
||||
'Timeline.startSync("sync");'
|
||||
'Timeline.finishSync();'
|
||||
'}');
|
||||
mainSrc:
|
||||
'import "dart:developer";'
|
||||
'void main() {'
|
||||
'Timeline.startSync("sync");'
|
||||
'Timeline.finishSync();'
|
||||
'}',
|
||||
);
|
||||
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--timeline-recorder=file',
|
||||
'--timeline-streams=Dart',
|
||||
p.relativeFilePath
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
expect(p.findFile('dart-timeline.json')!.readAsStringSync(),
|
||||
contains('"name":"sync","cat":"Dart"'));
|
||||
expect(
|
||||
p.findFile('dart-timeline.json')!.readAsStringSync(),
|
||||
contains('"name":"sync","cat":"Dart"'),
|
||||
);
|
||||
});
|
||||
|
||||
test('fails when provided verbose VM flags', () async {
|
||||
@@ -573,27 +595,29 @@ void main(List<String> args) => print("$b $args");
|
||||
// Now wait for the process to terminate, if the issue is not fixed
|
||||
// the process will not terminate as it will be paused on the exception,
|
||||
// we timeout and return 255 in that case.
|
||||
int exitCode = await process.exitCode.timeout(const Duration(seconds: 5),
|
||||
onTimeout: () {
|
||||
process.kill();
|
||||
return 255;
|
||||
});
|
||||
int exitCode = await process.exitCode.timeout(
|
||||
const Duration(seconds: 5),
|
||||
onTimeout: () {
|
||||
process.kill();
|
||||
return 255;
|
||||
},
|
||||
);
|
||||
expect(exitCode, 0);
|
||||
});
|
||||
|
||||
test('without verbose CFE info', () async {
|
||||
final p = project(mainSrc: '''void main() {}''');
|
||||
|
||||
var result = await p.run(
|
||||
[
|
||||
'run',
|
||||
'--verbosity=warning',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
);
|
||||
var result = await p.run([
|
||||
'run',
|
||||
'--verbosity=warning',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.stdout,
|
||||
predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)));
|
||||
expect(
|
||||
result.stdout,
|
||||
predicate((dynamic o) => !'$o'.contains(soundNullSafetyMessage)),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
@@ -619,13 +643,11 @@ void main(List<String> args) => print("$b $args");
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(
|
||||
result.stderr,
|
||||
stringContainsInOrder(
|
||||
[
|
||||
'Error encountered while parsing ',
|
||||
'package_config.json:',
|
||||
' Duplicate package name',
|
||||
],
|
||||
),
|
||||
stringContainsInOrder([
|
||||
'Error encountered while parsing ',
|
||||
'package_config.json:',
|
||||
' Duplicate package name',
|
||||
]),
|
||||
);
|
||||
printOnFailure(result.stderr);
|
||||
const int compileErrorExitCode = 254;
|
||||
@@ -634,10 +656,11 @@ void main(List<String> args) => print("$b $args");
|
||||
|
||||
test('workspace', () async {
|
||||
final p = project(
|
||||
sdkConstraint: VersionConstraint.parse('^3.5.0-0'),
|
||||
pubspecExtras: {
|
||||
'workspace': ['pkgs/a', 'pkgs/b']
|
||||
});
|
||||
sdkConstraint: VersionConstraint.parse('^3.5.0-0'),
|
||||
pubspecExtras: {
|
||||
'workspace': ['pkgs/a', 'pkgs/b'],
|
||||
},
|
||||
);
|
||||
p.file('pkgs/a/pubspec.yaml', '''
|
||||
name: a
|
||||
environment:
|
||||
@@ -662,62 +685,56 @@ main() => print('a:tool');
|
||||
main() => print('b:b');
|
||||
''');
|
||||
expect(
|
||||
await p
|
||||
.run(['run', 'a'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:a$eol'));
|
||||
await p.run(['run', 'a'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:a$eol'),
|
||||
);
|
||||
expect(
|
||||
await p
|
||||
.run(['run', 'a:a'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:a$eol'));
|
||||
await p.run([
|
||||
'run',
|
||||
'a:a',
|
||||
], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:a$eol'),
|
||||
);
|
||||
expect(
|
||||
await p.run(['run', ':tool'],
|
||||
workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:tool$eol'));
|
||||
await p.run([
|
||||
'run',
|
||||
':tool',
|
||||
], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'a:tool$eol'),
|
||||
);
|
||||
expect(
|
||||
await p
|
||||
.run(['run', 'b'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'b:b$eol'));
|
||||
await p.run(['run', 'b'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.exitCode, 'exitCode', 0)
|
||||
.having((r) => r.stdout, 'stdout', 'b:b$eol'),
|
||||
);
|
||||
});
|
||||
|
||||
group('DDS', () {
|
||||
group('disable', () {
|
||||
test('dart run simple', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'run',
|
||||
'--no-dds',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDevtoolsMsg: false,
|
||||
),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'run',
|
||||
'--no-dds',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDevtoolsMsg: false));
|
||||
});
|
||||
|
||||
test('dart simple', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'--no-dds',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDevtoolsMsg: false,
|
||||
),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'--no-dds',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDevtoolsMsg: false));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -726,16 +743,13 @@ main() => print('b:b');
|
||||
p = project(mainSrc: observeScript);
|
||||
final tempDir = Directory.systemTemp.createTempSync('a');
|
||||
final serviceInfo = path.join(tempDir.path, 'service.json');
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'run',
|
||||
'--dds',
|
||||
'--enable-vm-service=0',
|
||||
'--write-service-info=$serviceInfo',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(p),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'run',
|
||||
'--dds',
|
||||
'--enable-vm-service=0',
|
||||
'--write-service-info=$serviceInfo',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p));
|
||||
expect(File(serviceInfo).existsSync(), true);
|
||||
});
|
||||
|
||||
@@ -743,15 +757,12 @@ main() => print('b:b');
|
||||
p = project(mainSrc: observeScript);
|
||||
final tempDir = Directory.systemTemp.createTempSync('a');
|
||||
final serviceInfo = path.join(tempDir.path, 'service.json');
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'--dds',
|
||||
'--enable-vm-service=0',
|
||||
'--write-service-info=$serviceInfo',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(p),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'--dds',
|
||||
'--enable-vm-service=0',
|
||||
'--write-service-info=$serviceInfo',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p));
|
||||
expect(File(serviceInfo).existsSync(), true);
|
||||
});
|
||||
});
|
||||
@@ -769,26 +780,20 @@ main() => print('b:b');
|
||||
|
||||
test('dart simple', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(p),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p));
|
||||
});
|
||||
|
||||
test('dart run explicit', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'run',
|
||||
'--serve-devtools',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(p),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'run',
|
||||
'--serve-devtools',
|
||||
'--enable-vm-service=0',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p));
|
||||
});
|
||||
|
||||
test('dart explicit', () async {
|
||||
@@ -802,33 +807,21 @@ main() => print('b:b');
|
||||
|
||||
test('dart run disabled', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'--no-serve-devtools',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDevtoolsMsg: false,
|
||||
),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'--no-serve-devtools',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDevtoolsMsg: false));
|
||||
});
|
||||
|
||||
test('dart disabled', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'--enable-vm-service=0',
|
||||
'--no-serve-devtools',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDevtoolsMsg: false,
|
||||
),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'--enable-vm-service=0',
|
||||
'--no-serve-devtools',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDevtoolsMsg: false));
|
||||
});
|
||||
|
||||
test('dart run VM service not enabled', () async {
|
||||
@@ -857,9 +850,7 @@ main() => print('b:b');
|
||||
mainSrc:
|
||||
'void main() { print("ready"); int i = 0; while(true) { i++; } }',
|
||||
);
|
||||
Process process = await p.start([
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
Process process = await p.start([p.relativeFilePath]);
|
||||
|
||||
final readyCompleter = Completer<void>();
|
||||
final completer = Completer<void>();
|
||||
@@ -888,32 +879,21 @@ main() => print('b:b');
|
||||
group('--print-dtd', () {
|
||||
test('dart', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'--enable-vm-service=0',
|
||||
'--print-dtd',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDtdMsg: true,
|
||||
));
|
||||
await p.runWithVmService([
|
||||
'--enable-vm-service=0',
|
||||
'--print-dtd',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDtdMsg: true));
|
||||
});
|
||||
|
||||
test('dart run', () async {
|
||||
p = project(mainSrc: observeScript);
|
||||
await p.runWithVmService(
|
||||
[
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'--print-dtd',
|
||||
p.relativeFilePath,
|
||||
],
|
||||
onVmServicesData(
|
||||
p,
|
||||
expectDtdMsg: true,
|
||||
),
|
||||
);
|
||||
await p.runWithVmService([
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'--print-dtd',
|
||||
p.relativeFilePath,
|
||||
], onVmServicesData(p, expectDtdMsg: true));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -927,8 +907,9 @@ void residentRun() {
|
||||
serverInfoFile = path.join(serverInfoDirectory.dirPath, 'info');
|
||||
|
||||
final cachedDillFile = File(
|
||||
computeCachedDillAndCompilerOptionsPaths(serverInfoDirectory.mainPath)
|
||||
.cachedDillPath,
|
||||
computeCachedDillAndCompilerOptionsPaths(
|
||||
serverInfoDirectory.mainPath,
|
||||
).cachedDillPath,
|
||||
);
|
||||
expect(cachedDillFile.existsSync(), false);
|
||||
|
||||
@@ -987,31 +968,28 @@ Future<void> main() async {
|
||||
});
|
||||
|
||||
test(
|
||||
'passing --resident is a prerequisite for passing --resident-compiler-info-file',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--$residentCompilerInfoFileOption=$serverInfoFile',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
'passing --resident is a prerequisite for passing --resident-compiler-info-file',
|
||||
() async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--$residentCompilerInfoFileOption=$serverInfoFile',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 255);
|
||||
expect(
|
||||
result.stderr,
|
||||
contains(
|
||||
'Error: the --resident flag must be passed whenever the --resident-compiler-info-file option is passed.',
|
||||
),
|
||||
);
|
||||
});
|
||||
expect(result.exitCode, 255);
|
||||
expect(
|
||||
result.stderr,
|
||||
contains(
|
||||
'Error: the --resident flag must be passed whenever the --resident-compiler-info-file option is passed.',
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('passing --resident is a prerequisite for passing --quiet', () async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--$quietOption',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
final result = await p.run(['run', '--$quietOption', p.relativeFilePath]);
|
||||
|
||||
expect(result.exitCode, 255);
|
||||
expect(
|
||||
@@ -1042,10 +1020,7 @@ Future<void> main() async {
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result.stdout,
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
);
|
||||
expect(result.stdout, isNot(contains(residentFrontendCompilerPrefix)));
|
||||
expect(result.stderr, isEmpty);
|
||||
});
|
||||
|
||||
@@ -1106,66 +1081,69 @@ Future<void> main() async {
|
||||
cachedDillFile.deleteSync();
|
||||
});
|
||||
|
||||
test("'Hello World' with legacy --resident-server-info-file option",
|
||||
() async {
|
||||
p = project(mainSrc: "void main() { print('Hello World'); }");
|
||||
test(
|
||||
"'Hello World' with legacy --resident-server-info-file option",
|
||||
() async {
|
||||
p = project(mainSrc: "void main() { print('Hello World'); }");
|
||||
|
||||
final cachedDillFile = File(
|
||||
computeCachedDillAndCompilerOptionsPaths(p.mainPath).cachedDillPath,
|
||||
);
|
||||
expect(cachedDillFile.existsSync(), false);
|
||||
final cachedDillFile = File(
|
||||
computeCachedDillAndCompilerOptionsPaths(p.mainPath).cachedDillPath,
|
||||
);
|
||||
expect(cachedDillFile.existsSync(), false);
|
||||
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--resident-server-info-file=$serverInfoFile',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result.stdout,
|
||||
allOf(
|
||||
contains('Hello World'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(cachedDillFile.existsSync(), true);
|
||||
cachedDillFile.deleteSync();
|
||||
});
|
||||
|
||||
test('--resident-compiler-info-file handles relative paths correctly',
|
||||
() async {
|
||||
p = project(mainSrc: "void main() { print('Hello World'); }");
|
||||
|
||||
final cachedDillFile = File(
|
||||
computeCachedDillAndCompilerOptionsPaths(p.mainPath).cachedDillPath,
|
||||
);
|
||||
expect(cachedDillFile.existsSync(), false);
|
||||
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--$residentCompilerInfoFileOption=${path.relative(serverInfoFile, from: p.dirPath)}',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result.stdout,
|
||||
allOf(
|
||||
contains('Hello World'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(cachedDillFile.existsSync(), true);
|
||||
cachedDillFile.deleteSync();
|
||||
});
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result.stdout,
|
||||
allOf(
|
||||
contains('Hello World'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(cachedDillFile.existsSync(), true);
|
||||
cachedDillFile.deleteSync();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'a running resident compiler is restarted if the Dart SDK was '
|
||||
'--resident-compiler-info-file handles relative paths correctly',
|
||||
() async {
|
||||
p = project(mainSrc: "void main() { print('Hello World'); }");
|
||||
|
||||
final cachedDillFile = File(
|
||||
computeCachedDillAndCompilerOptionsPaths(p.mainPath).cachedDillPath,
|
||||
);
|
||||
expect(cachedDillFile.existsSync(), false);
|
||||
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--$residentCompilerInfoFileOption=${path.relative(serverInfoFile, from: p.dirPath)}',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(
|
||||
result.stdout,
|
||||
allOf(
|
||||
contains('Hello World'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(cachedDillFile.existsSync(), true);
|
||||
cachedDillFile.deleteSync();
|
||||
},
|
||||
);
|
||||
|
||||
test('a running resident compiler is restarted if the Dart SDK was '
|
||||
'upgraded or downgraded since it was started', () async {
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
|
||||
@@ -1218,48 +1196,48 @@ Future<void> main() async {
|
||||
expect(File(serverInfoFile).existsSync(), true);
|
||||
});
|
||||
|
||||
test('when a connection to a running resident compiler cannot be established',
|
||||
() async {
|
||||
// When this occurs, the user should be informed that the resident frontend
|
||||
// compiler will be restarted, and compilation will be retried.
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
// Create a [testServerInfoFile] that contains an invalid port to guarantee
|
||||
// that a connection will not be established.
|
||||
final testServerInfoFile = File(path.join(p.dirPath, 'info'));
|
||||
testServerInfoFile.createSync();
|
||||
testServerInfoFile.writeAsStringSync(
|
||||
'address:127.0.0.1 sdkHash:$sdkHashNull port:-12 ',
|
||||
);
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--$residentCompilerInfoFileOption=${testServerInfoFile.path}',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
test(
|
||||
'when a connection to a running resident compiler cannot be established',
|
||||
() async {
|
||||
// When this occurs, the user should be informed that the resident frontend
|
||||
// compiler will be restarted, and compilation will be retried.
|
||||
p = project(mainSrc: 'void main() {}');
|
||||
// Create a [testServerInfoFile] that contains an invalid port to guarantee
|
||||
// that a connection will not be established.
|
||||
final testServerInfoFile = File(path.join(p.dirPath, 'info'));
|
||||
testServerInfoFile.createSync();
|
||||
testServerInfoFile.writeAsStringSync(
|
||||
'address:127.0.0.1 sdkHash:$sdkHashNull port:-12 ',
|
||||
);
|
||||
final result = await p.run([
|
||||
'run',
|
||||
'--resident',
|
||||
'--$residentCompilerInfoFileOption=${testServerInfoFile.path}',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, contains(residentFrontendCompilerPrefix));
|
||||
expect(
|
||||
result.stderr,
|
||||
'Error: A connection to the Resident Frontend Compiler could not be '
|
||||
'established. Restarting the Resident Frontend Compiler and retrying '
|
||||
'compilation.\n',
|
||||
);
|
||||
expect(testServerInfoFile.existsSync(), true);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, contains(residentFrontendCompilerPrefix));
|
||||
expect(
|
||||
result.stderr,
|
||||
'Error: A connection to the Resident Frontend Compiler could not be '
|
||||
'established. Restarting the Resident Frontend Compiler and retrying '
|
||||
'compilation.\n',
|
||||
);
|
||||
expect(testServerInfoFile.existsSync(), true);
|
||||
|
||||
await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption=${testServerInfoFile.path}',
|
||||
]);
|
||||
});
|
||||
await p.run([
|
||||
'compilation-server',
|
||||
'shutdown',
|
||||
'--$residentCompilerInfoFileOption=${testServerInfoFile.path}',
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test('Handles experiments', () async {
|
||||
p = project(
|
||||
mainSrc: r"void main() { print(('hello','world').$1); }",
|
||||
sdkConstraint: VersionConstraint.parse(
|
||||
'^3.0.0',
|
||||
),
|
||||
sdkConstraint: VersionConstraint.parse('^3.0.0'),
|
||||
);
|
||||
|
||||
final (:cachedDillPath, :cachedCompilerOptionsPath) =
|
||||
@@ -1280,10 +1258,7 @@ Future<void> main() async {
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(
|
||||
result.stdout,
|
||||
allOf(
|
||||
contains('hello'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
allOf(contains('hello'), isNot(contains(residentFrontendCompilerPrefix))),
|
||||
);
|
||||
expect(result.exitCode, 0);
|
||||
|
||||
@@ -1291,8 +1266,8 @@ Future<void> main() async {
|
||||
cachedDillFile.deleteSync();
|
||||
|
||||
expect(cachedCompilerOptionsFile.existsSync(), true);
|
||||
final cachedCompilerOptionsFileContents =
|
||||
cachedCompilerOptionsFile.readAsStringSync();
|
||||
final cachedCompilerOptionsFileContents = cachedCompilerOptionsFile
|
||||
.readAsStringSync();
|
||||
cachedCompilerOptionsFile.deleteSync();
|
||||
|
||||
// [cachedCompilerOptionsFileContents] should be a valid JSON list that
|
||||
@@ -1326,17 +1301,11 @@ Future<void> main() async {
|
||||
expect(runResult1.exitCode, allOf(0, equals(runResult2.exitCode)));
|
||||
expect(
|
||||
runResult1.stdout,
|
||||
allOf(
|
||||
contains('1'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
allOf(contains('1'), isNot(contains(residentFrontendCompilerPrefix))),
|
||||
);
|
||||
expect(
|
||||
runResult2.stdout,
|
||||
allOf(
|
||||
contains('2'),
|
||||
isNot(contains(residentFrontendCompilerPrefix)),
|
||||
),
|
||||
allOf(contains('2'), isNot(contains(residentFrontendCompilerPrefix))),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1452,7 +1421,8 @@ Future<void> main() async {
|
||||
void onData1(event) {
|
||||
if (event.contains('The Dart VM service is listening on')) {
|
||||
final re = RegExp(
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:[0-9+]');
|
||||
r'The Dart VM service is listening on http:\/\/127.0.0.1:[0-9+]',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
sawVmServiceMsg = true;
|
||||
}
|
||||
@@ -1461,7 +1431,8 @@ Future<void> main() async {
|
||||
}
|
||||
if (event.contains('The Resident Frontend Compiler is listening')) {
|
||||
final re = RegExp(
|
||||
r'The Resident Frontend Compiler is listening at 127.0.0.1:[0-9]+');
|
||||
r'The Resident Frontend Compiler is listening at 127.0.0.1:[0-9]+',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
sawCFEMsg = true;
|
||||
}
|
||||
@@ -1518,7 +1489,8 @@ Future<void> main() async {
|
||||
void onData2(event) {
|
||||
if (event.contains('The Dart VM service is listening on')) {
|
||||
final re = RegExp(
|
||||
r'The Dart VM service is listening on http:\/\/\[::1\]:\d+\/[a-zA-Z0-9_-]+=\/.*');
|
||||
r'The Dart VM service is listening on http:\/\/\[::1\]:\d+\/[a-zA-Z0-9_-]+=\/.*',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
sawVmServiceMsg = true;
|
||||
}
|
||||
@@ -1527,7 +1499,8 @@ Future<void> main() async {
|
||||
}
|
||||
if (event.contains('The Resident Frontend Compiler is listening')) {
|
||||
final re = RegExp(
|
||||
r'The Resident Frontend Compiler is listening at 127.0.0.1:[0-9]+');
|
||||
r'The Resident Frontend Compiler is listening at 127.0.0.1:[0-9]+',
|
||||
);
|
||||
expect(re.hasMatch(event), true);
|
||||
sawCFEMsg = true;
|
||||
}
|
||||
@@ -1556,22 +1529,31 @@ Future<void> main() async {
|
||||
});
|
||||
|
||||
test('custom package_config path', () async {
|
||||
p = project(name: 'foo', mainSrc: '''
|
||||
p = project(
|
||||
name: 'foo',
|
||||
mainSrc: '''
|
||||
import 'package:bar/main.dart';
|
||||
void main() {
|
||||
cmd();
|
||||
}
|
||||
''');
|
||||
final bar1 = project(name: 'bar1', mainSrc: '''
|
||||
''',
|
||||
);
|
||||
final bar1 = project(
|
||||
name: 'bar1',
|
||||
mainSrc: '''
|
||||
cmd() {
|
||||
print('hi');
|
||||
}
|
||||
''');
|
||||
final bar2 = project(name: 'bar2', mainSrc: '''
|
||||
''',
|
||||
);
|
||||
final bar2 = project(
|
||||
name: 'bar2',
|
||||
mainSrc: '''
|
||||
cmd() {
|
||||
print('bye');
|
||||
}
|
||||
''');
|
||||
''',
|
||||
);
|
||||
|
||||
p.file('custom_packages1.json', '''
|
||||
{
|
||||
|
||||
@@ -23,25 +23,32 @@ void main() {
|
||||
|
||||
void defineTest(List<Experiment> experiments) {
|
||||
test('--help', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
});
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
|
||||
final result = await p.run(['test', '--help']);
|
||||
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, startsWith('''
|
||||
expect(
|
||||
result.stdout,
|
||||
startsWith('''
|
||||
Runs tests in this package.
|
||||
|
||||
Usage: dart test [files or directories...]
|
||||
'''));
|
||||
'''),
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
});
|
||||
|
||||
test('dart help test', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
});
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
|
||||
final result = await p.run(['help', 'test']);
|
||||
|
||||
@@ -51,9 +58,11 @@ Usage: dart test [files or directories...]
|
||||
});
|
||||
|
||||
test('no pubspec.yaml', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
});
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
var pubspec = File(path.join(p.dirPath, 'pubspec.yaml'));
|
||||
pubspec.deleteSync();
|
||||
|
||||
@@ -74,9 +83,11 @@ No pubspec.yaml file found - run this command in your project folder.
|
||||
});
|
||||
|
||||
test('runs test', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
});
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('test/foo_test.dart', '''
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -88,8 +99,12 @@ void main() {
|
||||
''');
|
||||
|
||||
// An implicit `pub get` will happen.
|
||||
final result =
|
||||
await p.run(['test', '--no-color', '--reporter', 'expanded']);
|
||||
final result = await p.run([
|
||||
'test',
|
||||
'--no-color',
|
||||
'--reporter',
|
||||
'expanded',
|
||||
]);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('All tests passed!'));
|
||||
expect(result.exitCode, 0);
|
||||
@@ -99,7 +114,7 @@ void main() {
|
||||
final p = project(
|
||||
mainSrc: 'int get foo => 1;\n',
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('pubspec.yaml', '''
|
||||
@@ -129,8 +144,12 @@ void main() {
|
||||
final resultPubAdd = await p.run(['pub', 'add', 'test']);
|
||||
|
||||
expect(resultPubAdd.exitCode, 0);
|
||||
final result2 =
|
||||
await p.run(['test', '--no-color', '--reporter', 'expanded']);
|
||||
final result2 = await p.run([
|
||||
'test',
|
||||
'--no-color',
|
||||
'--reporter',
|
||||
'expanded',
|
||||
]);
|
||||
expect(result2.stderr, isEmpty);
|
||||
expect(result2.stdout, contains('All tests passed!'));
|
||||
expect(result2.exitCode, 0);
|
||||
@@ -140,7 +159,7 @@ void main() {
|
||||
final p = project(
|
||||
mainSrc: 'int get foo => 1;\n',
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('test/foo_test.dart', '''
|
||||
@@ -153,8 +172,12 @@ void main() {
|
||||
}
|
||||
''');
|
||||
|
||||
final result =
|
||||
await p.run(['test', '--no-color', '--reporter', 'expanded']);
|
||||
final result = await p.run([
|
||||
'test',
|
||||
'--no-color',
|
||||
'--reporter',
|
||||
'expanded',
|
||||
]);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stdout, contains('All tests passed!'));
|
||||
expect(result.stderr, isEmpty);
|
||||
@@ -168,7 +191,7 @@ void main() {
|
||||
final p = project(
|
||||
mainSrc: 'int get foo => 1;\n',
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('test/foo_test.dart', '''
|
||||
@@ -181,8 +204,9 @@ void main() {
|
||||
}
|
||||
''');
|
||||
|
||||
final vmServiceUriRegExp =
|
||||
RegExp(r'(http:\/\/127.0.0.1:\d*\/[\da-zA-Z-_]*=\/)');
|
||||
final vmServiceUriRegExp = RegExp(
|
||||
r'(http:\/\/127.0.0.1:\d*\/[\da-zA-Z-_]*=\/)',
|
||||
);
|
||||
final process = await p.start(['test', '--pause-after-load']);
|
||||
final completer = Completer<Uri>();
|
||||
late final StreamSubscription<String> sub;
|
||||
@@ -190,16 +214,16 @@ void main() {
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.listen((line) async {
|
||||
if (line.contains(vmServiceUriRegExp)) {
|
||||
await sub.cancel();
|
||||
final httpUri = Uri.parse(
|
||||
vmServiceUriRegExp.firstMatch(line)!.group(0)!,
|
||||
);
|
||||
completer.complete(
|
||||
httpUri.replace(scheme: 'ws', path: '${httpUri.path}ws'),
|
||||
);
|
||||
}
|
||||
});
|
||||
if (line.contains(vmServiceUriRegExp)) {
|
||||
await sub.cancel();
|
||||
final httpUri = Uri.parse(
|
||||
vmServiceUriRegExp.firstMatch(line)!.group(0)!,
|
||||
);
|
||||
completer.complete(
|
||||
httpUri.replace(scheme: 'ws', path: '${httpUri.path}ws'),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
final vmServiceUri = await completer.future;
|
||||
final vmService = await vmServiceConnectUri(vmServiceUri.toString());
|
||||
@@ -211,9 +235,11 @@ void main() {
|
||||
group('properly handles --suppress-analytics', () {
|
||||
void suppressAnalyticsTest({required bool beforeCommand}) {
|
||||
test('${beforeCommand ? 'before' : 'after'} command', () async {
|
||||
final p = project(pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
});
|
||||
final p = project(
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('test/foo_test.dart', '''
|
||||
import 'package:test/test.dart';
|
||||
|
||||
@@ -247,7 +273,7 @@ void main() {
|
||||
late TestProject p;
|
||||
Future<ProcessResult> runTestWithExperimentFlag(String? flag) async {
|
||||
return await p.run([
|
||||
if (flag != null) flag,
|
||||
?flag,
|
||||
'test',
|
||||
'--no-color',
|
||||
'--reporter',
|
||||
@@ -257,10 +283,16 @@ void main() {
|
||||
|
||||
Future<void> expectSuccess(String? flag) async {
|
||||
final result = await runTestWithExperimentFlag(flag);
|
||||
expect(result.stdout, contains('feature enabled'),
|
||||
reason: 'stderr: ${result.stderr}');
|
||||
expect(result.exitCode, 0,
|
||||
reason: 'stdout: ${result.stdout} stderr: ${result.stderr}');
|
||||
expect(
|
||||
result.stdout,
|
||||
contains('feature enabled'),
|
||||
reason: 'stderr: ${result.stderr}',
|
||||
);
|
||||
expect(
|
||||
result.exitCode,
|
||||
0,
|
||||
reason: 'stdout: ${result.stdout} stderr: ${result.stderr}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> expectFailure(String? flag) async {
|
||||
@@ -275,7 +307,7 @@ void main() {
|
||||
mainSrc: experiment.validation,
|
||||
sdkConstraint: VersionConstraint.compatibleWith(currentSdk),
|
||||
pubspecExtras: {
|
||||
'dev_dependencies': {'test': 'any'}
|
||||
'dev_dependencies': {'test': 'any'},
|
||||
},
|
||||
);
|
||||
p.file('test/experiment_test.dart', '''
|
||||
@@ -303,10 +335,11 @@ void main() {
|
||||
|
||||
test('workspace', () async {
|
||||
final p = project(
|
||||
sdkConstraint: VersionConstraint.parse('^3.5.0-0'),
|
||||
pubspecExtras: {
|
||||
'workspace': ['pkgs/a', 'pkgs/b']
|
||||
});
|
||||
sdkConstraint: VersionConstraint.parse('^3.5.0-0'),
|
||||
pubspecExtras: {
|
||||
'workspace': ['pkgs/a', 'pkgs/b'],
|
||||
},
|
||||
);
|
||||
p.file('pkgs/a/pubspec.yaml', '''
|
||||
name: a
|
||||
environment:
|
||||
@@ -334,10 +367,11 @@ main() {
|
||||
main() => throw('Test failure');
|
||||
''');
|
||||
expect(
|
||||
await p.run(['test'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.stdout, 'stdout', contains('testing package a\n'))
|
||||
.having((r) => r.stderr, 'stderr', isEmpty)
|
||||
.having((r) => r.exitCode, 'exitCode', 0));
|
||||
await p.run(['test'], workingDir: path.join(p.dirPath, 'pkgs', 'a')),
|
||||
isA<ProcessResult>()
|
||||
.having((r) => r.stdout, 'stdout', contains('testing package a\n'))
|
||||
.having((r) => r.stderr, 'stderr', isEmpty)
|
||||
.having((r) => r.exitCode, 'exitCode', 0),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,29 +12,25 @@ import '../utils.dart' as utils;
|
||||
void main() {
|
||||
utils.ensureRunFromSdkBinDart();
|
||||
|
||||
group(
|
||||
'tooling-daemon',
|
||||
() {
|
||||
final dartToolingDaemonRegExp = RegExp(
|
||||
r'The Dart Tooling Daemon is listening on ws://(127.0.0.1:.*)',
|
||||
);
|
||||
Process? process;
|
||||
group('tooling-daemon', () {
|
||||
final dartToolingDaemonRegExp = RegExp(
|
||||
r'The Dart Tooling Daemon is listening on ws://(127.0.0.1:.*)',
|
||||
);
|
||||
Process? process;
|
||||
|
||||
tearDown(() {
|
||||
process?.kill();
|
||||
process = null;
|
||||
});
|
||||
tearDown(() {
|
||||
process?.kill();
|
||||
process = null;
|
||||
});
|
||||
|
||||
test('starts up', () async {
|
||||
final project = utils.project();
|
||||
process = await project.start(['tooling-daemon']);
|
||||
final stdout = process!.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter());
|
||||
test('starts up', () async {
|
||||
final project = utils.project();
|
||||
process = await project.start(['tooling-daemon']);
|
||||
final stdout = process!.stdout
|
||||
.transform<String>(utf8.decoder)
|
||||
.transform<String>(const LineSplitter());
|
||||
|
||||
expect(await stdout.first, contains(dartToolingDaemonRegExp));
|
||||
});
|
||||
},
|
||||
timeout: utils.longTimeout,
|
||||
);
|
||||
expect(await stdout.first, contains(dartToolingDaemonRegExp));
|
||||
});
|
||||
}, timeout: utils.longTimeout);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ void main() {
|
||||
|
||||
void _dartdevCommand() {
|
||||
void assertDartdevCommandProperties(
|
||||
DartdevCommand command, String name, String expectedUsagePath,
|
||||
[int subcommandCount = 0]) {
|
||||
DartdevCommand command,
|
||||
String name,
|
||||
String expectedUsagePath, [
|
||||
int subcommandCount = 0,
|
||||
]) {
|
||||
expect(command, isNotNull);
|
||||
expect(command.name, name);
|
||||
expect(command.description, isNotEmpty);
|
||||
@@ -44,51 +47,58 @@ void _dartdevCommand() {
|
||||
|
||||
test('compile/js', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['js'] as DartdevCommand,
|
||||
'js',
|
||||
'compile/js');
|
||||
CompileCommand().subcommands['js'] as DartdevCommand,
|
||||
'js',
|
||||
'compile/js',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/js-dev', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['js-dev'] as DartdevCommand,
|
||||
'js-dev',
|
||||
'compile/js-dev');
|
||||
CompileCommand().subcommands['js-dev'] as DartdevCommand,
|
||||
'js-dev',
|
||||
'compile/js-dev',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/jit-snapshot', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['jit-snapshot'] as DartdevCommand,
|
||||
'jit-snapshot',
|
||||
'compile/jit-snapshot');
|
||||
CompileCommand().subcommands['jit-snapshot'] as DartdevCommand,
|
||||
'jit-snapshot',
|
||||
'compile/jit-snapshot',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/kernel', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['kernel'] as DartdevCommand,
|
||||
'kernel',
|
||||
'compile/kernel');
|
||||
CompileCommand().subcommands['kernel'] as DartdevCommand,
|
||||
'kernel',
|
||||
'compile/kernel',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/exe', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['exe'] as DartdevCommand,
|
||||
'exe',
|
||||
'compile/exe');
|
||||
CompileCommand().subcommands['exe'] as DartdevCommand,
|
||||
'exe',
|
||||
'compile/exe',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/aot-snapshot', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['aot-snapshot'] as DartdevCommand,
|
||||
'aot-snapshot',
|
||||
'compile/aot-snapshot');
|
||||
CompileCommand().subcommands['aot-snapshot'] as DartdevCommand,
|
||||
'aot-snapshot',
|
||||
'compile/aot-snapshot',
|
||||
);
|
||||
});
|
||||
|
||||
test('compile/wasm', () {
|
||||
assertDartdevCommandProperties(
|
||||
CompileCommand().subcommands['wasm'] as DartdevCommand,
|
||||
'wasm',
|
||||
'compile/wasm');
|
||||
CompileCommand().subcommands['wasm'] as DartdevCommand,
|
||||
'wasm',
|
||||
'compile/wasm',
|
||||
);
|
||||
});
|
||||
|
||||
test('create', () {
|
||||
|
||||
@@ -32,8 +32,9 @@ final experimentalFeaturesYaml = () {
|
||||
/// break test_all.dart.
|
||||
List<Experiment> experimentsWithValidation() {
|
||||
final experiments = yaml.loadYaml(
|
||||
File(experimentalFeaturesYaml).readAsStringSync(),
|
||||
sourceUrl: path.toUri(experimentalFeaturesYaml));
|
||||
File(experimentalFeaturesYaml).readAsStringSync(),
|
||||
sourceUrl: path.toUri(experimentalFeaturesYaml),
|
||||
);
|
||||
return [
|
||||
for (final e in experiments['features'].entries)
|
||||
if (e.value['expired'] != true && e.value['validation'] != null)
|
||||
@@ -42,7 +43,7 @@ List<Experiment> experimentsWithValidation() {
|
||||
e.value['validation'],
|
||||
tryParseVersion(e.value['enabledIn']),
|
||||
tryParseVersion(e.value['experimentalReleaseVersion']),
|
||||
)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,16 +13,21 @@ void main() {
|
||||
|
||||
setUp(() => p = project(mainSrc: "void main() { print('Hello World'); }"));
|
||||
|
||||
test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
|
||||
() async {
|
||||
// The DartDev snapshot includes the --use_field_guards flag. If
|
||||
// --no-use-field-guards is passed, the VM will fail to load the
|
||||
// snapshot and should fall back to using the DartDev dill file.
|
||||
ProcessResult result =
|
||||
await p.run(['--no-use-field-guards', 'run', p.relativeFilePath]);
|
||||
test(
|
||||
"Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
|
||||
() async {
|
||||
// The DartDev snapshot includes the --use_field_guards flag. If
|
||||
// --no-use-field-guards is passed, the VM will fail to load the
|
||||
// snapshot and should fall back to using the DartDev dill file.
|
||||
ProcessResult result = await p.run([
|
||||
'--no-use-field-guards',
|
||||
'run',
|
||||
p.relativeFilePath,
|
||||
]);
|
||||
|
||||
expect(result.stdout, contains('Hello World'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
});
|
||||
expect(result.stdout, contains('Hello World'));
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.exitCode, 0);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,9 @@ const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
|
||||
Future<void> inTempDir(Future<void> Function(Uri tempUri) fun) async {
|
||||
final tempDir = await Directory.systemTemp.createTemp();
|
||||
// Deal with Windows temp folder aliases.
|
||||
final tempUri =
|
||||
Directory(await tempDir.resolveSymbolicLinks()).uri.normalizePath();
|
||||
final tempUri = Directory(
|
||||
await tempDir.resolveSymbolicLinks(),
|
||||
).uri.normalizePath();
|
||||
try {
|
||||
await fun(tempUri);
|
||||
} finally {
|
||||
@@ -64,22 +65,26 @@ Future<run_process.RunProcessResult> runProcess({
|
||||
bool captureOutput = true,
|
||||
int expectedExitCode = 0,
|
||||
bool throwOnUnexpectedExitCode = false,
|
||||
}) =>
|
||||
run_process.runProcess(
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
includeParentEnvironment: includeParentEnvironment,
|
||||
logger: logger,
|
||||
captureOutput: captureOutput,
|
||||
expectedExitCode: expectedExitCode,
|
||||
throwOnUnexpectedExitCode: throwOnUnexpectedExitCode,
|
||||
filesystem: const LocalFileSystem(),
|
||||
);
|
||||
}) => run_process.runProcess(
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
includeParentEnvironment: includeParentEnvironment,
|
||||
logger: logger,
|
||||
captureOutput: captureOutput,
|
||||
expectedExitCode: expectedExitCode,
|
||||
throwOnUnexpectedExitCode: throwOnUnexpectedExitCode,
|
||||
filesystem: const LocalFileSystem(),
|
||||
);
|
||||
|
||||
Future<void> copyTestProjects(Uri copyTargetUri, Logger logger,
|
||||
Uri packageLocation, Uri sdkRoot, bool usePubWorkspace) async {
|
||||
Future<void> copyTestProjects(
|
||||
Uri copyTargetUri,
|
||||
Logger logger,
|
||||
Uri packageLocation,
|
||||
Uri sdkRoot,
|
||||
bool usePubWorkspace,
|
||||
) async {
|
||||
// Reuse the test projects from `pkg:native`.
|
||||
final testProjectsUri = packageLocation.resolve('test_data/');
|
||||
final manifestUri = testProjectsUri.resolve('manifest.yaml');
|
||||
@@ -87,16 +92,21 @@ Future<void> copyTestProjects(Uri copyTargetUri, Logger logger,
|
||||
final manifestString = await manifestFile.readAsString();
|
||||
final manifestYaml = loadYamlDocument(manifestString);
|
||||
final manifest = [
|
||||
for (final path in manifestYaml.contents as YamlList) Uri(path: path)
|
||||
for (final path in manifestYaml.contents as YamlList) Uri(path: path),
|
||||
];
|
||||
final filesToCopy = manifest
|
||||
.where((e) => !(e.pathSegments.last.startsWith('pubspec') &&
|
||||
e.pathSegments.last.endsWith('.yaml')))
|
||||
.where(
|
||||
(e) =>
|
||||
!(e.pathSegments.last.startsWith('pubspec') &&
|
||||
e.pathSegments.last.endsWith('.yaml')),
|
||||
)
|
||||
.toList();
|
||||
final pubspecPaths = manifest
|
||||
.where((e) =>
|
||||
e.pathSegments.last.startsWith('pubspec') &&
|
||||
e.pathSegments.last.endsWith('.yaml'))
|
||||
.where(
|
||||
(e) =>
|
||||
e.pathSegments.last.startsWith('pubspec') &&
|
||||
e.pathSegments.last.endsWith('.yaml'),
|
||||
)
|
||||
.toList();
|
||||
|
||||
for (final pathToCopy in filesToCopy) {
|
||||
@@ -122,9 +132,7 @@ Future<void> copyTestProjects(Uri copyTargetUri, Logger logger,
|
||||
.resolve('third_party/pkg/native/pkgs/$package/')
|
||||
.toFilePath(),
|
||||
},
|
||||
'meta': {
|
||||
'path': sdkRoot.resolve('pkg/meta/').toFilePath(),
|
||||
},
|
||||
'meta': {'path': sdkRoot.resolve('pkg/meta/').toFilePath()},
|
||||
};
|
||||
final userDefinesWorkspace = {};
|
||||
for (final pubspecPath in pubspecPaths) {
|
||||
@@ -177,9 +185,7 @@ Future<void> copyTestProjects(Uri copyTargetUri, Logger logger,
|
||||
pubspec.toFilePath().replaceAll('pubspec.yaml', ''),
|
||||
],
|
||||
'dependency_overrides': dependencyOverrides,
|
||||
'hooks': {
|
||||
'user_defines': userDefinesWorkspace,
|
||||
}
|
||||
'hooks': {'user_defines': userDefinesWorkspace},
|
||||
});
|
||||
final pubspecUri = copyTargetUri.resolve('pubspec.yaml');
|
||||
await File.fromUri(pubspecUri).writeAsString(workspacePubspec.toString());
|
||||
@@ -189,10 +195,7 @@ Future<void> copyTestProjects(Uri copyTargetUri, Logger logger,
|
||||
// native assets are pre-built
|
||||
final myNativeLibraryUri = copyTargetUri.resolve('my_native_library/');
|
||||
if (await Directory(myNativeLibraryUri.toFilePath()).exists()) {
|
||||
await runPubGet(
|
||||
workingDirectory: myNativeLibraryUri,
|
||||
logger: logger,
|
||||
);
|
||||
await runPubGet(workingDirectory: myNativeLibraryUri, logger: logger);
|
||||
await runDart(
|
||||
arguments: ['tool/native.dart', 'build'],
|
||||
workingDirectory: myNativeLibraryUri,
|
||||
@@ -216,22 +219,17 @@ Future<void> runPubGet({
|
||||
void expectDartAppStdout(String stdout) {
|
||||
expect(
|
||||
stdout,
|
||||
stringContainsInOrder(
|
||||
[
|
||||
'add(5, 6) = 11',
|
||||
'subtract(5, 6) = -1',
|
||||
],
|
||||
),
|
||||
stringContainsInOrder(['add(5, 6) = 11', 'subtract(5, 6) = -1']),
|
||||
);
|
||||
}
|
||||
|
||||
/// Logger that outputs the full trace when a test fails.
|
||||
Logger get logger => _logger ??= () {
|
||||
// A new logger is lazily created for each test so that the messages
|
||||
// captured by printOnFailure are scoped to the correct test.
|
||||
addTearDown(() => _logger = null);
|
||||
return _createTestLogger();
|
||||
}();
|
||||
// A new logger is lazily created for each test so that the messages
|
||||
// captured by printOnFailure are scoped to the correct test.
|
||||
addTearDown(() => _logger = null);
|
||||
return _createTestLogger();
|
||||
}();
|
||||
|
||||
Logger? _logger;
|
||||
|
||||
@@ -243,7 +241,8 @@ Logger _createTestLogger({List<String>? capturedMessages}) =>
|
||||
..level = Level.ALL
|
||||
..onRecord.listen((record) {
|
||||
printOnFailure(
|
||||
'${record.level.name}: ${record.time}: ${record.message}');
|
||||
'${record.level.name}: ${record.time}: ${record.message}',
|
||||
);
|
||||
capturedMessages?.add(record.message);
|
||||
});
|
||||
|
||||
@@ -253,41 +252,39 @@ Future<void> nativeAssetsTest(
|
||||
String packageUnderTest,
|
||||
Future<void> Function(Uri) fun, {
|
||||
bool usePubWorkspace = false,
|
||||
}) async =>
|
||||
await runPackageTest(
|
||||
packageUnderTest,
|
||||
fun,
|
||||
const [
|
||||
'add_asset_link',
|
||||
'dart_app',
|
||||
'dev_dependency_with_hook',
|
||||
'drop_dylib_link',
|
||||
'native_add_duplicate',
|
||||
'native_add_version_skew',
|
||||
'native_add',
|
||||
'native_dynamic_linking',
|
||||
'recursive_invocation',
|
||||
'system_library',
|
||||
'treeshaking_native_libs',
|
||||
'user_defines',
|
||||
],
|
||||
sdkRootUri.resolve('third_party/pkg/native/pkgs/hooks_runner/'),
|
||||
sdkRootUri,
|
||||
usePubWorkspace,
|
||||
);
|
||||
}) async => await runPackageTest(
|
||||
packageUnderTest,
|
||||
fun,
|
||||
const [
|
||||
'add_asset_link',
|
||||
'dart_app',
|
||||
'dev_dependency_with_hook',
|
||||
'drop_dylib_link',
|
||||
'native_add_duplicate',
|
||||
'native_add_version_skew',
|
||||
'native_add',
|
||||
'native_dynamic_linking',
|
||||
'recursive_invocation',
|
||||
'system_library',
|
||||
'treeshaking_native_libs',
|
||||
'user_defines',
|
||||
],
|
||||
sdkRootUri.resolve('third_party/pkg/native/pkgs/hooks_runner/'),
|
||||
sdkRootUri,
|
||||
usePubWorkspace,
|
||||
);
|
||||
|
||||
Future<void> recordUseTest(
|
||||
String packageUnderTest,
|
||||
Future<void> Function(Uri) fun,
|
||||
) async =>
|
||||
await runPackageTest(
|
||||
packageUnderTest,
|
||||
fun,
|
||||
const ['drop_dylib_recording', 'drop_data_asset'],
|
||||
sdkRootUri.resolve('third_party/pkg/native/pkgs/record_use/'),
|
||||
sdkRootUri,
|
||||
false,
|
||||
);
|
||||
) async => await runPackageTest(
|
||||
packageUnderTest,
|
||||
fun,
|
||||
const ['drop_dylib_recording', 'drop_data_asset'],
|
||||
sdkRootUri.resolve('third_party/pkg/native/pkgs/record_use/'),
|
||||
sdkRootUri,
|
||||
false,
|
||||
);
|
||||
|
||||
Future<void> runPackageTest(
|
||||
String packageUnderTest,
|
||||
@@ -300,7 +297,12 @@ Future<void> runPackageTest(
|
||||
assert(validPackages.contains(packageUnderTest));
|
||||
return await inTempDir((tempUri) async {
|
||||
await copyTestProjects(
|
||||
tempUri, logger, packageLocation, sdkRoot, usePubWorkspace);
|
||||
tempUri,
|
||||
logger,
|
||||
packageLocation,
|
||||
sdkRoot,
|
||||
usePubWorkspace,
|
||||
);
|
||||
final packageUri = tempUri.resolve('$packageUnderTest/');
|
||||
return await fun(packageUri);
|
||||
});
|
||||
@@ -332,5 +334,6 @@ Future<run_process.RunProcessResult> runDart({
|
||||
}
|
||||
|
||||
final nativeAssetsExperimentAvailableOnCurrentChannel = ExperimentalFeatures
|
||||
.native_assets.channels
|
||||
.native_assets
|
||||
.channels
|
||||
.contains(Runtime.runtime.channel);
|
||||
|
||||
@@ -42,9 +42,7 @@ final _sdkUri = resolveDartDevUri('.').resolve('../../');
|
||||
|
||||
final _packageRelativePath = Uri.directory('pkg/vm_snapshot_analysis/');
|
||||
|
||||
final _packageDir = Directory.fromUri(
|
||||
_sdkUri.resolveUri(_packageRelativePath),
|
||||
);
|
||||
final _packageDir = Directory.fromUri(_sdkUri.resolveUri(_packageRelativePath));
|
||||
|
||||
/// Standalone, with its own pubspec.
|
||||
final _package2RelativePath = Uri.directory('pkg/dartdev/test/data/dart_app/');
|
||||
@@ -106,7 +104,7 @@ Usage: dart install <package> [version-constraint]
|
||||
-u, --hosted-url A custom pub server URL for the package. Only applies when using a package name for <package>.
|
||||
|
||||
Run "dart help" to see global options.
|
||||
'''
|
||||
''',
|
||||
),
|
||||
(
|
||||
'installed',
|
||||
@@ -121,7 +119,7 @@ Usage: dart installed [arguments]
|
||||
on `PATH` are non-active.
|
||||
|
||||
Run "dart help" to see global options.
|
||||
'''
|
||||
''',
|
||||
),
|
||||
(
|
||||
'uninstall',
|
||||
@@ -135,7 +133,7 @@ Usage: dart uninstall <package>
|
||||
-h, --help Print this usage information.
|
||||
|
||||
Run "dart help" to see global options.
|
||||
'''
|
||||
''',
|
||||
),
|
||||
];
|
||||
for (final (command, helpMessage) in commandsHelpmessages) {
|
||||
@@ -152,30 +150,15 @@ Run "dart help" to see global options.
|
||||
}
|
||||
|
||||
final argumentss = [
|
||||
(
|
||||
null,
|
||||
[_packageForTest],
|
||||
),
|
||||
(
|
||||
null,
|
||||
[_packageForTest, _packageVersion],
|
||||
),
|
||||
(null, [_packageForTest]),
|
||||
(null, [_packageForTest, _packageVersion]),
|
||||
(
|
||||
null,
|
||||
[_packageForTest, _packageVersion, '--hosted-url', 'https://pub.dev/'],
|
||||
),
|
||||
(
|
||||
null,
|
||||
[_packageDir.path],
|
||||
),
|
||||
(
|
||||
_sdkUri,
|
||||
[_packageRelativePath.path],
|
||||
),
|
||||
(
|
||||
_packageDir.uri,
|
||||
['.'],
|
||||
),
|
||||
(null, [_packageDir.path]),
|
||||
(_sdkUri, [_packageRelativePath.path]),
|
||||
(_packageDir.uri, ['.']),
|
||||
];
|
||||
|
||||
for (final (workingDirectory, arguments) in argumentss) {
|
||||
@@ -217,15 +200,9 @@ Run "dart help" to see global options.
|
||||
final installedLines = installedResult.stdout.split('\n');
|
||||
expect(installedLines.where((e) => e.isNotEmpty).length, equals(1));
|
||||
final installedLine = installedLines.first;
|
||||
expect(
|
||||
installedLine,
|
||||
startsWith(_packageForTest),
|
||||
);
|
||||
expect(installedLine, startsWith(_packageForTest));
|
||||
if (arguments.contains(_packageVersion)) {
|
||||
expect(
|
||||
installedLine,
|
||||
equals('$_packageForTest $_packageVersion'),
|
||||
);
|
||||
expect(installedLine, equals('$_packageForTest $_packageVersion'));
|
||||
}
|
||||
if (arguments.contains(_packageRelativePath.toString())) {
|
||||
expect(
|
||||
@@ -247,11 +224,7 @@ Run "dart help" to see global options.
|
||||
|
||||
final argumentssGit = [
|
||||
['git'],
|
||||
[
|
||||
'git',
|
||||
'--git-path',
|
||||
'--git-ref',
|
||||
],
|
||||
['git', '--git-path', '--git-ref'],
|
||||
];
|
||||
|
||||
for (final testArguments in argumentssGit) {
|
||||
@@ -261,12 +234,10 @@ Run "dart help" to see global options.
|
||||
await inTempDir((tempUri) async {
|
||||
final gitUri = tempUri.resolve('app.git/');
|
||||
await Directory.fromUri(gitUri.resolve('bin/')).create(recursive: true);
|
||||
for (final file in [
|
||||
'pubspec.yaml',
|
||||
'bin/dart_app.dart',
|
||||
]) {
|
||||
await File.fromUri(_package2Dir.uri.resolve(file))
|
||||
.copy(gitUri.resolve(file).toFilePath());
|
||||
for (final file in ['pubspec.yaml', 'bin/dart_app.dart']) {
|
||||
await File.fromUri(
|
||||
_package2Dir.uri.resolve(file),
|
||||
).copy(gitUri.resolve(file).toFilePath());
|
||||
}
|
||||
for (final commands in [
|
||||
['init'],
|
||||
@@ -279,31 +250,21 @@ Run "dart help" to see global options.
|
||||
workingDirectory: gitUri.toFilePath(),
|
||||
);
|
||||
if (gitResult.exitCode != 0) {
|
||||
throw ProcessException(
|
||||
'git',
|
||||
commands,
|
||||
gitResult.stderr,
|
||||
);
|
||||
throw ProcessException('git', commands, gitResult.stderr);
|
||||
}
|
||||
}
|
||||
final gitRef = ((await Process.run(
|
||||
'git',
|
||||
['rev-parse', 'HEAD'],
|
||||
workingDirectory: gitUri.toFilePath(),
|
||||
))
|
||||
.stdout as String)
|
||||
.trim();
|
||||
final gitRef =
|
||||
((await Process.run('git', [
|
||||
'rev-parse',
|
||||
'HEAD',
|
||||
], workingDirectory: gitUri.toFilePath())).stdout
|
||||
as String)
|
||||
.trim();
|
||||
final gitPath = './';
|
||||
final arguments = [
|
||||
gitUri.toFilePath(),
|
||||
if (testArguments.contains('--git-path')) ...[
|
||||
'--git-path',
|
||||
gitPath,
|
||||
],
|
||||
if (testArguments.contains('--git-ref')) ...[
|
||||
'--git-ref',
|
||||
gitRef,
|
||||
],
|
||||
if (testArguments.contains('--git-path')) ...['--git-path', gitPath],
|
||||
if (testArguments.contains('--git-ref')) ...['--git-ref', gitRef],
|
||||
];
|
||||
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
@@ -334,14 +295,8 @@ Run "dart help" to see global options.
|
||||
final installedLines = installedResult.stdout.split('\n');
|
||||
expect(installedLines.where((e) => e.isNotEmpty).length, equals(1));
|
||||
final installedLine = installedLines.first;
|
||||
expect(
|
||||
installedLine,
|
||||
startsWith(_gitPackageForTest),
|
||||
);
|
||||
expect(
|
||||
installedLine,
|
||||
contains(' at "${gitRef.substring(0, 8)}"'),
|
||||
);
|
||||
expect(installedLine, startsWith(_gitPackageForTest));
|
||||
expect(installedLine, contains(' at "${gitRef.substring(0, 8)}"'));
|
||||
|
||||
await _runDartdev(
|
||||
fromDartdevSource,
|
||||
@@ -356,9 +311,7 @@ Run "dart help" to see global options.
|
||||
|
||||
skippableTest('dart install ~/.dart/install/bin/ not on PATH', () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
};
|
||||
final environment = {_dartDirectoryEnvKey: tempUri.toFilePath()};
|
||||
|
||||
await inTempDir((tempUri) async {
|
||||
final installResult = await _runDartdev(
|
||||
@@ -393,77 +346,84 @@ Run "dart help" to see global options.
|
||||
});
|
||||
});
|
||||
|
||||
skippableTest('dart install dart_app (with build hooks and code assets)',
|
||||
timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
skippableTest(
|
||||
'dart install dart_app (with build hooks and code assets)',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
await nativeAssetsTest('dart_app', (dartAppUri) async {
|
||||
// Add a second executable.
|
||||
final entryPoint1 =
|
||||
File.fromUri(dartAppUri.resolve('bin/dart_app.dart'));
|
||||
final entryPoint2 =
|
||||
File.fromUri(dartAppUri.resolve('bin/dart_app_copy.dart'));
|
||||
final entryPoint1Contents = await entryPoint1.readAsString();
|
||||
final entryPoint2Contents = entryPoint1Contents.replaceAll('5', '42');
|
||||
await entryPoint2.writeAsString(entryPoint2Contents);
|
||||
final pubspecFile = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
final pubspecOld =
|
||||
pubspecFile.readAsStringSync().replaceAll('\r\n', '\n');
|
||||
final pubspecNew = pubspecOld.replaceAll(
|
||||
'''executables:
|
||||
await nativeAssetsTest('dart_app', (dartAppUri) async {
|
||||
// Add a second executable.
|
||||
final entryPoint1 = File.fromUri(
|
||||
dartAppUri.resolve('bin/dart_app.dart'),
|
||||
);
|
||||
final entryPoint2 = File.fromUri(
|
||||
dartAppUri.resolve('bin/dart_app_copy.dart'),
|
||||
);
|
||||
final entryPoint1Contents = await entryPoint1.readAsString();
|
||||
final entryPoint2Contents = entryPoint1Contents.replaceAll('5', '42');
|
||||
await entryPoint2.writeAsString(entryPoint2Contents);
|
||||
final pubspecFile = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
final pubspecOld = pubspecFile.readAsStringSync().replaceAll(
|
||||
'\r\n',
|
||||
'\n',
|
||||
);
|
||||
final pubspecNew = pubspecOld.replaceAll(
|
||||
'''executables:
|
||||
dart_app:'''
|
||||
.replaceAll('\r\n', '\n'),
|
||||
'''executables:
|
||||
.replaceAll('\r\n', '\n'),
|
||||
'''executables:
|
||||
dart_app:
|
||||
dart_app_copy:'''
|
||||
.replaceAll('\r\n', '\n'),
|
||||
);
|
||||
expect(pubspecNew, isNot(equals(pubspecOld)));
|
||||
pubspecFile.writeAsStringSync(pubspecNew);
|
||||
|
||||
final installResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[dartAppUri.toFilePath()],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
|
||||
expect(installResult.stdout, contains('Running build hooks'));
|
||||
expect(installResult.stdout, contains('Running link hooks'));
|
||||
|
||||
for (final (tool, someInt) in [
|
||||
('dart_app', 5),
|
||||
('dart_app_copy', 42)
|
||||
]) {
|
||||
final toolResult = await runProcess(
|
||||
// Note this has `runInShell: true` under it to ensure PATHEXT is used on
|
||||
// Windows so that invoking an executable without extension works.
|
||||
executable: Uri.file(tool),
|
||||
// Run in some unrelated directory ensuring PATH is picked up.
|
||||
workingDirectory: Directory.systemTemp.uri,
|
||||
logger: logger,
|
||||
environment: environment,
|
||||
.replaceAll('\r\n', '\n'),
|
||||
);
|
||||
expect(
|
||||
toolResult.stdout,
|
||||
stringContainsInOrder([
|
||||
'add($someInt, 6) = ${someInt + 6}',
|
||||
'subtract($someInt, 6) = ${someInt - 6}',
|
||||
]),
|
||||
expect(pubspecNew, isNot(equals(pubspecOld)));
|
||||
pubspecFile.writeAsStringSync(pubspecNew);
|
||||
|
||||
final installResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[dartAppUri.toFilePath()],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
expect(toolResult.exitCode, 0);
|
||||
}
|
||||
|
||||
expect(installResult.stdout, contains('Running build hooks'));
|
||||
expect(installResult.stdout, contains('Running link hooks'));
|
||||
|
||||
for (final (tool, someInt) in [
|
||||
('dart_app', 5),
|
||||
('dart_app_copy', 42),
|
||||
]) {
|
||||
final toolResult = await runProcess(
|
||||
// Note this has `runInShell: true` under it to ensure PATHEXT is used on
|
||||
// Windows so that invoking an executable without extension works.
|
||||
executable: Uri.file(tool),
|
||||
// Run in some unrelated directory ensuring PATH is picked up.
|
||||
workingDirectory: Directory.systemTemp.uri,
|
||||
logger: logger,
|
||||
environment: environment,
|
||||
);
|
||||
expect(
|
||||
toolResult.stdout,
|
||||
stringContainsInOrder([
|
||||
'add($someInt, 6) = ${someInt + 6}',
|
||||
'subtract($someInt, 6) = ${someInt - 6}',
|
||||
]),
|
||||
);
|
||||
expect(toolResult.exitCode, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
skippableTest('dart install --overwrite', timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
@@ -495,8 +455,10 @@ Run "dart help" to see global options.
|
||||
|
||||
final pubspecFile = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
final pubspecContents = await pubspecFile.readAsString();
|
||||
final pubspecContentsNew =
|
||||
pubspecContents.replaceFirst('dart_app', 'a_different_name');
|
||||
final pubspecContentsNew = pubspecContents.replaceFirst(
|
||||
'dart_app',
|
||||
'a_different_name',
|
||||
);
|
||||
await pubspecFile.writeAsString(pubspecContentsNew);
|
||||
|
||||
// Trying to install an executable with the same name from a different
|
||||
@@ -535,24 +497,17 @@ Run "dart help" to see global options.
|
||||
.toList();
|
||||
if (all) {
|
||||
expect(installedLines, hasLength(2));
|
||||
expect(
|
||||
installedLines,
|
||||
contains(startsWith('dart_app')),
|
||||
);
|
||||
expect(installedLines, contains(startsWith('dart_app')));
|
||||
} else {
|
||||
expect(installedLines, hasLength(1));
|
||||
expect(
|
||||
installedLines,
|
||||
isNot(contains(startsWith('dart_app'))),
|
||||
);
|
||||
expect(installedLines, isNot(contains(startsWith('dart_app'))));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
skippableTest('dart install check exit codes', timeout: longTimeout,
|
||||
() async {
|
||||
skippableTest('dart install check exit codes', timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
|
||||
@@ -566,15 +521,17 @@ Run "dart help" to see global options.
|
||||
final dartAppUri = tempUri.resolve('$appName/');
|
||||
final pubspec = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
await pubspec.create(recursive: true);
|
||||
await pubspec.writeAsString(jsonEncode(PubspecYamlFileSyntax(
|
||||
name: appName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
await pubspec.writeAsString(
|
||||
jsonEncode(
|
||||
PubspecYamlFileSyntax(
|
||||
name: appName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
),
|
||||
executables: {appName: appName},
|
||||
).json,
|
||||
),
|
||||
executables: {
|
||||
appName: appName,
|
||||
},
|
||||
).json));
|
||||
);
|
||||
final mainFile = File.fromUri(dartAppUri.resolve('bin/$appName.dart'));
|
||||
await mainFile.create(recursive: true);
|
||||
mainFile.writeAsString('''
|
||||
@@ -608,30 +565,35 @@ void main(List<String> args) {
|
||||
});
|
||||
});
|
||||
|
||||
skippableTest('dart install hooks user-defines and failures',
|
||||
timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
skippableTest(
|
||||
'dart install hooks user-defines and failures',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
const packageName = 'test_app';
|
||||
final dartAppUri = tempUri.resolve('$packageName/');
|
||||
final pubspec = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
await pubspec.create(recursive: true);
|
||||
final mainFile =
|
||||
File.fromUri(dartAppUri.resolve('bin/$packageName.dart'));
|
||||
await mainFile.create(recursive: true);
|
||||
mainFile.writeAsString('''
|
||||
const packageName = 'test_app';
|
||||
final dartAppUri = tempUri.resolve('$packageName/');
|
||||
final pubspec = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
await pubspec.create(recursive: true);
|
||||
final mainFile = File.fromUri(
|
||||
dartAppUri.resolve('bin/$packageName.dart'),
|
||||
);
|
||||
await mainFile.create(recursive: true);
|
||||
mainFile.writeAsString('''
|
||||
void main(List<String> args) { }
|
||||
''');
|
||||
final buildHookFile = File.fromUri(dartAppUri.resolve('hook/build.dart'));
|
||||
await buildHookFile.create(recursive: true);
|
||||
buildHookFile.writeAsString('''
|
||||
final buildHookFile = File.fromUri(
|
||||
dartAppUri.resolve('hook/build.dart'),
|
||||
);
|
||||
await buildHookFile.create(recursive: true);
|
||||
buildHookFile.writeAsString('''
|
||||
import 'package:hooks/hooks.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
@@ -643,117 +605,121 @@ void main(List<String> args) async {
|
||||
});
|
||||
}
|
||||
''');
|
||||
for (final addUserDefine in [true, false]) {
|
||||
await pubspec.writeAsString(jsonEncode(PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
),
|
||||
executables: {
|
||||
packageName: packageName,
|
||||
},
|
||||
dependencies: {
|
||||
'hooks': PathDependencySourceSyntax(
|
||||
path$: sdkRootUri
|
||||
.resolve('third_party/pkg/native/pkgs/hooks/')
|
||||
.toFilePath(),
|
||||
for (final addUserDefine in [true, false]) {
|
||||
await pubspec.writeAsString(
|
||||
jsonEncode(
|
||||
PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
),
|
||||
executables: {packageName: packageName},
|
||||
dependencies: {
|
||||
'hooks': PathDependencySourceSyntax(
|
||||
path$: sdkRootUri
|
||||
.resolve('third_party/pkg/native/pkgs/hooks/')
|
||||
.toFilePath(),
|
||||
),
|
||||
},
|
||||
hooks: HooksSyntax(
|
||||
userDefines: {
|
||||
packageName: {
|
||||
if (addUserDefine) 'my_user_define': 'a_value,',
|
||||
},
|
||||
},
|
||||
),
|
||||
).json,
|
||||
),
|
||||
},
|
||||
hooks: HooksSyntax(
|
||||
userDefines: {
|
||||
packageName: {
|
||||
if (addUserDefine) 'my_user_define': 'a_value,',
|
||||
},
|
||||
},
|
||||
),
|
||||
).json));
|
||||
);
|
||||
final installResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[dartAppUri.toFilePath()],
|
||||
null,
|
||||
environment,
|
||||
expectedExitCode: addUserDefine ? 0 : errorExitCode,
|
||||
);
|
||||
if (addUserDefine) {
|
||||
expect(installResult.exitCode, equals(0));
|
||||
expect(installResult.stderr, isEmpty);
|
||||
} else {
|
||||
// Check that build hook failures are surfaced and that error messages
|
||||
// are visible.
|
||||
expect(installResult.exitCode, equals(errorExitCode));
|
||||
expect(installResult.stderr, contains('Expected a user define'));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
skippableTest(
|
||||
'dart install uninstalls old versions',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
// Install two versions.
|
||||
await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
['.'],
|
||||
_packageDir.uri,
|
||||
environment,
|
||||
);
|
||||
final installResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[dartAppUri.toFilePath()],
|
||||
[_packageForTest, _packageVersion],
|
||||
null,
|
||||
environment,
|
||||
expectedExitCode: addUserDefine ? 0 : errorExitCode,
|
||||
);
|
||||
if (addUserDefine) {
|
||||
expect(installResult.exitCode, equals(0));
|
||||
expect(installResult.stderr, isEmpty);
|
||||
} else {
|
||||
// Check that build hook failures are surfaced and that error messages
|
||||
// are visible.
|
||||
expect(installResult.exitCode, equals(errorExitCode));
|
||||
expect(installResult.stderr, contains('Expected a user define'));
|
||||
expect(
|
||||
installResult.stdout,
|
||||
stringContainsInOrder(['Uninstalling ', _packageForTest]),
|
||||
);
|
||||
|
||||
// `--all` should also report the non-active versions.
|
||||
Future<List<String>> runInstalled() async {
|
||||
final installedResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'installed',
|
||||
['--all'],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
final installedLines = installedResult.stdout
|
||||
.split('\n')
|
||||
.where((e) => e.isNotEmpty)
|
||||
.toList();
|
||||
return installedLines;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
skippableTest('dart install uninstalls old versions', timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final binDir = Directory.fromUri(tempUri.resolve('install/bin'));
|
||||
expect(await runInstalled(), hasLength(1));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
// Install two versions.
|
||||
await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
['.'],
|
||||
_packageDir.uri,
|
||||
environment,
|
||||
);
|
||||
final installResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[_packageForTest, _packageVersion],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
expect(
|
||||
installResult.stdout,
|
||||
stringContainsInOrder(['Uninstalling ', _packageForTest]),
|
||||
);
|
||||
|
||||
// `--all` should also report the non-active versions.
|
||||
Future<List<String>> runInstalled() async {
|
||||
final installedResult = await _runDartdev(
|
||||
// `uninstall` uninstalls all versions.
|
||||
await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'installed',
|
||||
['--all'],
|
||||
'uninstall',
|
||||
[_packageForTest],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
final installedLines = installedResult.stdout
|
||||
.split('\n')
|
||||
.where((e) => e.isNotEmpty)
|
||||
.toList();
|
||||
return installedLines;
|
||||
}
|
||||
|
||||
expect(await runInstalled(), hasLength(1));
|
||||
|
||||
// `uninstall` uninstalls all versions.
|
||||
await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'uninstall',
|
||||
[_packageForTest],
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
expect(await runInstalled(), hasLength(0));
|
||||
});
|
||||
});
|
||||
expect(await runInstalled(), hasLength(0));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
skippableTest('dart uninstall', timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: tempUri.toFilePath(),
|
||||
};
|
||||
final environment = {_dartDirectoryEnvKey: tempUri.toFilePath()};
|
||||
|
||||
// `uninstall` should have a non-zero exit if nothing was uninstalled.
|
||||
await _runDartdev(
|
||||
@@ -781,17 +747,20 @@ void main(List<String> args) async {
|
||||
final dartAppUri = tempUri.resolve('$packageName/');
|
||||
final pubspec = File.fromUri(dartAppUri.resolve('pubspec.yaml'));
|
||||
await pubspec.create(recursive: true);
|
||||
await pubspec.writeAsString(jsonEncode(PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
await pubspec.writeAsString(
|
||||
jsonEncode(
|
||||
PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
),
|
||||
executables: {packageName: packageName},
|
||||
).json,
|
||||
),
|
||||
executables: {
|
||||
packageName: packageName,
|
||||
},
|
||||
).json));
|
||||
final mainFile =
|
||||
File.fromUri(dartAppUri.resolve('bin/$packageName.dart'));
|
||||
);
|
||||
final mainFile = File.fromUri(
|
||||
dartAppUri.resolve('bin/$packageName.dart'),
|
||||
);
|
||||
await mainFile.create(recursive: true);
|
||||
mainFile.writeAsString('''
|
||||
void main(List<String> args) async {
|
||||
@@ -799,9 +768,14 @@ void main(List<String> args) async {
|
||||
}
|
||||
''');
|
||||
Future<RunProcessResult> doInstall(int expectedExitCode) async {
|
||||
return await _runDartdev(fromDartdevSource, 'install',
|
||||
[dartAppUri.toFilePath()], null, environment,
|
||||
expectedExitCode: expectedExitCode);
|
||||
return await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'install',
|
||||
[dartAppUri.toFilePath()],
|
||||
null,
|
||||
environment,
|
||||
expectedExitCode: expectedExitCode,
|
||||
);
|
||||
}
|
||||
|
||||
await doInstall(0);
|
||||
|
||||
@@ -131,11 +131,7 @@ void main() async {
|
||||
|
||||
final argumentssGit = [
|
||||
['git'],
|
||||
[
|
||||
'git',
|
||||
'--git-path',
|
||||
'--git-ref',
|
||||
],
|
||||
['git', '--git-path', '--git-ref'],
|
||||
];
|
||||
|
||||
for (final testArguments in argumentssGit) {
|
||||
@@ -147,19 +143,13 @@ void main() async {
|
||||
final gitPath = './';
|
||||
final arguments = [
|
||||
'--enable-experiment-remote-run',
|
||||
if (testArguments.contains('--git-path')) ...[
|
||||
'--git-path',
|
||||
gitPath,
|
||||
],
|
||||
if (testArguments.contains('--git-ref')) ...[
|
||||
'--git-ref',
|
||||
gitRef,
|
||||
],
|
||||
if (testArguments.contains('--git-path')) ...['--git-path', gitPath],
|
||||
if (testArguments.contains('--git-ref')) ...['--git-ref', gitRef],
|
||||
'${gitUri.toFilePath()}:$_gitPackageForTest',
|
||||
// Make sure to pass arguments that influence stdout.
|
||||
'Alice',
|
||||
'and',
|
||||
'Bob'
|
||||
'Bob',
|
||||
];
|
||||
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
@@ -182,9 +172,7 @@ void main() async {
|
||||
|
||||
expect(
|
||||
runResult.stdout,
|
||||
stringContainsInOrder([
|
||||
'Hello Alice and Bob',
|
||||
]),
|
||||
stringContainsInOrder(['Hello Alice and Bob']),
|
||||
);
|
||||
expect(runResult.exitCode, 0);
|
||||
});
|
||||
@@ -195,7 +183,7 @@ void main() async {
|
||||
(
|
||||
[
|
||||
'--enable-experiment-remote-run',
|
||||
'https://pub.dev/this_package_does_not_exist_12345'
|
||||
'https://pub.dev/this_package_does_not_exist_12345',
|
||||
],
|
||||
'could not find package this_package_does_not_exist_12345 at',
|
||||
errorExitCode,
|
||||
@@ -205,7 +193,7 @@ void main() async {
|
||||
'--enable-experiment-remote-run',
|
||||
'--git-path',
|
||||
'foo/',
|
||||
'https://pub.dev/vm_snapshot_analysis'
|
||||
'https://pub.dev/vm_snapshot_analysis',
|
||||
],
|
||||
'git-path',
|
||||
usageExitCode,
|
||||
@@ -214,7 +202,7 @@ void main() async {
|
||||
[
|
||||
'--enable-experiment-remote-run',
|
||||
'--enable-asserts',
|
||||
'https://pub.dev/vm_snapshot_analysis'
|
||||
'https://pub.dev/vm_snapshot_analysis',
|
||||
],
|
||||
'enable-asserts',
|
||||
usageExitCode,
|
||||
@@ -226,8 +214,7 @@ void main() async {
|
||||
),
|
||||
];
|
||||
for (final (errorArguments, error, exitCode) in errorArgumentss) {
|
||||
test('dart run ${errorArguments.join(' ')}', timeout: longTimeout,
|
||||
() async {
|
||||
test('dart run ${errorArguments.join(' ')}', timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
await Directory.fromUri(dartDataHome).create();
|
||||
@@ -247,71 +234,76 @@ void main() async {
|
||||
environment,
|
||||
expectedExitCode: exitCode,
|
||||
);
|
||||
expect(
|
||||
runResult.stderr,
|
||||
contains(error),
|
||||
);
|
||||
expect(runResult.stderr, contains(error));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test('dart run error from git with build hook failure', timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
await Directory.fromUri(dartDataHome).create();
|
||||
final binDir = Directory.fromUri(dartDataHome.resolve('install/bin'));
|
||||
test(
|
||||
'dart run error from git with build hook failure',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
await Directory.fromUri(dartDataHome).create();
|
||||
final binDir = Directory.fromUri(dartDataHome.resolve('install/bin'));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: dartDataHome.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: dartDataHome.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
const packageName = 'test_app_with_failing_hook';
|
||||
final (gitUri, _) = await _setupGitRepo(
|
||||
tempUri,
|
||||
repoName: '$packageName.git',
|
||||
files: {
|
||||
'pubspec.yaml': jsonEncode(PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
const packageName = 'test_app_with_failing_hook';
|
||||
final (gitUri, _) = await _setupGitRepo(
|
||||
tempUri,
|
||||
repoName: '$packageName.git',
|
||||
files: {
|
||||
'pubspec.yaml': jsonEncode(
|
||||
PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^${Platform.version.split(' ').first}',
|
||||
),
|
||||
executables: {packageName: packageName},
|
||||
).json,
|
||||
),
|
||||
executables: {
|
||||
packageName: packageName,
|
||||
},
|
||||
).json),
|
||||
'bin/$packageName.dart': '''
|
||||
'bin/$packageName.dart': '''
|
||||
void main(List<String> args) {
|
||||
print('This should not be printed.');
|
||||
}
|
||||
''',
|
||||
'hook/build.dart': '''
|
||||
'hook/build.dart': '''
|
||||
void main(List<String> args) async {
|
||||
throw Exception('This build hook is designed to fail.');
|
||||
}
|
||||
''',
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
final runResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'run',
|
||||
[
|
||||
'--enable-experiment-remote-run',
|
||||
'${gitUri.toFilePath()}:$packageName'
|
||||
],
|
||||
null,
|
||||
environment,
|
||||
expectedExitCode: errorExitCode,
|
||||
);
|
||||
final runResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'run',
|
||||
[
|
||||
'--enable-experiment-remote-run',
|
||||
'${gitUri.toFilePath()}:$packageName',
|
||||
],
|
||||
null,
|
||||
environment,
|
||||
expectedExitCode: errorExitCode,
|
||||
);
|
||||
|
||||
expect(
|
||||
runResult.stderr, contains('This build hook is designed to fail.'));
|
||||
expect(runResult.stdout, isNot(contains('This should not be printed.')));
|
||||
});
|
||||
});
|
||||
expect(
|
||||
runResult.stderr,
|
||||
contains('This build hook is designed to fail.'),
|
||||
);
|
||||
expect(
|
||||
runResult.stdout,
|
||||
isNot(contains('This should not be printed.')),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test('dart run caches git package', timeout: longTimeout, () async {
|
||||
await inTempDir((tempUri) async {
|
||||
@@ -368,60 +360,63 @@ void main(List<String> args) async {
|
||||
|
||||
for (final verbosityError in [true, false]) {
|
||||
final testName = verbosityError ? ' --verbosity=error' : '';
|
||||
test('dart run from git with build hook$testName', timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
const packageName = 'test_app_with_hook';
|
||||
final (gitUri, gitRef) = await _setupGitRepoWithHook(
|
||||
tempUri,
|
||||
packageName: packageName,
|
||||
);
|
||||
test(
|
||||
'dart run from git with build hook$testName',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await inTempDir((tempUri) async {
|
||||
const packageName = 'test_app_with_hook';
|
||||
final (gitUri, gitRef) = await _setupGitRepoWithHook(
|
||||
tempUri,
|
||||
packageName: packageName,
|
||||
);
|
||||
|
||||
final arguments = [
|
||||
'--enable-experiment-remote-run',
|
||||
if (verbosityError) '--verbosity=error',
|
||||
'--git-ref',
|
||||
gitRef,
|
||||
'${gitUri.toFilePath()}:$packageName',
|
||||
'ignored',
|
||||
'arguments',
|
||||
];
|
||||
final arguments = [
|
||||
'--enable-experiment-remote-run',
|
||||
if (verbosityError) '--verbosity=error',
|
||||
'--git-ref',
|
||||
gitRef,
|
||||
'${gitUri.toFilePath()}:$packageName',
|
||||
'ignored',
|
||||
'arguments',
|
||||
];
|
||||
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
await Directory.fromUri(dartDataHome).create();
|
||||
final binDir = Directory.fromUri(dartDataHome.resolve('install/bin'));
|
||||
final dartDataHome = tempUri.resolve('dart_home/');
|
||||
await Directory.fromUri(dartDataHome).create();
|
||||
final binDir = Directory.fromUri(dartDataHome.resolve('install/bin'));
|
||||
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: dartDataHome.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
final environment = {
|
||||
_dartDirectoryEnvKey: dartDataHome.toFilePath(),
|
||||
'PATH':
|
||||
'${binDir.path}$_pathEnvVarSeparator${Platform.environment['PATH']!}',
|
||||
};
|
||||
|
||||
print(environment);
|
||||
print('dart run ${arguments.join(' ')}');
|
||||
final runResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'run',
|
||||
arguments,
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
print(environment);
|
||||
print('dart run ${arguments.join(' ')}');
|
||||
final runResult = await _runDartdev(
|
||||
fromDartdevSource,
|
||||
'run',
|
||||
arguments,
|
||||
null,
|
||||
environment,
|
||||
);
|
||||
|
||||
expect(runResult.stdout, contains('Hello World'));
|
||||
expect(runResult.exitCode, 0);
|
||||
if (verbosityError) {
|
||||
expect(runResult.stdout, isNot(contains('Running build hooks')));
|
||||
expect(runResult.stdout, isNot(contains('Running link hooks')));
|
||||
expect(runResult.stdout, isNot(contains('Generated: ')));
|
||||
// Should have no other output then the program.
|
||||
expect(runResult.stdout.trim(), equals('Hello World'));
|
||||
} else {
|
||||
expect(runResult.stdout, contains('Running build hooks'));
|
||||
expect(runResult.stdout, contains('Running link hooks'));
|
||||
expect(runResult.stdout, contains('Generated: '));
|
||||
}
|
||||
});
|
||||
});
|
||||
expect(runResult.stdout, contains('Hello World'));
|
||||
expect(runResult.exitCode, 0);
|
||||
if (verbosityError) {
|
||||
expect(runResult.stdout, isNot(contains('Running build hooks')));
|
||||
expect(runResult.stdout, isNot(contains('Running link hooks')));
|
||||
expect(runResult.stdout, isNot(contains('Generated: ')));
|
||||
// Should have no other output then the program.
|
||||
expect(runResult.stdout.trim(), equals('Hello World'));
|
||||
} else {
|
||||
expect(runResult.stdout, contains('Running build hooks'));
|
||||
expect(runResult.stdout, contains('Running link hooks'));
|
||||
expect(runResult.stdout, contains('Generated: '));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,20 +443,16 @@ Future<(Uri gitUri, String gitRef)> _setupGitRepo(
|
||||
workingDirectory: gitUri.toFilePath(),
|
||||
);
|
||||
if (gitResult.exitCode != 0) {
|
||||
throw ProcessException(
|
||||
'git',
|
||||
commands,
|
||||
gitResult.stderr,
|
||||
);
|
||||
throw ProcessException('git', commands, gitResult.stderr);
|
||||
}
|
||||
}
|
||||
final gitRef = ((await Process.run(
|
||||
'git',
|
||||
['rev-parse', 'HEAD'],
|
||||
workingDirectory: gitUri.toFilePath(),
|
||||
))
|
||||
.stdout as String)
|
||||
.trim();
|
||||
final gitRef =
|
||||
((await Process.run('git', [
|
||||
'rev-parse',
|
||||
'HEAD',
|
||||
], workingDirectory: gitUri.toFilePath())).stdout
|
||||
as String)
|
||||
.trim();
|
||||
return (gitUri, gitRef);
|
||||
}
|
||||
|
||||
@@ -473,22 +464,18 @@ Future<(Uri gitUri, String gitRef)> _setupGitRepoWithHook(
|
||||
tempUri,
|
||||
repoName: '$packageName.git',
|
||||
files: {
|
||||
'pubspec.yaml': jsonEncode(PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(
|
||||
sdk: '^3.8.0',
|
||||
),
|
||||
executables: {
|
||||
packageName: null,
|
||||
},
|
||||
dependencies: {
|
||||
// Git dependencies can't have path dependencies outside the git repo
|
||||
// so use a published dependency.
|
||||
'hooks': HostedDependencySourceSyntax(
|
||||
version: '^1.0.0',
|
||||
),
|
||||
},
|
||||
).json),
|
||||
'pubspec.yaml': jsonEncode(
|
||||
PubspecYamlFileSyntax(
|
||||
name: packageName,
|
||||
environment: EnvironmentSyntax(sdk: '^3.8.0'),
|
||||
executables: {packageName: null},
|
||||
dependencies: {
|
||||
// Git dependencies can't have path dependencies outside the git repo
|
||||
// so use a published dependency.
|
||||
'hooks': HostedDependencySourceSyntax(version: '^1.0.0'),
|
||||
},
|
||||
).json,
|
||||
),
|
||||
'bin/$packageName.dart': '''
|
||||
void main(List<String> args) {
|
||||
print('Hello World');
|
||||
@@ -520,12 +507,12 @@ Future<(Uri gitUri, String gitRef)> _setupSimpleGitRepo(Uri tempUri) async {
|
||||
return await _setupGitRepo(
|
||||
tempUri,
|
||||
files: {
|
||||
'pubspec.yaml':
|
||||
await File.fromUri(_package2Dir.uri.resolve('pubspec.yaml'))
|
||||
.readAsString(),
|
||||
'bin/dart_app.dart':
|
||||
await File.fromUri(_package2Dir.uri.resolve('bin/dart_app.dart'))
|
||||
.readAsString(),
|
||||
'pubspec.yaml': await File.fromUri(
|
||||
_package2Dir.uri.resolve('pubspec.yaml'),
|
||||
).readAsString(),
|
||||
'bin/dart_app.dart': await File.fromUri(
|
||||
_package2Dir.uri.resolve('bin/dart_app.dart'),
|
||||
).readAsString(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,19 +14,16 @@ void main([List<String> args = const []]) async {
|
||||
test('dart run', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('dart_app', (dartAppUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
],
|
||||
arguments: ['run'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
expectExitCodeZero: false,
|
||||
);
|
||||
expect(result.exitCode, 254);
|
||||
expect(
|
||||
result.stderr,
|
||||
stringContainsInOrder(
|
||||
['Unavailable experiment: native-assets'],
|
||||
));
|
||||
result.stderr,
|
||||
stringContainsInOrder(['Unavailable experiment: native-assets']),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,11 +44,7 @@ void main([List<String> args = const []]) async {
|
||||
test('dart run$testModifier', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('dart_app', (dartAppUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
if (residentCompiler) '-r',
|
||||
if (verbose) '-v',
|
||||
],
|
||||
arguments: ['run', if (residentCompiler) '-r', if (verbose) '-v'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
);
|
||||
@@ -70,10 +63,7 @@ void main([List<String> args = const []]) async {
|
||||
test('dart run --verbosity=error', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('dart_app', (dartAppUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'--verbosity=error',
|
||||
],
|
||||
arguments: ['run', '--verbosity=error'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
);
|
||||
@@ -85,58 +75,41 @@ void main([List<String> args = const []]) async {
|
||||
test('dart run test/xxx_test.dart', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('native_add', (packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'test/native_add_test.dart',
|
||||
],
|
||||
arguments: ['run', 'test/native_add_test.dart'],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrder(
|
||||
[
|
||||
'native add test',
|
||||
'All tests passed!',
|
||||
],
|
||||
),
|
||||
stringContainsInOrder(['native add test', 'All tests passed!']),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
for (final subcommand in ['test', 'test/my_test.dart']) {
|
||||
test('dart run $subcommand (dev_dependency_with_hook)',
|
||||
timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('dev_dependency_with_hook', (packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
subcommand,
|
||||
],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrder(
|
||||
[
|
||||
'native add test',
|
||||
'All tests passed!',
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
test(
|
||||
'dart run $subcommand (dev_dependency_with_hook)',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await nativeAssetsTest('dev_dependency_with_hook', (packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: ['run', subcommand],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
expect(
|
||||
result.stdout,
|
||||
stringContainsInOrder(['native add test', 'All tests passed!']),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test('dart run some_dev_dep', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('native_add', (packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'-v',
|
||||
'some_dev_dep',
|
||||
],
|
||||
arguments: ['run', '-v', 'some_dev_dep'],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
@@ -156,35 +129,35 @@ void main([List<String> args = const []]) async {
|
||||
});
|
||||
});
|
||||
|
||||
test('dart link assets doesnt have treeshaken asset', timeout: longTimeout,
|
||||
() async {
|
||||
await nativeAssetsTest('drop_dylib_link', (dartAppUri) async {
|
||||
try {
|
||||
await runDart(
|
||||
arguments: ['run', 'bin/drop_dylib_link.dart', 'multiply'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
expectExitCodeZero: false,
|
||||
);
|
||||
} catch (e) {
|
||||
expect(e, e is ArgumentError);
|
||||
expect(
|
||||
(e as ArgumentError).message.toString(),
|
||||
contains('''
|
||||
test(
|
||||
'dart link assets doesnt have treeshaken asset',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await nativeAssetsTest('drop_dylib_link', (dartAppUri) async {
|
||||
try {
|
||||
await runDart(
|
||||
arguments: ['run', 'bin/drop_dylib_link.dart', 'multiply'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
expectExitCodeZero: false,
|
||||
);
|
||||
} catch (e) {
|
||||
expect(e, e is ArgumentError);
|
||||
expect(
|
||||
(e as ArgumentError).message.toString(),
|
||||
contains('''
|
||||
Couldn't resolve native function 'multiply' in 'package:drop_dylib_link/dylib_multiply' : No asset with id 'package:drop_dylib_link/dylib_multiply' found. Available native assets: package:drop_dylib_link/dylib_add.
|
||||
'''),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test('dart add asset in linking', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('add_asset_link', (dartAppUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'bin/add_asset_link.dart',
|
||||
],
|
||||
arguments: ['run', 'bin/add_asset_link.dart'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
expectExitCodeZero: false,
|
||||
@@ -199,10 +172,7 @@ Couldn't resolve native function 'multiply' in 'package:drop_dylib_link/dylib_mu
|
||||
test('dart run with native dynamic linking', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('native_dynamic_linking', (packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'bin/native_dynamic_linking.dart',
|
||||
],
|
||||
arguments: ['run', 'bin/native_dynamic_linking.dart'],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
@@ -211,24 +181,18 @@ Couldn't resolve native function 'multiply' in 'package:drop_dylib_link/dylib_mu
|
||||
});
|
||||
|
||||
for (final usePubWorkspace in [true, false]) {
|
||||
test(
|
||||
'dart run with user defines',
|
||||
timeout: longTimeout,
|
||||
() async {
|
||||
await nativeAssetsTest('user_defines', usePubWorkspace: usePubWorkspace,
|
||||
(packageUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'bin/user_defines.dart',
|
||||
],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
expect(result.stdout, contains('Hello world!'));
|
||||
});
|
||||
},
|
||||
);
|
||||
test('dart run with user defines', timeout: longTimeout, () async {
|
||||
await nativeAssetsTest('user_defines', usePubWorkspace: usePubWorkspace, (
|
||||
packageUri,
|
||||
) async {
|
||||
final result = await runDart(
|
||||
arguments: ['run', 'bin/user_defines.dart'],
|
||||
workingDirectory: packageUri,
|
||||
logger: logger,
|
||||
);
|
||||
expect(result.stdout, contains('Hello world!'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Regression test for Bug: https://github.com/dart-lang/native/issues/2921.
|
||||
@@ -240,10 +204,7 @@ Couldn't resolve native function 'multiply' in 'package:drop_dylib_link/dylib_mu
|
||||
() async {
|
||||
await nativeAssetsTest('recursive_invocation', (dartAppUri) async {
|
||||
final result = await runDart(
|
||||
arguments: [
|
||||
'run',
|
||||
'bin/subprocess.dart',
|
||||
],
|
||||
arguments: ['run', 'bin/subprocess.dart'],
|
||||
workingDirectory: dartAppUri,
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
@@ -24,15 +24,17 @@ void main() {
|
||||
expect(argsResult.exitCode, 254);
|
||||
});
|
||||
|
||||
test('Providing --snapshot VM option with invalid script fails gracefully',
|
||||
() async {
|
||||
// Regression test for https://github.com/dart-lang/sdk/issues/43785
|
||||
final result = await p.run(['--snapshot=abc', 'foo.dart']);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.stderr, contains("Error when reading 'foo.dart':"));
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.exitCode, 254);
|
||||
});
|
||||
test(
|
||||
'Providing --snapshot VM option with invalid script fails gracefully',
|
||||
() async {
|
||||
// Regression test for https://github.com/dart-lang/sdk/issues/43785
|
||||
final result = await p.run(['--snapshot=abc', 'foo.dart']);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.stderr, contains("Error when reading 'foo.dart':"));
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(result.exitCode, 254);
|
||||
},
|
||||
);
|
||||
|
||||
test('Will not try to run file named the same as command', () async {
|
||||
p.file('pub', 'main() => print("All your base are belong to us")');
|
||||
|
||||
@@ -26,23 +26,25 @@ Future<void> copyPath(String from, String to) async {
|
||||
}
|
||||
|
||||
Future<void> main() async {
|
||||
test('Regression test for https://github.com/dart-lang/sdk/issues/46364',
|
||||
() async {
|
||||
ensureRunFromSdkBinDart();
|
||||
test(
|
||||
'Regression test for https://github.com/dart-lang/sdk/issues/46364',
|
||||
() async {
|
||||
ensureRunFromSdkBinDart();
|
||||
|
||||
final exePath = Platform.resolvedExecutable;
|
||||
final sdkDir = p.dirname(p.dirname(exePath));
|
||||
// Try to run the VM located on a path with % encoded characters. The VM
|
||||
// should not try and resolve the path as a URI for SDK artifacts (e.g.,
|
||||
// dartdev.dart.snapshot).
|
||||
final d = Directory.systemTemp.createTempSync('dart_symlink%3A');
|
||||
try {
|
||||
await copyPath(sdkDir, d.path);
|
||||
final path = '${d.path}/bin/dart';
|
||||
final result = await Process.run(path, ['help']);
|
||||
Expect.equals(result.exitCode, 0);
|
||||
} finally {
|
||||
await d.delete(recursive: true);
|
||||
}
|
||||
});
|
||||
final exePath = Platform.resolvedExecutable;
|
||||
final sdkDir = p.dirname(p.dirname(exePath));
|
||||
// Try to run the VM located on a path with % encoded characters. The VM
|
||||
// should not try and resolve the path as a URI for SDK artifacts (e.g.,
|
||||
// dartdev.dart.snapshot).
|
||||
final d = Directory.systemTemp.createTempSync('dart_symlink%3A');
|
||||
try {
|
||||
await copyPath(sdkDir, d.path);
|
||||
final path = '${d.path}/bin/dart';
|
||||
final result = await Process.run(path, ['help']);
|
||||
Expect.equals(result.exitCode, 0);
|
||||
} finally {
|
||||
await d.delete(recursive: true);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,18 +13,17 @@ import 'package:test/test.dart';
|
||||
// See https://github.com/dart-lang/sdk/issues/56592 for details.
|
||||
|
||||
Future<void> main() async {
|
||||
test('Regression test for https://github.com/dart-lang/sdk/issues/56592',
|
||||
() async {
|
||||
final result = await Process.run(
|
||||
Platform.resolvedExecutable,
|
||||
[
|
||||
test(
|
||||
'Regression test for https://github.com/dart-lang/sdk/issues/56592',
|
||||
() async {
|
||||
final result = await Process.run(Platform.resolvedExecutable, [
|
||||
'test',
|
||||
'--disable-dart-dev',
|
||||
],
|
||||
);
|
||||
Expect.contains(
|
||||
'Attempted to use --disable-dart-dev with a Dart CLI command.',
|
||||
result.stderr,
|
||||
);
|
||||
});
|
||||
]);
|
||||
Expect.contains(
|
||||
'Attempted to use --disable-dart-dev with a Dart CLI command.',
|
||||
result.stderr,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@ void main() {
|
||||
|
||||
group('ResidentCompilerInfo.fromFile', () {
|
||||
test('correctly parses resident compiler info files', () async {
|
||||
final testInfoFile = File(path.join(
|
||||
testProject.dirPath,
|
||||
'resident_compiler_info.txt',
|
||||
));
|
||||
final testInfoFile = File(
|
||||
path.join(testProject.dirPath, 'resident_compiler_info.txt'),
|
||||
);
|
||||
testInfoFile.writeAsStringSync('address:127.0.0.1 port:45678');
|
||||
|
||||
final testInfo = ResidentCompilerInfo.fromFile(testInfoFile);
|
||||
@@ -36,120 +35,179 @@ void main() {
|
||||
|
||||
group('isFileKernelFile', () {
|
||||
test(
|
||||
'returns false when passed a file that is too small to contain the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3]);
|
||||
expect(await isFileKernelFile(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that is too small to contain the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3]);
|
||||
expect(await isFileKernelFile(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns false when passed a file that does not start with the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4]);
|
||||
expect(await isFileKernelFile(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that does not start with the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4]);
|
||||
expect(await isFileKernelFile(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x90, 0xab, 0xcd, 0xef, 1, 2, 3]);
|
||||
expect(await isFileKernelFile(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the kernel magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x90, 0xab, 0xcd, 0xef, 1, 2, 3]);
|
||||
expect(await isFileKernelFile(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('isFileAppJitSnapshot', () {
|
||||
test(
|
||||
'returns false when passed a file that is too small to contain the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that is too small to contain the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns false when passed a file that does not start with the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that does not start with the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile
|
||||
.writeAsBytesSync([0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0, 1, 2, 3]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AppJIT magic number',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([
|
||||
0xdc,
|
||||
0xdc,
|
||||
0xf6,
|
||||
0xf6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
expect(await isFileAppJitSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
group('isFileAotSnapshot', () {
|
||||
test(
|
||||
'returns false when passed a file that is too small to contain any of the AOT magic numbers',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that is too small to contain any of the AOT magic numbers',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns false when passed a file that does not start with any of the AOT magic numbers',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), false);
|
||||
});
|
||||
'returns false when passed a file that does not start with any of the AOT magic numbers',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([1, 2, 3, 4]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), false);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for arm32 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x01, 0xc0, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for arm32 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x01, 0xc0, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for arm64 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0xaa, 0x64, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for arm64 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0xaa, 0x64, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for riscv32 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x50, 0x32, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for riscv32 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x50, 0x32, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for riscv64 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x50, 0x64, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for riscv64 COFF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x50, 0x64, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for ELF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0x7f, 0x45, 0x4c, 0x46, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for ELF files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([
|
||||
0x7f,
|
||||
0x45,
|
||||
0x4c,
|
||||
0x46,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for macho32 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0xfe, 0xed, 0xfa, 0xce, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for macho32 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([
|
||||
0xfe,
|
||||
0xed,
|
||||
0xfa,
|
||||
0xce,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for macho64 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0xfe, 0xed, 0xfa, 0xcf, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for macho64 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([
|
||||
0xfe,
|
||||
0xed,
|
||||
0xfa,
|
||||
0xcf,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'returns true when passed a file that starts with the AOT magic number for macho64_arm64 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([0xcf, 0xfa, 0xed, 0xfe, 1, 2, 3]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
});
|
||||
'returns true when passed a file that starts with the AOT magic number for macho64_arm64 files',
|
||||
() async {
|
||||
testExecutableFile.writeAsBytesSync([
|
||||
0xcf,
|
||||
0xfa,
|
||||
0xed,
|
||||
0xfe,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]);
|
||||
expect(await isFileAotSnapshot(testExecutableFile), true);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,48 +26,62 @@ void main() {
|
||||
setUp(() {
|
||||
// Make sure we support both path separators.
|
||||
fs = MemoryFileSystem(
|
||||
style: io.Platform.isWindows
|
||||
? FileSystemStyle.windows
|
||||
: FileSystemStyle.posix);
|
||||
style: io.Platform.isWindows
|
||||
? FileSystemStyle.windows
|
||||
: FileSystemStyle.posix,
|
||||
);
|
||||
stderr = StringBuffer();
|
||||
expectedRequests = <String, http.Response>{};
|
||||
chmodRuns = <String, io.ProcessResult>{};
|
||||
|
||||
cache = SdkCache(
|
||||
directory: fs.directory(Uri.file('/tmp/cache')).path,
|
||||
stderr: stderr,
|
||||
verbose: true,
|
||||
fs: fs,
|
||||
httpClient: http.MockClient((request) async {
|
||||
final key = '${request.method.toUpperCase()} ${request.url}';
|
||||
if (!expectedRequests.containsKey(key)) {
|
||||
throw Exception('Unexpected request $key');
|
||||
}
|
||||
return expectedRequests[key]!;
|
||||
}),
|
||||
chmod: (path) => chmodRuns[path]!);
|
||||
directory: fs.directory(Uri.file('/tmp/cache')).path,
|
||||
stderr: stderr,
|
||||
verbose: true,
|
||||
fs: fs,
|
||||
httpClient: http.MockClient((request) async {
|
||||
final key = '${request.method.toUpperCase()} ${request.url}';
|
||||
if (!expectedRequests.containsKey(key)) {
|
||||
throw Exception('Unexpected request $key');
|
||||
}
|
||||
return expectedRequests[key]!;
|
||||
}),
|
||||
chmod: (path) => chmodRuns[path]!,
|
||||
);
|
||||
});
|
||||
|
||||
group('resolveStage', () {
|
||||
test('Uses signed on macOS dev for executables', () {
|
||||
expect(
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.dev, isExecutable: true, hostOS: OS.macOS),
|
||||
Stage.signed);
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.dev,
|
||||
isExecutable: true,
|
||||
hostOS: OS.macOS,
|
||||
),
|
||||
Stage.signed,
|
||||
);
|
||||
});
|
||||
|
||||
test('Uses raw on macOS main for executables', () {
|
||||
expect(
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.main, isExecutable: true, hostOS: OS.macOS),
|
||||
Stage.raw);
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.main,
|
||||
isExecutable: true,
|
||||
hostOS: OS.macOS,
|
||||
),
|
||||
Stage.raw,
|
||||
);
|
||||
});
|
||||
|
||||
test('Uses raw on macOS stable for non-executables', () {
|
||||
expect(
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.stable, isExecutable: false, hostOS: OS.macOS),
|
||||
Stage.raw);
|
||||
SdkCache.resolveStage(
|
||||
channel: Channel.stable,
|
||||
isExecutable: false,
|
||||
hostOS: OS.macOS,
|
||||
),
|
||||
Stage.raw,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,15 +90,18 @@ void main() {
|
||||
final version = '3.4.4';
|
||||
final revision = '60465149414572c8ca189d8f65fdb39795c4b97d';
|
||||
final folder = await cache.resolveVersion(
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'stable',
|
||||
host: Target.linuxArm64);
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'stable',
|
||||
host: Target.linuxArm64,
|
||||
);
|
||||
expect(folder.version, version);
|
||||
expect(folder.revision, revision);
|
||||
expect(folder.channel, Channel.stable);
|
||||
expect(folder.fileUri('VERSION', stage: Stage.raw).toString(),
|
||||
'$dartArchiveUri/channels/stable/raw/hash/$revision/VERSION');
|
||||
expect(
|
||||
folder.fileUri('VERSION', stage: Stage.raw).toString(),
|
||||
'$dartArchiveUri/channels/stable/raw/hash/$revision/VERSION',
|
||||
);
|
||||
});
|
||||
|
||||
test('Falls back to the latest on empty main revision', () async {
|
||||
@@ -97,14 +114,15 @@ void main() {
|
||||
|
||||
expectedRequests['GET $dartArchiveUri/channels/main/raw/latest/VERSION'] =
|
||||
http.Response(
|
||||
json.encode(
|
||||
{'version': latestVersion, 'revision': latestRevision}),
|
||||
io.HttpStatus.ok);
|
||||
json.encode({'version': latestVersion, 'revision': latestRevision}),
|
||||
io.HttpStatus.ok,
|
||||
);
|
||||
final folder = await cache.resolveVersion(
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'main',
|
||||
host: Target.macOSArm64);
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'main',
|
||||
host: Target.macOSArm64,
|
||||
);
|
||||
expect(folder.version, latestVersion);
|
||||
expect(folder.revision, latestRevision);
|
||||
expect(folder.channel, Channel.main);
|
||||
@@ -124,15 +142,17 @@ void main() {
|
||||
http.Response('', io.HttpStatus.notFound),
|
||||
// Revision resolution request.
|
||||
'GET $dartArchiveUri/channels/main/raw/latest/VERSION': http.Response(
|
||||
json.encode({'version': latestVersion, 'revision': latestRevision}),
|
||||
io.HttpStatus.ok)
|
||||
json.encode({'version': latestVersion, 'revision': latestRevision}),
|
||||
io.HttpStatus.ok,
|
||||
),
|
||||
});
|
||||
|
||||
final folder = await cache.resolveVersion(
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'main',
|
||||
host: Target.macOSArm64);
|
||||
version: version,
|
||||
revision: revision,
|
||||
channelName: 'main',
|
||||
host: Target.macOSArm64,
|
||||
);
|
||||
expect(folder.version, latestVersion);
|
||||
expect(folder.revision, latestRevision);
|
||||
expect(folder.channel, Channel.main);
|
||||
@@ -141,10 +161,11 @@ void main() {
|
||||
test('Reports unknown channel', () async {
|
||||
try {
|
||||
await cache.resolveVersion(
|
||||
channelName: 'wat',
|
||||
host: Target.linuxArm64,
|
||||
revision: '',
|
||||
version: '4.0');
|
||||
channelName: 'wat',
|
||||
host: Target.linuxArm64,
|
||||
revision: '',
|
||||
version: '4.0',
|
||||
);
|
||||
fail('expected to throw');
|
||||
} on ArgumentError catch (e) {
|
||||
expect(e.message, contains('Unsupported channel'));
|
||||
@@ -157,15 +178,22 @@ void main() {
|
||||
final version = '3.4.4';
|
||||
final revision = '60465149414572c8ca189d8f65fdb39795c4b97d';
|
||||
|
||||
final genSnapshotFile = fs.file(Uri.file(
|
||||
'/tmp/cache/$version/gen_snapshot_windows_arm64_linux_x64.exe'));
|
||||
final genSnapshotFile = fs.file(
|
||||
Uri.file(
|
||||
'/tmp/cache/$version/gen_snapshot_windows_arm64_linux_x64.exe',
|
||||
),
|
||||
);
|
||||
genSnapshotFile.createSync(exclusive: true, recursive: true);
|
||||
|
||||
final path = await cache.ensureGenSnapshot(
|
||||
archiveFolder: ArchiveFolder(
|
||||
channel: Channel.stable, version: version, revision: revision),
|
||||
host: Target.windowsArm64,
|
||||
target: Target.linuxX64);
|
||||
archiveFolder: ArchiveFolder(
|
||||
channel: Channel.stable,
|
||||
version: version,
|
||||
revision: revision,
|
||||
),
|
||||
host: Target.windowsArm64,
|
||||
target: Target.linuxX64,
|
||||
);
|
||||
expect(path, genSnapshotFile.path);
|
||||
});
|
||||
|
||||
@@ -174,22 +202,32 @@ void main() {
|
||||
final revision = '54cec4d7d36e7a5066770287998f425606a2f983';
|
||||
|
||||
final archiveFolder = ArchiveFolder(
|
||||
channel: Channel.beta, version: version, revision: revision);
|
||||
channel: Channel.beta,
|
||||
version: version,
|
||||
revision: revision,
|
||||
);
|
||||
expectedRequests['GET $dartArchiveUri/channels/beta/signed/hash/'
|
||||
'$revision/sdk/gen_snapshot_macos_arm64_linux_x64'] =
|
||||
http.Response('i am gen_snapshot', io.HttpStatus.ok);
|
||||
'$revision/sdk/gen_snapshot_macos_arm64_linux_x64'] = http.Response(
|
||||
'i am gen_snapshot',
|
||||
io.HttpStatus.ok,
|
||||
);
|
||||
|
||||
final path = await cache.ensureGenSnapshot(
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.macOSArm64,
|
||||
target: Target.linuxX64);
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.macOSArm64,
|
||||
target: Target.linuxX64,
|
||||
);
|
||||
|
||||
expect(
|
||||
path,
|
||||
fs
|
||||
.file(Uri.file(
|
||||
'/tmp/cache/$version/gen_snapshot_macos_arm64_linux_x64'))
|
||||
.path);
|
||||
path,
|
||||
fs
|
||||
.file(
|
||||
Uri.file(
|
||||
'/tmp/cache/$version/gen_snapshot_macos_arm64_linux_x64',
|
||||
),
|
||||
)
|
||||
.path,
|
||||
);
|
||||
expect(fs.file(path).readAsStringSync(), 'i am gen_snapshot');
|
||||
});
|
||||
|
||||
@@ -198,21 +236,26 @@ void main() {
|
||||
final revision = '54cec4d7d36e7a5066770287998f425606a2f983';
|
||||
|
||||
final archiveFolder = ArchiveFolder(
|
||||
channel: Channel.beta, version: version, revision: revision);
|
||||
channel: Channel.beta,
|
||||
version: version,
|
||||
revision: revision,
|
||||
);
|
||||
expectedRequests['GET $dartArchiveUri/channels/beta/raw/hash/'
|
||||
'$revision/sdk/dartaotruntime_linux_x64'] =
|
||||
http.Response('i am dartaotruntime', io.HttpStatus.ok);
|
||||
'$revision/sdk/dartaotruntime_linux_x64'] = http.Response(
|
||||
'i am dartaotruntime',
|
||||
io.HttpStatus.ok,
|
||||
);
|
||||
|
||||
final path = await cache.ensureDartAotRuntime(
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.macOSArm64,
|
||||
target: Target.linuxX64);
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.macOSArm64,
|
||||
target: Target.linuxX64,
|
||||
);
|
||||
|
||||
expect(
|
||||
path,
|
||||
fs
|
||||
.file(Uri.file('/tmp/cache/$version/dartaotruntime_linux_x64'))
|
||||
.path);
|
||||
path,
|
||||
fs.file(Uri.file('/tmp/cache/$version/dartaotruntime_linux_x64')).path,
|
||||
);
|
||||
expect(fs.file(path).readAsStringSync(), 'i am dartaotruntime');
|
||||
});
|
||||
|
||||
@@ -222,16 +265,22 @@ void main() {
|
||||
final revision = '9594995093f642957b780603c6435d9e7a61b923';
|
||||
final binary = 'gen_snapshot_windows_x64_linux_x64.exe';
|
||||
|
||||
final archiveFolder =
|
||||
ArchiveFolder(channel: channel, version: version, revision: revision);
|
||||
final archiveFolder = ArchiveFolder(
|
||||
channel: channel,
|
||||
version: version,
|
||||
revision: revision,
|
||||
);
|
||||
expectedRequests['GET $dartArchiveUri/channels/stable/raw/hash/'
|
||||
'$revision/sdk/$binary'] =
|
||||
http.Response('i am gen_snapshot', io.HttpStatus.ok);
|
||||
'$revision/sdk/$binary'] = http.Response(
|
||||
'i am gen_snapshot',
|
||||
io.HttpStatus.ok,
|
||||
);
|
||||
|
||||
final path = await cache.ensureGenSnapshot(
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.windowsX64,
|
||||
target: Target.linuxX64);
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.windowsX64,
|
||||
target: Target.linuxX64,
|
||||
);
|
||||
|
||||
expect(path, fs.file(Uri.file('/tmp/cache/$version/$binary')).path);
|
||||
expect(fs.file(path).readAsStringSync(), 'i am gen_snapshot');
|
||||
@@ -243,16 +292,22 @@ void main() {
|
||||
final revision = '9594995093f642957b780603c6435d9e7a61b923';
|
||||
final binary = 'dartaotruntime_linux_x64';
|
||||
|
||||
final archiveFolder =
|
||||
ArchiveFolder(channel: channel, version: version, revision: revision);
|
||||
final archiveFolder = ArchiveFolder(
|
||||
channel: channel,
|
||||
version: version,
|
||||
revision: revision,
|
||||
);
|
||||
expectedRequests['GET $dartArchiveUri/channels/stable/raw/hash/'
|
||||
'$revision/sdk/$binary'] =
|
||||
http.Response('i am dartaotruntime', io.HttpStatus.ok);
|
||||
'$revision/sdk/$binary'] = http.Response(
|
||||
'i am dartaotruntime',
|
||||
io.HttpStatus.ok,
|
||||
);
|
||||
|
||||
final path = await cache.ensureDartAotRuntime(
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.windowsX64,
|
||||
target: Target.linuxX64);
|
||||
archiveFolder: archiveFolder,
|
||||
host: Target.windowsX64,
|
||||
target: Target.linuxX64,
|
||||
);
|
||||
|
||||
expect(path, fs.file(Uri.file('/tmp/cache/$version/$binary')).path);
|
||||
expect(fs.file(path).readAsStringSync(), 'i am dartaotruntime');
|
||||
|
||||
@@ -31,66 +31,57 @@ final dartVMServiceMsg =
|
||||
'The Dart VM service is listening on http://127.0.0.1:';
|
||||
|
||||
void main() {
|
||||
group(
|
||||
'implicit dartdev smoke -',
|
||||
() {
|
||||
late final String script;
|
||||
late TestProject p;
|
||||
late TestProject op;
|
||||
group('implicit dartdev smoke -', () {
|
||||
late final String script;
|
||||
late TestProject p;
|
||||
late TestProject op;
|
||||
|
||||
setUpAll(() {
|
||||
p = project(mainSrc: smokeTestScript);
|
||||
script = path.join(p.dirPath, p.relativeFilePath);
|
||||
op = project(mainSrc: observeSmokeTestScript);
|
||||
});
|
||||
setUpAll(() {
|
||||
p = project(mainSrc: smokeTestScript);
|
||||
script = path.join(p.dirPath, p.relativeFilePath);
|
||||
op = project(mainSrc: observeSmokeTestScript);
|
||||
});
|
||||
|
||||
test('dart smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
script,
|
||||
],
|
||||
);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Smoke test!'));
|
||||
expect(result.exitCode, 0);
|
||||
test('dart smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
});
|
||||
final result = await Process.run(Platform.executable, [script]);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Smoke test!'));
|
||||
expect(result.exitCode, 0);
|
||||
}
|
||||
});
|
||||
|
||||
// This test forces dartdev to run implicitly and for
|
||||
// DDS to spawn in a separate process.
|
||||
test('dart --enable-vm-service smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
bool sawProgramMsg = false;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
if (event.contains(dartVMServiceMsg)) {
|
||||
sawServiceMsg = true;
|
||||
}
|
||||
if (event.contains('Observe smoke test!')) {
|
||||
sawProgramMsg = true;
|
||||
}
|
||||
if (sawServiceMsg && sawProgramMsg) {
|
||||
op.kill();
|
||||
}
|
||||
}
|
||||
|
||||
await op.runWithVmService([
|
||||
'--enable-vm-service=0',
|
||||
op.relativeFilePath,
|
||||
], onData);
|
||||
expect(sawServiceMsg, true);
|
||||
expect(sawProgramMsg, true);
|
||||
// This test forces dartdev to run implicitly and for
|
||||
// DDS to spawn in a separate process.
|
||||
test('dart --enable-vm-service smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
});
|
||||
},
|
||||
timeout: Timeout.none,
|
||||
);
|
||||
bool sawProgramMsg = false;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
if (event.contains(dartVMServiceMsg)) {
|
||||
sawServiceMsg = true;
|
||||
}
|
||||
if (event.contains('Observe smoke test!')) {
|
||||
sawProgramMsg = true;
|
||||
}
|
||||
if (sawServiceMsg && sawProgramMsg) {
|
||||
op.kill();
|
||||
}
|
||||
}
|
||||
|
||||
await op.runWithVmService([
|
||||
'--enable-vm-service=0',
|
||||
op.relativeFilePath,
|
||||
], onData);
|
||||
expect(sawServiceMsg, true);
|
||||
expect(sawProgramMsg, true);
|
||||
}
|
||||
});
|
||||
}, timeout: Timeout.none);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@ void main() {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'invalid.dart',
|
||||
],
|
||||
);
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'invalid.dart',
|
||||
]);
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(
|
||||
@@ -42,13 +39,10 @@ void main() {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'--enable-vm-service=0',
|
||||
'invalid.dart',
|
||||
],
|
||||
);
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'--enable-vm-service=0',
|
||||
'invalid.dart',
|
||||
]);
|
||||
expect(result.exitCode, 64);
|
||||
expect(result.stdout, contains('The Dart VM service is listening'));
|
||||
expect(
|
||||
@@ -66,13 +60,10 @@ void main() {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'run',
|
||||
'invalid.dart',
|
||||
],
|
||||
);
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'run',
|
||||
'invalid.dart',
|
||||
]);
|
||||
expect(result.exitCode, 254);
|
||||
expect(result.stdout, isEmpty);
|
||||
expect(
|
||||
@@ -91,14 +82,11 @@ void main() {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'invalid.dart',
|
||||
],
|
||||
);
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
'invalid.dart',
|
||||
]);
|
||||
expect(result.exitCode, 254);
|
||||
expect(result.stdout, contains('The Dart VM service is listening'));
|
||||
expect(
|
||||
|
||||
@@ -34,149 +34,128 @@ final dartVMServiceMsg =
|
||||
'The Dart VM service is listening on http://127.0.0.1:';
|
||||
|
||||
void main() {
|
||||
group(
|
||||
'explicit dartdev smoke -',
|
||||
() {
|
||||
late final String script;
|
||||
late final String observeScript;
|
||||
late TestProject p;
|
||||
late TestProject op;
|
||||
group('explicit dartdev smoke -', () {
|
||||
late final String script;
|
||||
late final String observeScript;
|
||||
late TestProject p;
|
||||
late TestProject op;
|
||||
|
||||
setUpAll(() {
|
||||
p = project(mainSrc: smokeTestScript);
|
||||
script = path.join(p.dirPath, p.relativeFilePath);
|
||||
op = project(mainSrc: observeSmokeTestScript);
|
||||
observeScript = path.join(op.dirPath, op.relativeFilePath);
|
||||
});
|
||||
setUpAll(() {
|
||||
p = project(mainSrc: smokeTestScript);
|
||||
script = path.join(p.dirPath, p.relativeFilePath);
|
||||
op = project(mainSrc: observeSmokeTestScript);
|
||||
observeScript = path.join(op.dirPath, op.relativeFilePath);
|
||||
});
|
||||
|
||||
test('dart run smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'run',
|
||||
script,
|
||||
],
|
||||
);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Smoke test!'));
|
||||
test('dart run smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
});
|
||||
|
||||
// This test forces DDS to spawn in a separate process.
|
||||
test('dart run --enable-vm-service smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
bool sawProgramMsg = false;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
if (event.contains(dartVMServiceMsg)) {
|
||||
sawServiceMsg = true;
|
||||
}
|
||||
if (event.contains('Observe smoke test!')) {
|
||||
sawProgramMsg = true;
|
||||
}
|
||||
if (sawServiceMsg && sawProgramMsg) {
|
||||
op.kill();
|
||||
}
|
||||
}
|
||||
|
||||
await op.runWithVmService([
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
op.relativeFilePath,
|
||||
], onData);
|
||||
expect(sawServiceMsg, true);
|
||||
expect(sawProgramMsg, true);
|
||||
}
|
||||
});
|
||||
|
||||
test('dart run --enable-vm-service smoke.dart with used port', () async {
|
||||
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
||||
final process = await Process.start(
|
||||
Platform.executable,
|
||||
[
|
||||
'run',
|
||||
'--enable-vm-service=${server.port}',
|
||||
observeScript,
|
||||
],
|
||||
);
|
||||
final completer = Completer<void>();
|
||||
late final StreamSubscription<String> sub;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
print(event);
|
||||
if (event.contains('Could not start the VM service:')) {
|
||||
sawServiceMsg = true;
|
||||
process.kill();
|
||||
}
|
||||
}
|
||||
|
||||
void onError(error) async {
|
||||
process.kill();
|
||||
await sub.cancel();
|
||||
completer.complete();
|
||||
}
|
||||
|
||||
void onDone() async {
|
||||
await sub.cancel();
|
||||
completer.complete();
|
||||
}
|
||||
|
||||
sub = process.stderr
|
||||
.transform(utf8.decoder)
|
||||
.listen(onData, onError: onError, onDone: onDone);
|
||||
|
||||
// Wait for process to start.
|
||||
await completer.future;
|
||||
await server.close(force: true);
|
||||
expect(sawServiceMsg, true);
|
||||
});
|
||||
|
||||
// This test verifies that an error isn't thrown when a valid experiment
|
||||
// is passed.
|
||||
// Experiments are lists here:
|
||||
// https://github.com/dart-lang/sdk/blob/main/tools/experimental_features.yaml
|
||||
test(
|
||||
'dart --enable-experiment=variance '
|
||||
'run smoke.dart', () async {
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'--enable-experiment=variance',
|
||||
'run',
|
||||
script,
|
||||
],
|
||||
);
|
||||
final result = await Process.run(Platform.executable, ['run', script]);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Smoke test!'));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// This test verifies that an error is thrown when an invalid experiment
|
||||
// is passed.
|
||||
test(
|
||||
'dart --enable-experiment=invalid-experiment-name '
|
||||
'run smoke.dart', () async {
|
||||
final result = await Process.run(
|
||||
Platform.executable,
|
||||
[
|
||||
'--enable-experiment=invalid-experiment-name',
|
||||
'run',
|
||||
script,
|
||||
],
|
||||
);
|
||||
expect(result.exitCode, 254);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.stdout, isEmpty);
|
||||
});
|
||||
},
|
||||
timeout: Timeout.none,
|
||||
);
|
||||
// This test forces DDS to spawn in a separate process.
|
||||
test('dart run --enable-vm-service smoke.dart', () async {
|
||||
for (int i = 1; i <= numRuns; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
print('Done [$i/$numRuns]');
|
||||
}
|
||||
bool sawProgramMsg = false;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
if (event.contains(dartVMServiceMsg)) {
|
||||
sawServiceMsg = true;
|
||||
}
|
||||
if (event.contains('Observe smoke test!')) {
|
||||
sawProgramMsg = true;
|
||||
}
|
||||
if (sawServiceMsg && sawProgramMsg) {
|
||||
op.kill();
|
||||
}
|
||||
}
|
||||
|
||||
await op.runWithVmService([
|
||||
'run',
|
||||
'--enable-vm-service=0',
|
||||
op.relativeFilePath,
|
||||
], onData);
|
||||
expect(sawServiceMsg, true);
|
||||
expect(sawProgramMsg, true);
|
||||
}
|
||||
});
|
||||
|
||||
test('dart run --enable-vm-service smoke.dart with used port', () async {
|
||||
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
||||
final process = await Process.start(Platform.executable, [
|
||||
'run',
|
||||
'--enable-vm-service=${server.port}',
|
||||
observeScript,
|
||||
]);
|
||||
final completer = Completer<void>();
|
||||
late final StreamSubscription<String> sub;
|
||||
bool sawServiceMsg = false;
|
||||
void onData(event) {
|
||||
print(event);
|
||||
if (event.contains('Could not start the VM service:')) {
|
||||
sawServiceMsg = true;
|
||||
process.kill();
|
||||
}
|
||||
}
|
||||
|
||||
void onError(error) async {
|
||||
process.kill();
|
||||
await sub.cancel();
|
||||
completer.complete();
|
||||
}
|
||||
|
||||
void onDone() async {
|
||||
await sub.cancel();
|
||||
completer.complete();
|
||||
}
|
||||
|
||||
sub = process.stderr
|
||||
.transform(utf8.decoder)
|
||||
.listen(onData, onError: onError, onDone: onDone);
|
||||
|
||||
// Wait for process to start.
|
||||
await completer.future;
|
||||
await server.close(force: true);
|
||||
expect(sawServiceMsg, true);
|
||||
});
|
||||
|
||||
// This test verifies that an error isn't thrown when a valid experiment
|
||||
// is passed.
|
||||
// Experiments are lists here:
|
||||
// https://github.com/dart-lang/sdk/blob/main/tools/experimental_features.yaml
|
||||
test('dart --enable-experiment=variance '
|
||||
'run smoke.dart', () async {
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'--enable-experiment=variance',
|
||||
'run',
|
||||
script,
|
||||
]);
|
||||
expect(result.exitCode, 0);
|
||||
expect(result.stderr, isEmpty);
|
||||
expect(result.stdout, contains('Smoke test!'));
|
||||
});
|
||||
|
||||
// This test verifies that an error is thrown when an invalid experiment
|
||||
// is passed.
|
||||
test('dart --enable-experiment=invalid-experiment-name '
|
||||
'run smoke.dart', () async {
|
||||
final result = await Process.run(Platform.executable, [
|
||||
'--enable-experiment=invalid-experiment-name',
|
||||
'run',
|
||||
script,
|
||||
]);
|
||||
expect(result.exitCode, 254);
|
||||
expect(result.stderr, isNotEmpty);
|
||||
expect(result.stdout, isEmpty);
|
||||
});
|
||||
}, timeout: Timeout.none);
|
||||
}
|
||||
|
||||
@@ -17,19 +17,29 @@ void main() {
|
||||
});
|
||||
|
||||
test('matching input', () {
|
||||
_expect('foo __bar__ baz', {'bar': '__baz__', 'baz': 'foo'},
|
||||
'foo __baz__ baz');
|
||||
_expect('foo __bar__ baz', {
|
||||
'bar': '__baz__',
|
||||
'baz': 'foo',
|
||||
}, 'foo __baz__ baz');
|
||||
});
|
||||
|
||||
test('vars must be alpha + numeric', () {
|
||||
expect(() => substituteVars('str', {'with space': 'noop'}),
|
||||
throwsArgumentError);
|
||||
expect(() => substituteVars('str', {'with!symbols': 'noop'}),
|
||||
throwsArgumentError);
|
||||
expect(() => substituteVars('str', {'with1numbers': 'noop'}),
|
||||
throwsArgumentError);
|
||||
expect(() => substituteVars('str', {'with_under': 'noop'}),
|
||||
throwsArgumentError);
|
||||
expect(
|
||||
() => substituteVars('str', {'with space': 'noop'}),
|
||||
throwsArgumentError,
|
||||
);
|
||||
expect(
|
||||
() => substituteVars('str', {'with!symbols': 'noop'}),
|
||||
throwsArgumentError,
|
||||
);
|
||||
expect(
|
||||
() => substituteVars('str', {'with1numbers': 'noop'}),
|
||||
throwsArgumentError,
|
||||
);
|
||||
expect(
|
||||
() => substituteVars('str', {'with_under': 'noop'}),
|
||||
throwsArgumentError,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+46
-56
@@ -37,18 +37,20 @@ void initGlobalState() {
|
||||
|
||||
/// Creates a test-project in a temp-dir that will [dispose] itself at the end
|
||||
/// of the test.
|
||||
TestProject project(
|
||||
{String? mainSrc,
|
||||
String? analysisOptions,
|
||||
String name = TestProject._defaultProjectName,
|
||||
VersionConstraint? sdkConstraint,
|
||||
Map<String, dynamic>? pubspecExtras}) {
|
||||
TestProject project({
|
||||
String? mainSrc,
|
||||
String? analysisOptions,
|
||||
String name = TestProject._defaultProjectName,
|
||||
VersionConstraint? sdkConstraint,
|
||||
Map<String, dynamic>? pubspecExtras,
|
||||
}) {
|
||||
var testProject = TestProject(
|
||||
mainSrc: mainSrc,
|
||||
name: name,
|
||||
analysisOptions: analysisOptions,
|
||||
sdkConstraint: sdkConstraint,
|
||||
pubspecExtras: pubspecExtras);
|
||||
mainSrc: mainSrc,
|
||||
name: name,
|
||||
analysisOptions: analysisOptions,
|
||||
sdkConstraint: sdkConstraint,
|
||||
pubspecExtras: pubspecExtras,
|
||||
);
|
||||
addTearDown(() => testProject.dispose());
|
||||
return testProject;
|
||||
}
|
||||
@@ -70,11 +72,8 @@ class TestProject {
|
||||
|
||||
String get analysisOptionsPath => path.join(dirPath, 'analysis_options.yaml');
|
||||
|
||||
String get packageConfigPath => path.join(
|
||||
dirPath,
|
||||
'.dart_tool',
|
||||
'package_config.json',
|
||||
);
|
||||
String get packageConfigPath =>
|
||||
path.join(dirPath, '.dart_tool', 'package_config.json');
|
||||
|
||||
final String name;
|
||||
|
||||
@@ -93,30 +92,26 @@ class TestProject {
|
||||
root = Directory.systemTemp.createTempSync('dartdev');
|
||||
file(
|
||||
'pubspec.yaml',
|
||||
JsonEncoder.withIndent(' ').convert(
|
||||
{
|
||||
'name': name,
|
||||
'environment': {'sdk': sdkConstraint?.toString() ?? '^3.0.0'},
|
||||
...?pubspecExtras,
|
||||
},
|
||||
),
|
||||
JsonEncoder.withIndent(' ').convert({
|
||||
'name': name,
|
||||
'environment': {'sdk': sdkConstraint?.toString() ?? '^3.0.0'},
|
||||
...?pubspecExtras,
|
||||
}),
|
||||
);
|
||||
file(
|
||||
'.dart_tool/package_config.json',
|
||||
JsonEncoder.withIndent(' ').convert(
|
||||
{
|
||||
'configVersion': 2,
|
||||
'generator': 'utils.dart',
|
||||
'packages': [
|
||||
{
|
||||
'name': name,
|
||||
'rootUri': '../',
|
||||
'packageUri': 'lib/',
|
||||
'languageVersion': '3.2',
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
JsonEncoder.withIndent(' ').convert({
|
||||
'configVersion': 2,
|
||||
'generator': 'utils.dart',
|
||||
'packages': [
|
||||
{
|
||||
'name': name,
|
||||
'rootUri': '../',
|
||||
'packageUri': 'lib/',
|
||||
'languageVersion': '3.2',
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
file(
|
||||
'.dart_tool/package_graph.json',
|
||||
@@ -127,10 +122,10 @@ class TestProject {
|
||||
'name': name,
|
||||
'version': '1.0.0',
|
||||
'dependencies': [],
|
||||
'devDependencies': []
|
||||
'devDependencies': [],
|
||||
},
|
||||
],
|
||||
'configVersion': 1
|
||||
'configVersion': 1,
|
||||
}),
|
||||
);
|
||||
if (analysisOptions != null) {
|
||||
@@ -195,20 +190,13 @@ class TestProject {
|
||||
);
|
||||
}
|
||||
|
||||
Future<Process> start(
|
||||
List<String> arguments, {
|
||||
String? workingDir,
|
||||
}) {
|
||||
Future<Process> start(List<String> arguments, {String? workingDir}) {
|
||||
return Process.start(
|
||||
Platform.resolvedExecutable,
|
||||
[
|
||||
...arguments,
|
||||
],
|
||||
workingDirectory: workingDir ?? dir.path,
|
||||
environment: {
|
||||
'PUB_CACHE': pubCachePath,
|
||||
})
|
||||
..then((p) => _process = p);
|
||||
Platform.resolvedExecutable,
|
||||
[...arguments],
|
||||
workingDirectory: workingDir ?? dir.path,
|
||||
environment: {'PUB_CACHE': pubCachePath},
|
||||
)..then((p) => _process = p);
|
||||
}
|
||||
|
||||
Future<void> runWithVmService(
|
||||
@@ -340,9 +328,10 @@ void ensureRunFromSdkBinDart() {
|
||||
}
|
||||
if (pathReversed.length < 2 || pathReversed[1] != 'bin') {
|
||||
throw StateError(
|
||||
'''Main executable is not from an SDK build: ${uri.toFilePath()}.
|
||||
'''Main executable is not from an SDK build: ${uri.toFilePath()}.
|
||||
The `pkg/dartdev` tests must be run with the `dart` executable in the `bin` folder.
|
||||
''');
|
||||
''',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +349,8 @@ String replacePathsWithMatchingCase(String input, {required String filePath}) {
|
||||
|
||||
/// Resolves a relative URI from the pkg/dartdev folder.
|
||||
Uri resolveDartDevUri(String path) {
|
||||
final dartDevLibUri =
|
||||
Isolate.resolvePackageUriSync(Uri.parse('package:dartdev/'));
|
||||
final dartDevLibUri = Isolate.resolvePackageUriSync(
|
||||
Uri.parse('package:dartdev/'),
|
||||
);
|
||||
return dartDevLibUri!.resolve('../$path');
|
||||
}
|
||||
|
||||
@@ -96,18 +96,24 @@ void main() {
|
||||
});
|
||||
|
||||
test('twoLines_exactLength', () {
|
||||
expect(wrapText('one two three four', width: 10),
|
||||
equals('one two\nthree four'));
|
||||
expect(
|
||||
wrapText('one two three four', width: 10),
|
||||
equals('one two\nthree four'),
|
||||
);
|
||||
});
|
||||
|
||||
test('twoLines_exactLength_minusOne', () {
|
||||
expect(wrapText('one two three fou', width: 10),
|
||||
equals('one two\nthree fou'));
|
||||
expect(
|
||||
wrapText('one two three fou', width: 10),
|
||||
equals('one two\nthree fou'),
|
||||
);
|
||||
});
|
||||
|
||||
test('twoLines_exactLength_plusOne', () {
|
||||
expect(wrapText('one two three fourr', width: 10),
|
||||
equals('one two\nthree\nfourr'));
|
||||
expect(
|
||||
wrapText('one two three fourr', width: 10),
|
||||
equals('one two\nthree\nfourr'),
|
||||
);
|
||||
});
|
||||
|
||||
test('twoLines_lastLineEndsWithSpace', () {
|
||||
@@ -116,7 +122,9 @@ void main() {
|
||||
|
||||
test('twoLines_multipleSpacesAtSplit', () {
|
||||
expect(
|
||||
wrapText('one two. Three', width: 10), equals('one two. \nThree'));
|
||||
wrapText('one two. Three', width: 10),
|
||||
equals('one two. \nThree'),
|
||||
);
|
||||
});
|
||||
|
||||
test('twoLines_noSpaceLastLine', () {
|
||||
@@ -124,13 +132,17 @@ void main() {
|
||||
});
|
||||
|
||||
test('twoLines_wordLongerThanLine_firstLine', () {
|
||||
expect(wrapText('http://long-url word', width: 10),
|
||||
equals('http://long-url\nword'));
|
||||
expect(
|
||||
wrapText('http://long-url word', width: 10),
|
||||
equals('http://long-url\nword'),
|
||||
);
|
||||
});
|
||||
|
||||
test('twoLines_wordLongerThanLine_lastLine', () {
|
||||
expect(wrapText('word http://long-url', width: 10),
|
||||
equals('word\nhttp://long-url'));
|
||||
expect(
|
||||
wrapText('word http://long-url', width: 10),
|
||||
equals('word\nhttp://long-url'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,14 +162,17 @@ void main() {
|
||||
..cell('bar ' * foo);
|
||||
}
|
||||
var result = table.finish();
|
||||
expect(result, equals('''
|
||||
expect(
|
||||
result,
|
||||
equals('''
|
||||
| Number | Value | Words |
|
||||
| ------ | ----- | ---------------- |
|
||||
| one | 1.0 | bar |
|
||||
| two | 2.0 | bar bar |
|
||||
| three | 3.0 | bar bar bar |
|
||||
| four | 4.0 | bar bar bar bar |
|
||||
'''));
|
||||
'''),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,8 +101,10 @@ class FixRunner<T extends Logger> extends CommandRunner<int> {
|
||||
final ArgParser argParser = globalDartdevOptionsParser();
|
||||
|
||||
FixRunner({required this.logger})
|
||||
: super('fix_runner',
|
||||
'A command-line utility for testing the `dart fix` command.') {
|
||||
: super(
|
||||
'fix_runner',
|
||||
'A command-line utility for testing the `dart fix` command.',
|
||||
) {
|
||||
addCommand(FixCommand());
|
||||
_supportedOptions.forEach(argParser.addOption);
|
||||
}
|
||||
|
||||
@@ -16,14 +16,18 @@ final String dartSdkPath = p.dirname(p.dirname(Platform.resolvedExecutable));
|
||||
final List<FileStats> fileStats = [];
|
||||
|
||||
void main(List<String> arguments) {
|
||||
final version =
|
||||
File(p.join(dartSdkPath, 'version')).readAsStringSync().trim();
|
||||
final version = File(
|
||||
p.join(dartSdkPath, 'version'),
|
||||
).readAsStringSync().trim();
|
||||
|
||||
final sdkData = build(Directory(dartSdkPath), extra: {
|
||||
'comment-1': 'Dart SDK $version',
|
||||
'comment-2': '<size>',
|
||||
'type': 'web',
|
||||
});
|
||||
final sdkData = build(
|
||||
Directory(dartSdkPath),
|
||||
extra: {
|
||||
'comment-1': 'Dart SDK $version',
|
||||
'comment-2': '<size>',
|
||||
'type': 'web',
|
||||
},
|
||||
);
|
||||
final sdkSize = fileStats.fold<int>(0, (previous, e) => previous + e.size);
|
||||
|
||||
sdkData['comment-2'] = sizeMB(sdkSize);
|
||||
@@ -55,8 +59,10 @@ void main(List<String> arguments) {
|
||||
|
||||
String sizeMB(int size) => '${(size / (1024.0 * 1024)).toStringAsFixed(1)}MB';
|
||||
|
||||
Map<String, Object?> build(FileSystemEntity entity,
|
||||
{Map<String, String> extra = const {}}) {
|
||||
Map<String, Object?> build(
|
||||
FileSystemEntity entity, {
|
||||
Map<String, String> extra = const {},
|
||||
}) {
|
||||
const fsBlockSize = 4096.0;
|
||||
|
||||
if (entity is File) {
|
||||
@@ -64,19 +70,14 @@ Map<String, Object?> build(FileSystemEntity entity,
|
||||
((entity.lengthSync() / fsBlockSize).ceilToDouble() * fsBlockSize)
|
||||
.truncate();
|
||||
fileStats.add(FileStats(p.relative(entity.path, from: dartSdkPath), size));
|
||||
return {
|
||||
'n': entity.name,
|
||||
'value': size,
|
||||
};
|
||||
return {'n': entity.name, 'value': size};
|
||||
} else {
|
||||
entity as Directory;
|
||||
|
||||
return {
|
||||
...extra,
|
||||
'n': '${entity.name}/',
|
||||
'children': [
|
||||
...entity.listSyncSorted().map(build),
|
||||
],
|
||||
'children': [...entity.listSyncSorted().map(build)],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user