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:
Sigurd Meldgaard
2026-02-02 06:47:50 -08:00
committed by Commit Queue
parent b2c4c10bba
commit 65c4d768f1
90 changed files with 4567 additions and 4228 deletions
+65 -41
View File
@@ -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;
+88 -56
View File
@@ -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)';
}
+114 -76
View File
@@ -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('|'),
);
}
}
+63 -47
View File
@@ -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
+164 -116
View File
@@ -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));
}
+26 -22
View File
@@ -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 {
+13 -26
View File
@@ -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(
+7 -2
View File
@@ -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([
+53 -27
View File
@@ -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.
+3 -3
View File
@@ -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);
}
+102 -88
View File
@@ -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;
+25 -23
View File
@@ -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');
+128 -94
View File
@@ -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
+28 -18
View File
@@ -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) {
+4 -3
View File
@@ -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;
+7 -3
View File
@@ -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 -31
View File
@@ -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');
+17 -10
View File
@@ -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)) {
+22 -21
View File
@@ -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()) {
+33 -48
View File
@@ -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 =>
+2 -1
View File
@@ -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);
});
+20 -16
View File
@@ -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;
}
+23 -31
View File
@@ -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);
}
}
+57 -66
View File
@@ -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}',
+10 -6
View File
@@ -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) {
+1 -4
View File
@@ -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,
});
}
+6 -5
View File
@@ -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;
}
+112 -68
View File
@@ -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.
///
+8 -6
View File
@@ -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]!,
);
}
+11 -15
View File
@@ -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
+11 -15
View File
@@ -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
+11 -15
View File
@@ -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
+11 -18
View File
@@ -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
+11 -15
View File
@@ -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
+12 -18
View File
@@ -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');
+43 -18
View File
@@ -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));
}
+1 -1
View File
@@ -58,7 +58,7 @@ abstract class VmInteropHandler {
script,
packageConfigOverride,
markMainIsolateAsSystemIsolate,
argsList
argsList,
];
port.send(message);
}
+1 -1
View File
@@ -4,7 +4,7 @@ name: dartdev
publish_to: none
environment:
sdk: ^3.5.0
sdk: ^3.11.0
resolution: workspace
+22 -39
View File
@@ -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: ''),
]);
});
+135 -135
View File
@@ -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')}');
+47 -28
View File
@@ -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'),
),
);
});
}
+70 -67
View File
@@ -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);
});
}
+10 -4
View File
@@ -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);
});
+261 -209
View File
@@ -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));
}
+32 -18
View File
@@ -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]'),
);
});
}
+18 -12
View File
@@ -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 '));
});
+12 -11
View File
@@ -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);
+4 -2
View File
@@ -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;
}
+28 -25
View File
@@ -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'));
}
+11 -7
View File
@@ -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".'),
);
});
}
+342 -360
View File
@@ -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', '''
{
+87 -53
View File
@@ -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);
}
+33 -23
View File
@@ -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', () {
+4 -3
View File
@@ -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']),
)
),
];
}
+16 -11
View File
@@ -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);
},
);
}
+81 -78
View File
@@ -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);
+260 -286
View File
@@ -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(),
},
);
}
+63 -102
View File
@@ -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,
);
+11 -9
View File
@@ -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")');
+20 -18
View File
@@ -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);
}
},
);
}
+11 -12
View File
@@ -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);
},
);
});
});
}
+143 -88
View File
@@ -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');
+48 -57
View File
@@ -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);
}
+16 -28
View File
@@ -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(
+117 -138
View File
@@ -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);
}
+20 -10
View File
@@ -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
View File
@@ -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');
}
+28 -13
View File
@@ -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 |
'''));
'''),
);
});
});
}
+4 -2
View File
@@ -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);
}
+17 -16
View File
@@ -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)],
};
}
}