mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[flutter_tools] update compilation to use package config (#54467)
This commit is contained in:
parent
e5ea6ddb24
commit
b7e30cfc26
@ -373,7 +373,11 @@ class WebAssetServer implements AssetReader {
|
||||
|
||||
/// Write a single file into the in-memory cache.
|
||||
void writeFile(String filePath, String contents) {
|
||||
_files[filePath] = Uint8List.fromList(utf8.encode(contents));
|
||||
writeBytes(filePath, utf8.encode(contents) as Uint8List);
|
||||
}
|
||||
|
||||
void writeBytes(String filePath, Uint8List contents) {
|
||||
_files[filePath] = contents;
|
||||
}
|
||||
|
||||
/// Update the in-memory asset server with the provided source and manifest files.
|
||||
@ -620,6 +624,9 @@ class WebDevFS implements DevFS {
|
||||
@override
|
||||
DateTime lastCompiled;
|
||||
|
||||
@override
|
||||
PackageConfig lastPackageConfig;
|
||||
|
||||
// We do not evict assets on the web.
|
||||
@override
|
||||
Set<String> get assetPathsToEvict => const <String>{};
|
||||
@ -668,7 +675,7 @@ class WebDevFS implements DevFS {
|
||||
|
||||
@override
|
||||
Future<UpdateFSReport> update({
|
||||
String mainPath,
|
||||
Uri mainUri,
|
||||
String target,
|
||||
AssetBundle bundle,
|
||||
DateTime firstBuildTime,
|
||||
@ -681,20 +688,23 @@ class WebDevFS implements DevFS {
|
||||
String pathToReload,
|
||||
List<Uri> invalidatedFiles,
|
||||
bool skipAssets = false,
|
||||
@required PackageConfig packageConfig,
|
||||
}) async {
|
||||
assert(trackWidgetCreation != null);
|
||||
assert(generator != null);
|
||||
final String outputDirectoryPath = globals.fs.file(mainPath).parent.path;
|
||||
lastPackageConfig = packageConfig;
|
||||
final File mainFile = globals.fs.file(mainUri);
|
||||
final String outputDirectoryPath = mainFile.parent.path;
|
||||
|
||||
if (bundleFirstUpload) {
|
||||
webAssetServer.entrypointCacheDirectory = globals.fs.directory(outputDirectoryPath);
|
||||
generator.addFileSystemRoot(outputDirectoryPath);
|
||||
final String entrypoint = globals.fs.path.basename(mainPath);
|
||||
webAssetServer.writeFile(entrypoint, globals.fs.file(mainPath).readAsStringSync());
|
||||
final String entrypoint = globals.fs.path.basename(mainFile.path);
|
||||
webAssetServer.writeBytes(entrypoint, mainFile.readAsBytesSync());
|
||||
webAssetServer.writeBytes('require.js', requireJS.readAsBytesSync());
|
||||
webAssetServer.writeBytes('stack_trace_mapper.js', stackTraceMapper.readAsBytesSync());
|
||||
webAssetServer.writeFile('manifest.json', '{"info":"manifest not generated in run mode."}');
|
||||
webAssetServer.writeFile('flutter_service_worker.js', '// Service worker not loaded in run mode.');
|
||||
webAssetServer.writeFile('require.js', requireJS.readAsStringSync());
|
||||
webAssetServer.writeFile('stack_trace_mapper.js', stackTraceMapper.readAsStringSync());
|
||||
webAssetServer.writeFile(
|
||||
'main.dart.js',
|
||||
generateBootstrapScript(
|
||||
@ -727,11 +737,14 @@ class WebDevFS implements DevFS {
|
||||
// mapping the file name, this is done via an additional file root and
|
||||
// specicial hard-coded scheme.
|
||||
final CompilerOutput compilerOutput = await generator.recompile(
|
||||
'org-dartlang-app:///' + globals.fs.path.basename(mainPath),
|
||||
Uri(
|
||||
scheme: 'org-dartlang-app',
|
||||
path: '/' + mainUri.pathSegments.last,
|
||||
),
|
||||
invalidatedFiles,
|
||||
outputPath: dillOutputPath ??
|
||||
getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
|
||||
packagesFilePath: packagesFilePath,
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
if (compilerOutput == null || compilerOutput.errorCount > 0) {
|
||||
return UpdateFSReport(success: false);
|
||||
|
||||
@ -6,6 +6,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:dwds/dwds.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vmservice;
|
||||
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
|
||||
hide StackTrace;
|
||||
@ -21,7 +22,6 @@ import '../base/terminal.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../cache.dart';
|
||||
import '../compile.dart';
|
||||
import '../convert.dart';
|
||||
import '../dart/pub.dart';
|
||||
import '../devfs.dart';
|
||||
@ -558,7 +558,7 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
// Flutter web projects need to include a generated main entrypoint to call the
|
||||
// appropriate bootstrap method and inject plugins.
|
||||
// Keep this in sync with build_system/targets/web.dart.
|
||||
Future<String> _generateEntrypoint(String main, String packagesPath) async {
|
||||
Future<Uri> _generateEntrypoint(Uri mainUri, PackageConfig packageConfig) async {
|
||||
File result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
|
||||
if (_generatedEntrypointDirectory == null) {
|
||||
_generatedEntrypointDirectory ??= globals.fs.systemTempDirectory.createTempSync('flutter_tools.')
|
||||
@ -569,18 +569,20 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
.any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
|
||||
await injectPlugins(flutterProject, checkProjects: true);
|
||||
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper(main, packagesPath, null, null);
|
||||
final String generatedPath = globals.fs.currentDirectory
|
||||
final Uri generatedUri = globals.fs.currentDirectory
|
||||
.childDirectory('lib')
|
||||
.childFile('generated_plugin_registrant.dart')
|
||||
.absolute.path;
|
||||
final Uri generatedImport = packageUriMapper.map(generatedPath);
|
||||
String importedEntrypoint = packageUriMapper.map(main)?.toString();
|
||||
.absolute.uri;
|
||||
final Uri generatedImport = packageConfig.toPackageUri(generatedUri);
|
||||
Uri importedEntrypoint = packageConfig.toPackageUri(mainUri);
|
||||
// Special handling for entrypoints that are not under lib, such as test scripts.
|
||||
if (importedEntrypoint == null) {
|
||||
final String parent = globals.fs.file(main).parent.path;
|
||||
final String parent = globals.fs.file(mainUri).parent.path;
|
||||
flutterDevices.first.generator.addFileSystemRoot(parent);
|
||||
importedEntrypoint = 'org-dartlang-app:///${globals.fs.path.basename(main)}';
|
||||
importedEntrypoint = Uri(
|
||||
scheme: 'org-dartlang-app',
|
||||
path: '/' + mainUri.pathSegments.last,
|
||||
);
|
||||
}
|
||||
|
||||
final String entrypoint = <String>[
|
||||
@ -604,7 +606,7 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
].join('\n');
|
||||
result.writeAsStringSync(entrypoint);
|
||||
}
|
||||
return result.path;
|
||||
return result.absolute.uri;
|
||||
}
|
||||
|
||||
Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
|
||||
@ -617,18 +619,21 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
return UpdateFSReport(success: false);
|
||||
}
|
||||
}
|
||||
final List<Uri> invalidatedFiles =
|
||||
await projectFileInvalidator.findInvalidated(
|
||||
final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: device.devFS.lastCompiled,
|
||||
urisToMonitor: device.devFS.sources,
|
||||
packagesPath: packagesFilePath,
|
||||
packageConfig: device.devFS.lastPackageConfig,
|
||||
);
|
||||
final Status devFSStatus = globals.logger.startProgress(
|
||||
'Syncing files to device ${device.device.name}...',
|
||||
timeout: timeoutConfiguration.fastOperation,
|
||||
);
|
||||
final UpdateFSReport report = await device.devFS.update(
|
||||
mainPath: await _generateEntrypoint(mainPath, packagesFilePath),
|
||||
mainUri: await _generateEntrypoint(
|
||||
globals.fs.file(mainPath).absolute.uri,
|
||||
invalidationResult.packageConfig,
|
||||
),
|
||||
target: target,
|
||||
bundle: assetBundle,
|
||||
firstBuildTime: firstBuildTime,
|
||||
@ -638,7 +643,8 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
dillOutputPath: dillOutputPath,
|
||||
projectRootPath: projectRootPath,
|
||||
pathToReload: getReloadPath(fullRestart: fullRestart),
|
||||
invalidatedFiles: invalidatedFiles,
|
||||
invalidatedFiles: invalidationResult.uris,
|
||||
packageConfig: invalidationResult.packageConfig,
|
||||
trackWidgetCreation: true,
|
||||
);
|
||||
devFSStatus.stop();
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import '../../artifacts.dart';
|
||||
import '../../base/build.dart';
|
||||
import '../../base/file_system.dart';
|
||||
@ -196,7 +198,7 @@ class KernelSnapshot extends Target {
|
||||
}
|
||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||
final String targetFile = environment.defines[kTargetFile] ?? globals.fs.path.join('lib', 'main.dart');
|
||||
final String packagesPath = environment.projectDir.childFile('.packages').path;
|
||||
final File packagesFile = environment.projectDir.childFile('.packages');
|
||||
final String targetFileAbsolute = globals.fs.file(targetFile).absolute.path;
|
||||
// everything besides 'false' is considered to be enabled.
|
||||
final bool trackWidgetCreation = environment.defines[kTrackWidgetCreation] != 'false';
|
||||
@ -229,6 +231,17 @@ class KernelSnapshot extends Target {
|
||||
forceLinkPlatform = false;
|
||||
}
|
||||
|
||||
final PackageConfig packageConfig = await loadPackageConfigUri(
|
||||
packagesFile.absolute.uri,
|
||||
loader: (Uri uri) {
|
||||
final File file = globals.fs.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
|
||||
final CompilerOutput output = await compiler.compile(
|
||||
sdkRoot: globals.artifacts.getArtifactPath(
|
||||
Artifact.flutterPatchedSdkPath,
|
||||
@ -240,7 +253,7 @@ class KernelSnapshot extends Target {
|
||||
trackWidgetCreation: trackWidgetCreation && buildMode == BuildMode.debug,
|
||||
targetModel: targetModel,
|
||||
outputFilePath: environment.buildDir.childFile('app.dill').path,
|
||||
packagesPath: packagesPath,
|
||||
packagesPath: packagesFile.path,
|
||||
linkPlatformKernelIn: forceLinkPlatform || buildMode.isPrecompiled,
|
||||
mainPath: targetFileAbsolute,
|
||||
depFilePath: environment.buildDir.childFile('kernel_snapshot.d').path,
|
||||
@ -248,6 +261,7 @@ class KernelSnapshot extends Target {
|
||||
fileSystemRoots: fileSystemRoots,
|
||||
fileSystemScheme: fileSystemScheme,
|
||||
dartDefines: parseDartDefines(environment),
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
if (output == null || output.errorCount != 0) {
|
||||
throw Exception('Errors during snapshot creation: $output');
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import '../../artifacts.dart';
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/io.dart';
|
||||
import '../../build_info.dart';
|
||||
import '../../compile.dart';
|
||||
import '../../dart/package_map.dart';
|
||||
import '../../globals.dart' as globals;
|
||||
import '../build_system.dart';
|
||||
@ -56,35 +56,39 @@ class WebEntrypointTarget extends Target {
|
||||
final String targetFile = environment.defines[kTargetFile];
|
||||
final bool shouldInitializePlatform = environment.defines[kInitializePlatform] == 'true';
|
||||
final bool hasPlugins = environment.defines[kHasWebPlugins] == 'true';
|
||||
final String importPath = globals.fs.path.absolute(targetFile);
|
||||
final Uri importUri = environment.fileSystem.file(targetFile).absolute.uri;
|
||||
final PackageConfig packageConfig = await loadPackageConfigUri(
|
||||
environment.projectDir.childFile('.packages').absolute.uri,
|
||||
loader: (Uri uri) {
|
||||
final File file = environment.fileSystem.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
|
||||
// Use the package uri mapper to find the correct package-scheme import path
|
||||
// Use the PackageConfig to find the correct package-scheme import path
|
||||
// for the user application. If the application has a mix of package-scheme
|
||||
// and relative imports for a library, then importing the entrypoint as a
|
||||
// file-scheme will cause said library to be recognized as two distinct
|
||||
// libraries. This can cause surprising behavior as types from that library
|
||||
// will be considered distinct from each other.
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper(
|
||||
importPath,
|
||||
PackageMap.globalPackagesPath,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
// By construction, this will only be null if the .packages file does not
|
||||
// have an entry for the user's application or if the main file is
|
||||
// outside of the lib/ directory.
|
||||
final String mainImport = packageUriMapper.map(importPath)?.toString()
|
||||
?? globals.fs.file(importPath).absolute.uri.toString();
|
||||
final String mainImport = packageConfig.toPackageUri(importUri)?.toString()
|
||||
?? importUri.toString();
|
||||
|
||||
String contents;
|
||||
if (hasPlugins) {
|
||||
final String generatedPath = environment.projectDir
|
||||
final Uri generatedUri = environment.projectDir
|
||||
.childDirectory('lib')
|
||||
.childFile('generated_plugin_registrant.dart')
|
||||
.absolute.path;
|
||||
final String generatedImport = packageUriMapper.map(generatedPath)?.toString()
|
||||
?? globals.fs.file(generatedPath).absolute.uri.toString();
|
||||
.absolute
|
||||
.uri;
|
||||
final String generatedImport = packageConfig.toPackageUri(generatedUri)?.toString()
|
||||
?? generatedUri.toString();
|
||||
contents = '''
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import 'base/context.dart';
|
||||
import 'build_info.dart';
|
||||
@ -72,7 +73,6 @@ class CodeGeneratingKernelCompiler implements KernelCompiler {
|
||||
String outputFilePath,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool aot = false,
|
||||
@required BuildMode buildMode,
|
||||
bool trackWidgetCreation,
|
||||
List<String> extraFrontEndOptions,
|
||||
String sdkRoot,
|
||||
@ -84,6 +84,8 @@ class CodeGeneratingKernelCompiler implements KernelCompiler {
|
||||
String initializeFromDill,
|
||||
String platformDill,
|
||||
List<String> dartDefines,
|
||||
@required BuildMode buildMode,
|
||||
@required PackageConfig packageConfig,
|
||||
}) async {
|
||||
final FlutterProject flutterProject = FlutterProject.current();
|
||||
final CodegenDaemon codegenDaemon = await codeGenerator.daemon(flutterProject);
|
||||
@ -113,6 +115,7 @@ class CodeGeneratingKernelCompiler implements KernelCompiler {
|
||||
targetModel: targetModel,
|
||||
initializeFromDill: initializeFromDill,
|
||||
dartDefines: dartDefines,
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -170,7 +173,12 @@ class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> recompile(String mainPath, List<Uri> invalidatedFiles, {String outputPath, String packagesFilePath}) async {
|
||||
Future<CompilerOutput> recompile(
|
||||
Uri mainUri,
|
||||
List<Uri> invalidatedFiles, {
|
||||
String outputPath,
|
||||
PackageConfig packageConfig,
|
||||
}) async {
|
||||
if (_codegenDaemon.lastStatus != CodegenStatus.Succeeded && _codegenDaemon.lastStatus != CodegenStatus.Failed) {
|
||||
await _codegenDaemon.buildResults.firstWhere((CodegenStatus status) {
|
||||
return status == CodegenStatus.Succeeded || status == CodegenStatus.Failed;
|
||||
@ -180,10 +188,10 @@ class CodeGeneratingResidentCompiler implements ResidentCompiler {
|
||||
globals.printError('Code generation failed, build may have compile errors.');
|
||||
}
|
||||
return _residentCompiler.recompile(
|
||||
mainPath,
|
||||
mainUri,
|
||||
invalidatedFiles,
|
||||
outputPath: outputPath,
|
||||
packagesFilePath: packagesFilePath,
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:usage/uuid/uuid.dart';
|
||||
|
||||
import 'artifacts.dart';
|
||||
@ -15,7 +16,6 @@ import 'base/terminal.dart';
|
||||
import 'build_info.dart';
|
||||
import 'codegen.dart';
|
||||
import 'convert.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'project.dart';
|
||||
|
||||
@ -193,54 +193,6 @@ class StdoutHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts filesystem paths to package URIs.
|
||||
class PackageUriMapper {
|
||||
PackageUriMapper(String scriptPath, String packagesPath, String fileSystemScheme, List<String> fileSystemRoots) {
|
||||
final Map<String, Uri> packageMap = PackageMap(globals.fs.path.absolute(packagesPath), fileSystem: globals.fs).map;
|
||||
final bool isWindowsPath = globals.platform.isWindows && !scriptPath.startsWith('org-dartlang-app');
|
||||
final String scriptUri = Uri.file(scriptPath, windows: isWindowsPath).toString();
|
||||
for (final String packageName in packageMap.keys) {
|
||||
final String prefix = packageMap[packageName].toString();
|
||||
// Only perform a multi-root mapping if there are multiple roots.
|
||||
if (fileSystemScheme != null
|
||||
&& fileSystemRoots != null
|
||||
&& fileSystemRoots.length > 1
|
||||
&& prefix.contains(fileSystemScheme)) {
|
||||
_packageName = packageName;
|
||||
_uriPrefixes = fileSystemRoots
|
||||
.map((String name) => Uri.file(name, windows:globals.platform.isWindows).toString())
|
||||
.toList();
|
||||
return;
|
||||
}
|
||||
if (scriptUri.startsWith(prefix)) {
|
||||
_packageName = packageName;
|
||||
_uriPrefixes = <String>[prefix];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String _packageName;
|
||||
List<String> _uriPrefixes;
|
||||
|
||||
Uri map(String scriptPath) {
|
||||
if (_packageName == null) {
|
||||
return null;
|
||||
}
|
||||
final String scriptUri = Uri.file(scriptPath, windows: globals.platform.isWindows).toString();
|
||||
for (final String uriPrefix in _uriPrefixes) {
|
||||
if (scriptUri.startsWith(uriPrefix)) {
|
||||
return Uri.parse('package:$_packageName/${scriptUri.substring(uriPrefix.length)}');
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Uri findUri(String scriptPath, String packagesPath, String fileSystemScheme, List<String> fileSystemRoots) {
|
||||
return PackageUriMapper(scriptPath, packagesPath, fileSystemScheme, fileSystemRoots).map(scriptPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// List the preconfigured build options for a given build mode.
|
||||
List<String> buildModeOptions(BuildMode mode) {
|
||||
switch (mode) {
|
||||
@ -276,17 +228,18 @@ class KernelCompiler {
|
||||
String outputFilePath,
|
||||
String depFilePath,
|
||||
TargetModel targetModel = TargetModel.flutter,
|
||||
@required BuildMode buildMode,
|
||||
bool linkPlatformKernelIn = false,
|
||||
bool aot = false,
|
||||
@required bool trackWidgetCreation,
|
||||
List<String> extraFrontEndOptions,
|
||||
String packagesPath,
|
||||
List<String> fileSystemRoots,
|
||||
String fileSystemScheme,
|
||||
String initializeFromDill,
|
||||
String platformDill,
|
||||
@required String packagesPath,
|
||||
@required BuildMode buildMode,
|
||||
@required bool trackWidgetCreation,
|
||||
@required List<String> dartDefines,
|
||||
@required PackageConfig packageConfig,
|
||||
}) async {
|
||||
final String frontendServer = globals.artifacts.getArtifactPath(
|
||||
Artifact.frontendServerSnapshotForEngineDartSdk
|
||||
@ -301,7 +254,7 @@ class KernelCompiler {
|
||||
}
|
||||
Uri mainUri;
|
||||
if (packagesPath != null) {
|
||||
mainUri = PackageUriMapper.findUri(mainPath, packagesPath, fileSystemScheme, fileSystemRoots);
|
||||
mainUri = packageConfig.toPackageUri(globals.fs.file(mainPath).uri);
|
||||
}
|
||||
// TODO(jonahwilliams): The output file must already exist, but this seems
|
||||
// unnecessary.
|
||||
@ -392,16 +345,16 @@ abstract class _CompilationRequest {
|
||||
class _RecompileRequest extends _CompilationRequest {
|
||||
_RecompileRequest(
|
||||
Completer<CompilerOutput> completer,
|
||||
this.mainPath,
|
||||
this.mainUri,
|
||||
this.invalidatedFiles,
|
||||
this.outputPath,
|
||||
this.packagesFilePath,
|
||||
this.packageConfig,
|
||||
) : super(completer);
|
||||
|
||||
String mainPath;
|
||||
Uri mainUri;
|
||||
List<Uri> invalidatedFiles;
|
||||
String outputPath;
|
||||
String packagesFilePath;
|
||||
PackageConfig packageConfig;
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> _run(DefaultResidentCompiler compiler) async =>
|
||||
@ -499,10 +452,10 @@ abstract class ResidentCompiler {
|
||||
/// Binary file name is returned if compilation was successful, otherwise
|
||||
/// null is returned.
|
||||
Future<CompilerOutput> recompile(
|
||||
String mainPath,
|
||||
Uri mainUri,
|
||||
List<Uri> invalidatedFiles, {
|
||||
@required String outputPath,
|
||||
String packagesFilePath,
|
||||
@required PackageConfig packageConfig,
|
||||
});
|
||||
|
||||
Future<CompilerOutput> compileExpression(
|
||||
@ -620,56 +573,46 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> recompile(
|
||||
String mainPath,
|
||||
Uri mainUri,
|
||||
List<Uri> invalidatedFiles, {
|
||||
@required String outputPath,
|
||||
String packagesFilePath,
|
||||
@required PackageConfig packageConfig,
|
||||
}) async {
|
||||
assert (outputPath != null);
|
||||
assert(outputPath != null);
|
||||
if (!_controller.hasListener) {
|
||||
_controller.stream.listen(_handleCompilationRequest);
|
||||
}
|
||||
|
||||
final Completer<CompilerOutput> completer = Completer<CompilerOutput>();
|
||||
_controller.add(
|
||||
_RecompileRequest(completer, mainPath, invalidatedFiles, outputPath, packagesFilePath)
|
||||
_RecompileRequest(completer, mainUri, invalidatedFiles, outputPath, packageConfig)
|
||||
);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future<CompilerOutput> _recompile(_RecompileRequest request) async {
|
||||
_stdoutHandler.reset();
|
||||
|
||||
// First time recompile is called we actually have to compile the app from
|
||||
// scratch ignoring list of invalidated files.
|
||||
PackageUriMapper packageUriMapper;
|
||||
if (request.packagesFilePath != null || packagesPath != null) {
|
||||
packageUriMapper = PackageUriMapper(
|
||||
request.mainPath,
|
||||
request.packagesFilePath ?? packagesPath,
|
||||
fileSystemScheme,
|
||||
fileSystemRoots,
|
||||
);
|
||||
}
|
||||
|
||||
_compileRequestNeedsConfirmation = true;
|
||||
|
||||
if (_server == null) {
|
||||
return _compile(
|
||||
_mapFilename(request.mainPath, packageUriMapper),
|
||||
request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? request.mainUri.toString(),
|
||||
request.outputPath,
|
||||
_mapFilename(request.packagesFilePath ?? packagesPath, /* packageUriMapper= */ null),
|
||||
);
|
||||
}
|
||||
|
||||
final String inputKey = Uuid().generateV4();
|
||||
final String mainUri = request.mainPath != null
|
||||
? _mapFilename(request.mainPath, packageUriMapper) + ' '
|
||||
: '';
|
||||
_server.stdin.writeln('recompile $mainUri$inputKey');
|
||||
globals.printTrace('<- recompile $mainUri$inputKey');
|
||||
final String mainUri = request.packageConfig.toPackageUri(request.mainUri)?.toString()
|
||||
?? request.mainUri.toString();
|
||||
_server.stdin.writeln('recompile $mainUri $inputKey');
|
||||
globals.printTrace('<- recompile $mainUri $inputKey');
|
||||
for (final Uri fileUri in request.invalidatedFiles) {
|
||||
final String message = _mapFileUri(fileUri.toString(), packageUriMapper);
|
||||
String message;
|
||||
if (fileUri.scheme == 'package') {
|
||||
message = fileUri.toString();
|
||||
} else {
|
||||
message = request.packageConfig.toPackageUri(fileUri)?.toString()
|
||||
?? fileUri.toString();
|
||||
}
|
||||
_server.stdin.writeln(message);
|
||||
globals.printTrace(message);
|
||||
}
|
||||
@ -699,7 +642,6 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
Future<CompilerOutput> _compile(
|
||||
String scriptUri,
|
||||
String outputPath,
|
||||
String packagesFilePath,
|
||||
) async {
|
||||
final String frontendServer = globals.artifacts.getArtifactPath(
|
||||
Artifact.frontendServerSnapshotForEngineDartSdk
|
||||
@ -726,10 +668,7 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
'--libraries-spec',
|
||||
librariesSpec,
|
||||
],
|
||||
if (packagesFilePath != null) ...<String>[
|
||||
'--packages',
|
||||
packagesFilePath,
|
||||
] else if (packagesPath != null) ...<String>[
|
||||
if (packagesPath != null) ...<String>[
|
||||
'--packages',
|
||||
packagesPath,
|
||||
],
|
||||
@ -916,43 +855,6 @@ class DefaultResidentCompiler implements ResidentCompiler {
|
||||
globals.printTrace('<- reset');
|
||||
}
|
||||
|
||||
String _mapFilename(String filename, PackageUriMapper packageUriMapper) {
|
||||
return _doMapFilename(filename, packageUriMapper) ?? filename;
|
||||
}
|
||||
|
||||
String _mapFileUri(String fileUri, PackageUriMapper packageUriMapper) {
|
||||
String filename;
|
||||
try {
|
||||
filename = Uri.parse(fileUri).toFilePath();
|
||||
} on UnsupportedError catch (_) {
|
||||
return fileUri;
|
||||
}
|
||||
return _doMapFilename(filename, packageUriMapper) ?? fileUri;
|
||||
}
|
||||
|
||||
String _doMapFilename(String filename, PackageUriMapper packageUriMapper) {
|
||||
if (packageUriMapper != null) {
|
||||
final Uri packageUri = packageUriMapper.map(filename);
|
||||
if (packageUri != null) {
|
||||
return packageUri.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (fileSystemRoots != null) {
|
||||
for (final String root in fileSystemRoots) {
|
||||
if (filename.startsWith(root)) {
|
||||
return Uri(
|
||||
scheme: fileSystemScheme, path: filename.substring(root.length))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (globals.platform.isWindows && fileSystemRoots != null && fileSystemRoots.length > 1) {
|
||||
return Uri.file(filename, windows: globals.platform.isWindows).toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<dynamic> shutdown() async {
|
||||
// Server was never successfully created.
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vmservice;
|
||||
|
||||
import 'asset.dart';
|
||||
@ -17,7 +18,6 @@ import 'build_info.dart';
|
||||
import 'bundle.dart';
|
||||
import 'compile.dart';
|
||||
import 'convert.dart' show base64, utf8;
|
||||
import 'dart/package_map.dart';
|
||||
import 'globals.dart' as globals;
|
||||
import 'vmservice.dart';
|
||||
|
||||
@ -395,32 +395,28 @@ class DevFS {
|
||||
VMService serviceProtocol,
|
||||
this.fsName,
|
||||
this.rootDirectory, {
|
||||
String packagesFilePath,
|
||||
@required OperatingSystemUtils osUtils,
|
||||
}) : _operations = ServiceProtocolDevFSOperations(serviceProtocol),
|
||||
_httpWriter = _DevFSHttpWriter(
|
||||
fsName,
|
||||
serviceProtocol,
|
||||
osUtils: osUtils,
|
||||
),
|
||||
_packagesFilePath = packagesFilePath ?? globals.fs.path.join(rootDirectory.path, kPackagesFileName);
|
||||
);
|
||||
|
||||
DevFS.operations(
|
||||
this._operations,
|
||||
this.fsName,
|
||||
this.rootDirectory, {
|
||||
String packagesFilePath,
|
||||
}) : _httpWriter = null,
|
||||
_packagesFilePath = packagesFilePath ?? globals.fs.path.join(rootDirectory.path, kPackagesFileName);
|
||||
this.rootDirectory,
|
||||
) : _httpWriter = null;
|
||||
|
||||
final DevFSOperations _operations;
|
||||
final _DevFSHttpWriter _httpWriter;
|
||||
final String fsName;
|
||||
final Directory rootDirectory;
|
||||
final String _packagesFilePath;
|
||||
final Set<String> assetPathsToEvict = <String>{};
|
||||
List<Uri> sources = <Uri>[];
|
||||
DateTime lastCompiled;
|
||||
PackageConfig lastPackageConfig;
|
||||
|
||||
Uri _baseUri;
|
||||
Uri get baseUri => _baseUri;
|
||||
@ -462,23 +458,25 @@ class DevFS {
|
||||
///
|
||||
/// Returns the number of bytes synced.
|
||||
Future<UpdateFSReport> update({
|
||||
@required String mainPath,
|
||||
@required Uri mainUri,
|
||||
@required ResidentCompiler generator,
|
||||
@required bool trackWidgetCreation,
|
||||
@required String pathToReload,
|
||||
@required List<Uri> invalidatedFiles,
|
||||
@required PackageConfig packageConfig,
|
||||
String target,
|
||||
AssetBundle bundle,
|
||||
DateTime firstBuildTime,
|
||||
bool bundleFirstUpload = false,
|
||||
@required ResidentCompiler generator,
|
||||
String dillOutputPath,
|
||||
@required bool trackWidgetCreation,
|
||||
bool fullRestart = false,
|
||||
String projectRootPath,
|
||||
@required String pathToReload,
|
||||
@required List<Uri> invalidatedFiles,
|
||||
bool skipAssets = false,
|
||||
}) async {
|
||||
assert(trackWidgetCreation != null);
|
||||
assert(generator != null);
|
||||
final DateTime candidateCompileTime = DateTime.now();
|
||||
lastPackageConfig = packageConfig;
|
||||
|
||||
// Update modified files
|
||||
final String assetBuildDirPrefix = _asUriPath(getAssetBuildDirectory());
|
||||
@ -514,10 +512,10 @@ class DevFS {
|
||||
// dill files that depend on the invalidated files.
|
||||
globals.printTrace('Compiling dart to kernel with ${invalidatedFiles.length} updated files');
|
||||
final CompilerOutput compilerOutput = await generator.recompile(
|
||||
mainPath,
|
||||
mainUri,
|
||||
invalidatedFiles,
|
||||
outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
|
||||
packagesFilePath : _packagesFilePath,
|
||||
outputPath: dillOutputPath ?? getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation),
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
if (compilerOutput == null || compilerOutput.errorCount > 0) {
|
||||
return UpdateFSReport(success: false);
|
||||
|
||||
@ -7,6 +7,7 @@ import 'dart:async';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
import 'package:devtools_server/devtools_server.dart' as devtools_server;
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import 'application_package.dart';
|
||||
import 'artifacts.dart';
|
||||
@ -58,6 +59,7 @@ class FlutterDevice {
|
||||
targetModel: targetModel,
|
||||
experimentalFlags: experimentalFlags,
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
);
|
||||
|
||||
/// Create a [FlutterDevice] with optional code generation enabled.
|
||||
@ -104,7 +106,8 @@ class FlutterDevice {
|
||||
.absolute.uri.toString(),
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
librariesSpec: globals.fs.file(globals.artifacts
|
||||
.getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString()
|
||||
.getArtifactPath(Artifact.flutterWebLibrariesJson)).uri.toString(),
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
);
|
||||
} else {
|
||||
generator = ResidentCompiler(
|
||||
@ -121,6 +124,7 @@ class FlutterDevice {
|
||||
experimentalFlags: experimentalFlags,
|
||||
dartDefines: buildInfo.dartDefines,
|
||||
initializeFromDill: globals.fs.path.join(getBuildDirectory(), 'cache.dill'),
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
);
|
||||
}
|
||||
|
||||
@ -285,7 +289,6 @@ class FlutterDevice {
|
||||
vmService,
|
||||
fsName,
|
||||
rootDirectory,
|
||||
packagesFilePath: packagesFilePath,
|
||||
osUtils: globals.os,
|
||||
);
|
||||
return devFS.create();
|
||||
@ -548,7 +551,7 @@ class FlutterDevice {
|
||||
}
|
||||
|
||||
Future<UpdateFSReport> updateDevFS({
|
||||
String mainPath,
|
||||
Uri mainUri,
|
||||
String target,
|
||||
AssetBundle bundle,
|
||||
DateTime firstBuildTime,
|
||||
@ -559,6 +562,7 @@ class FlutterDevice {
|
||||
String pathToReload,
|
||||
@required String dillOutputPath,
|
||||
@required List<Uri> invalidatedFiles,
|
||||
@required PackageConfig packageConfig,
|
||||
}) async {
|
||||
final Status devFSStatus = globals.logger.startProgress(
|
||||
'Syncing files to device ${device.name}...',
|
||||
@ -567,7 +571,7 @@ class FlutterDevice {
|
||||
UpdateFSReport report;
|
||||
try {
|
||||
report = await devFS.update(
|
||||
mainPath: mainPath,
|
||||
mainUri: mainUri,
|
||||
target: target,
|
||||
bundle: bundle,
|
||||
firstBuildTime: firstBuildTime,
|
||||
@ -579,6 +583,7 @@ class FlutterDevice {
|
||||
projectRootPath: projectRootPath,
|
||||
pathToReload: pathToReload,
|
||||
invalidatedFiles: invalidatedFiles,
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
} on DevFSException {
|
||||
devFSStatus.cancel();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
@ -17,6 +18,7 @@ import 'build_info.dart';
|
||||
import 'bundle.dart';
|
||||
import 'compile.dart';
|
||||
import 'convert.dart';
|
||||
import 'dart/package_map.dart';
|
||||
import 'devfs.dart';
|
||||
import 'device.dart';
|
||||
import 'globals.dart' as globals;
|
||||
@ -151,13 +153,23 @@ class HotRunner extends ResidentRunner {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<OperationResult> reloadMethod({String libraryId, String classId}) async {
|
||||
Future<OperationResult> reloadMethod({ String libraryId, String classId }) async {
|
||||
final Stopwatch stopwatch = Stopwatch()..start();
|
||||
final UpdateFSReport results = UpdateFSReport(success: true);
|
||||
final List<Uri> invalidated = <Uri>[Uri.parse(libraryId)];
|
||||
final PackageConfig packageConfig = await loadPackageConfigUri(
|
||||
globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
|
||||
loader: (Uri uri) {
|
||||
final File file = globals.fs.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
results.incorporateResults(await device.updateDevFS(
|
||||
mainPath: mainPath,
|
||||
mainUri: globals.fs.file(mainPath).absolute.uri,
|
||||
target: target,
|
||||
bundle: assetBundle,
|
||||
firstBuildTime: firstBuildTime,
|
||||
@ -167,6 +179,7 @@ class HotRunner extends ResidentRunner {
|
||||
projectRootPath: projectRootPath,
|
||||
pathToReload: getReloadPath(fullRestart: false),
|
||||
invalidatedFiles: invalidated,
|
||||
packageConfig: packageConfig,
|
||||
dillOutputPath: dillOutputPath,
|
||||
));
|
||||
}
|
||||
@ -345,6 +358,16 @@ class HotRunner extends ResidentRunner {
|
||||
firstBuildTime = DateTime.now();
|
||||
|
||||
final List<Future<bool>> startupTasks = <Future<bool>>[];
|
||||
final PackageConfig packageConfig = await loadPackageConfigUri(
|
||||
globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
|
||||
loader: (Uri uri) {
|
||||
final File file = globals.fs.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
// Here we initialize the frontend_server concurrently with the platform
|
||||
// build, reducing overall initialization time. This is safe because the first
|
||||
@ -353,11 +376,11 @@ class HotRunner extends ResidentRunner {
|
||||
if (device.generator != null) {
|
||||
startupTasks.add(
|
||||
device.generator.recompile(
|
||||
mainPath,
|
||||
globals.fs.file(mainPath).uri,
|
||||
<Uri>[],
|
||||
outputPath: dillOutputPath ??
|
||||
getDefaultApplicationKernelPath(trackWidgetCreation: debuggingOptions.buildInfo.trackWidgetCreation),
|
||||
packagesFilePath : packagesFilePath,
|
||||
packageConfig: packageConfig,
|
||||
).then((CompilerOutput output) => output?.errorCount == 0)
|
||||
);
|
||||
}
|
||||
@ -405,18 +428,17 @@ class HotRunner extends ResidentRunner {
|
||||
}
|
||||
}
|
||||
|
||||
// Picking up first device's compiler as a source of truth - compilers
|
||||
// for all devices should be in sync.
|
||||
final List<Uri> invalidatedFiles = await projectFileInvalidator.findInvalidated(
|
||||
final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: flutterDevices[0].devFS.lastCompiled,
|
||||
urisToMonitor: flutterDevices[0].devFS.sources,
|
||||
packagesPath: packagesFilePath,
|
||||
asyncScanning: hotRunnerConfig.asyncScanning,
|
||||
packageConfig: flutterDevices[0].devFS.lastPackageConfig,
|
||||
);
|
||||
final UpdateFSReport results = UpdateFSReport(success: true);
|
||||
for (final FlutterDevice device in flutterDevices) {
|
||||
results.incorporateResults(await device.updateDevFS(
|
||||
mainPath: mainPath,
|
||||
mainUri: globals.fs.file(mainPath).absolute.uri,
|
||||
target: target,
|
||||
bundle: assetBundle,
|
||||
firstBuildTime: firstBuildTime,
|
||||
@ -425,7 +447,8 @@ class HotRunner extends ResidentRunner {
|
||||
fullRestart: fullRestart,
|
||||
projectRootPath: projectRootPath,
|
||||
pathToReload: getReloadPath(fullRestart: fullRestart),
|
||||
invalidatedFiles: invalidatedFiles,
|
||||
invalidatedFiles: invalidationResult.uris,
|
||||
packageConfig: invalidationResult.packageConfig,
|
||||
dillOutputPath: dillOutputPath,
|
||||
));
|
||||
}
|
||||
@ -1156,6 +1179,17 @@ class HotRunner extends ResidentRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of an invalidation check from [ProjectFileInvalidator].
|
||||
class InvalidationResult {
|
||||
const InvalidationResult({
|
||||
this.uris,
|
||||
this.packageConfig,
|
||||
});
|
||||
|
||||
final List<Uri> uris;
|
||||
final PackageConfig packageConfig;
|
||||
}
|
||||
|
||||
/// The [ProjectFileInvalidator] track the dependencies for a running
|
||||
/// application to determine when they are dirty.
|
||||
class ProjectFileInvalidator {
|
||||
@ -1182,10 +1216,11 @@ class ProjectFileInvalidator {
|
||||
// ~2000 files.
|
||||
static const int _kMaxPendingStats = 8;
|
||||
|
||||
Future<List<Uri>> findInvalidated({
|
||||
Future<InvalidationResult> findInvalidated({
|
||||
@required DateTime lastCompiled,
|
||||
@required List<Uri> urisToMonitor,
|
||||
@required String packagesPath,
|
||||
@required PackageConfig packageConfig,
|
||||
bool asyncScanning = false,
|
||||
}) async {
|
||||
assert(urisToMonitor != null);
|
||||
@ -1194,7 +1229,10 @@ class ProjectFileInvalidator {
|
||||
if (lastCompiled == null) {
|
||||
// Initial load.
|
||||
assert(urisToMonitor.isEmpty);
|
||||
return <Uri>[];
|
||||
return InvalidationResult(
|
||||
packageConfig: await _createPackageConfig(packagesPath),
|
||||
uris: <Uri>[]
|
||||
);
|
||||
}
|
||||
|
||||
final Stopwatch stopwatch = Stopwatch()..start();
|
||||
@ -1202,9 +1240,6 @@ class ProjectFileInvalidator {
|
||||
// Don't watch pub cache directories to speed things up a little.
|
||||
for (final Uri uri in urisToMonitor)
|
||||
if (_isNotInPubCache(uri)) uri,
|
||||
|
||||
// We need to check the .packages file too since it is not used in compilation.
|
||||
_fileSystem.file(packagesPath).uri,
|
||||
];
|
||||
final List<Uri> invalidatedFiles = <Uri>[];
|
||||
|
||||
@ -1233,16 +1268,41 @@ class ProjectFileInvalidator {
|
||||
}
|
||||
}
|
||||
}
|
||||
// We need to check the .packages file too since it is not used in compilation.
|
||||
final Uri packageUri = _fileSystem.file(packagesPath).uri;
|
||||
final DateTime updatedAt = _fileSystem.statSync(
|
||||
packageUri.toFilePath(windows: _platform.isWindows)).modified;
|
||||
if (updatedAt != null && updatedAt.isAfter(lastCompiled)) {
|
||||
invalidatedFiles.add(packageUri);
|
||||
packageConfig = await _createPackageConfig(packagesPath);
|
||||
}
|
||||
|
||||
_logger.printTrace(
|
||||
'Scanned through ${urisToScan.length} files in '
|
||||
'${stopwatch.elapsedMilliseconds}ms'
|
||||
'${asyncScanning ? " (async)" : ""}',
|
||||
);
|
||||
return invalidatedFiles;
|
||||
return InvalidationResult(
|
||||
packageConfig: packageConfig,
|
||||
uris: invalidatedFiles,
|
||||
);
|
||||
}
|
||||
|
||||
bool _isNotInPubCache(Uri uri) {
|
||||
return !(_platform.isWindows && uri.path.contains(_pubCachePathWindows))
|
||||
&& !uri.path.contains(_pubCachePathLinuxAndMac);
|
||||
}
|
||||
|
||||
Future<PackageConfig> _createPackageConfig(String packagesPath) {
|
||||
return loadPackageConfigUri(
|
||||
_fileSystem.file(packagesPath).absolute.uri,
|
||||
loader: (Uri uri) {
|
||||
final File file = _fileSystem.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ class FlutterPlatform extends PlatformPlugin {
|
||||
if (precompiledDillPath == null && precompiledDillFiles == null) {
|
||||
// Lazily instantiate compiler so it is built only if it is actually used.
|
||||
compiler ??= TestCompiler(buildMode, trackWidgetCreation, flutterProject);
|
||||
mainDart = await compiler.compile(mainDart);
|
||||
mainDart = await compiler.compile(globals.fs.file(mainDart).uri);
|
||||
|
||||
if (mainDart == null) {
|
||||
controller.sink.addError(_getErrorMessage('Compilation failed', testPath, shellPath));
|
||||
|
||||
@ -869,7 +869,7 @@ class TestGoldenComparator {
|
||||
|
||||
// Lazily create the compiler
|
||||
_compiler = _compiler ?? compilerFactory();
|
||||
final String output = await _compiler.compile(listenerFile.path);
|
||||
final String output = await _compiler.compile(listenerFile.uri);
|
||||
final List<String> command = <String>[
|
||||
shellPath,
|
||||
'--disable-observatory',
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../base/file_system.dart';
|
||||
@ -19,8 +20,9 @@ import '../project.dart';
|
||||
|
||||
/// A request to the [TestCompiler] for recompilation.
|
||||
class _CompilationRequest {
|
||||
_CompilationRequest(this.path, this.result);
|
||||
String path;
|
||||
_CompilationRequest(this.mainUri, this.result);
|
||||
|
||||
Uri mainUri;
|
||||
Completer<String> result;
|
||||
}
|
||||
|
||||
@ -70,7 +72,7 @@ class TestCompiler {
|
||||
// Whether to report compiler messages.
|
||||
bool _suppressOutput = false;
|
||||
|
||||
Future<String> compile(String mainDart) {
|
||||
Future<String> compile(Uri mainDart) {
|
||||
final Completer<String> completer = Completer<String>();
|
||||
compilerController.add(_CompilationRequest(mainDart, completer));
|
||||
return completer.future;
|
||||
@ -95,13 +97,13 @@ class TestCompiler {
|
||||
Future<ResidentCompiler> createCompiler() async {
|
||||
final ResidentCompiler residentCompiler = ResidentCompiler(
|
||||
globals.artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
buildMode: buildMode,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
compilerMessageConsumer: _reportCompilerMessage,
|
||||
initializeFromDill: testFilePath,
|
||||
unsafePackageSerialization: false,
|
||||
dartDefines: const <String>[],
|
||||
packagesPath: PackageMap.globalPackagesPath,
|
||||
);
|
||||
if (flutterProject.hasBuilders) {
|
||||
return CodeGeneratingResidentCompiler.create(
|
||||
@ -112,6 +114,8 @@ class TestCompiler {
|
||||
return residentCompiler;
|
||||
}
|
||||
|
||||
PackageConfig _packageConfig;
|
||||
|
||||
// Handle a compilation request.
|
||||
Future<void> _onCompilationRequest(_CompilationRequest request) async {
|
||||
final bool isEmpty = compilationQueue.isEmpty;
|
||||
@ -122,9 +126,19 @@ class TestCompiler {
|
||||
if (!isEmpty) {
|
||||
return;
|
||||
}
|
||||
_packageConfig ??= await loadPackageConfigUri(
|
||||
globals.fs.file(PackageMap.globalPackagesPath).absolute.uri,
|
||||
loader: (Uri uri) async {
|
||||
final File file = globals.fs.file(uri);
|
||||
if (!file.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
return file.readAsBytes();
|
||||
}
|
||||
);
|
||||
while (compilationQueue.isNotEmpty) {
|
||||
final _CompilationRequest request = compilationQueue.first;
|
||||
globals.printTrace('Compiling ${request.path}');
|
||||
globals.printTrace('Compiling ${request.mainUri}');
|
||||
final Stopwatch compilerTime = Stopwatch()..start();
|
||||
bool firstCompile = false;
|
||||
if (compiler == null) {
|
||||
@ -133,9 +147,10 @@ class TestCompiler {
|
||||
}
|
||||
_suppressOutput = false;
|
||||
final CompilerOutput compilerOutput = await compiler.recompile(
|
||||
request.path,
|
||||
<Uri>[Uri.parse(request.path)],
|
||||
request.mainUri,
|
||||
<Uri>[request.mainUri],
|
||||
outputPath: outputDill.path,
|
||||
packageConfig: _packageConfig,
|
||||
);
|
||||
final String outputPath = compilerOutput?.outputFilename;
|
||||
|
||||
@ -143,12 +158,13 @@ class TestCompiler {
|
||||
// errors, pass [null] upwards to the consumer and shutdown the
|
||||
// compiler to avoid reusing compiler that might have gotten into
|
||||
// a weird state.
|
||||
final String path = request.mainUri.toFilePath(windows: globals.platform.isWindows);
|
||||
if (outputPath == null || compilerOutput.errorCount > 0) {
|
||||
request.result.complete(null);
|
||||
await _shutdown();
|
||||
} else {
|
||||
final File outputFile = globals.fs.file(outputPath);
|
||||
final File kernelReadyToRun = await outputFile.copy('${request.path}.dill');
|
||||
final File kernelReadyToRun = await outputFile.copy('$path.dill');
|
||||
final File testCache = globals.fs.file(testFilePath);
|
||||
if (firstCompile || !testCache.existsSync() || (testCache.lengthSync() < outputFile.lengthSync())) {
|
||||
// The idea is to keep the cache file up-to-date and include as
|
||||
@ -161,7 +177,7 @@ class TestCompiler {
|
||||
compiler.accept();
|
||||
compiler.reset();
|
||||
}
|
||||
globals.printTrace('Compiling ${request.path} took ${compilerTime.elapsedMilliseconds}ms');
|
||||
globals.printTrace('Compiling $path took ${compilerTime.elapsedMilliseconds}ms');
|
||||
// Only remove now when we finished processing the element
|
||||
compilationQueue.removeAt(0);
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ void main() {
|
||||
|
||||
// Import.
|
||||
expect(generated, contains("import 'file:///other/lib/main.dart' as entrypoint;"));
|
||||
expect(generated, contains("import 'file:///foo/lib/generated_plugin_registrant.dart';"));
|
||||
expect(generated, contains("import 'package:foo/generated_plugin_registrant.dart';"));
|
||||
}));
|
||||
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
@ -59,6 +60,8 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
trackWidgetCreation: false,
|
||||
dartDefines: const <String>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
|
||||
@ -88,6 +91,8 @@ void main() {
|
||||
trackWidgetCreation: false,
|
||||
aot: true,
|
||||
dartDefines: const <String>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
|
||||
@ -121,6 +126,8 @@ void main() {
|
||||
trackWidgetCreation: false,
|
||||
aot: true,
|
||||
dartDefines: const <String>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
|
||||
@ -152,6 +159,8 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
trackWidgetCreation: false,
|
||||
dartDefines: const <String>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
|
||||
@ -179,6 +188,8 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
trackWidgetCreation: false,
|
||||
dartDefines: const <String>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
expect(mockFrontendServerStdIn.getAndClear(), isEmpty);
|
||||
expect(testLogger.errorText, equals('\nCompiler message:\nline1\nline2\n'));
|
||||
@ -201,6 +212,8 @@ void main() {
|
||||
buildMode: BuildMode.debug,
|
||||
trackWidgetCreation: false,
|
||||
dartDefines: const <String>['FOO=bar', 'BAZ=qux'],
|
||||
packageConfig: PackageConfig.empty,
|
||||
packagesPath: '.packages',
|
||||
);
|
||||
|
||||
expect(latestCommand, containsAllInOrder(<String>['-DFOO=bar', '-DBAZ=qux']));
|
||||
|
||||
@ -10,7 +10,9 @@ import 'package:flutter_tools/src/base/terminal.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
@ -74,12 +76,13 @@ void main() {
|
||||
)));
|
||||
|
||||
await generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
globals.fs.file('/path/to/main.dart').uri,
|
||||
null, /* invalidatedFiles */
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
).then((CompilerOutput output) {
|
||||
expect(mockFrontendServerStdIn.getAndClear(),
|
||||
'compile /path/to/main.dart\n');
|
||||
'compile file:///path/to/main.dart\n');
|
||||
verifyNoMoreInteractions(mockFrontendServerStdIn);
|
||||
expect(testLogger.errorText,
|
||||
equals('\nCompiler message:\nline1\nline2\n'));
|
||||
@ -122,9 +125,10 @@ void main() {
|
||||
// The test manages timing via completers.
|
||||
unawaited(
|
||||
generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null, /* invalidatedFiles */
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
).then((CompilerOutput outputCompile) {
|
||||
expect(testLogger.errorText,
|
||||
equals('\nCompiler message:\nline1\nline2\n'));
|
||||
|
||||
@ -11,6 +11,7 @@ import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:process/process.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
@ -58,9 +59,10 @@ void main() {
|
||||
));
|
||||
|
||||
final CompilerOutput output = await generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null /* invalidatedFiles */,
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
|
||||
verifyNoMoreInteractions(mockFrontendServerStdIn);
|
||||
@ -78,9 +80,10 @@ void main() {
|
||||
);
|
||||
|
||||
expect(asyncGuard(() => generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null, /* invalidatedFiles */
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
)), throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
@ -96,9 +99,10 @@ void main() {
|
||||
);
|
||||
|
||||
expect(asyncGuard(() => generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null, /* invalidatedFiles */
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
)), throwsToolExit());
|
||||
}, overrides: <Type, Generator>{
|
||||
ProcessManager: () => mockProcessManager,
|
||||
@ -112,9 +116,10 @@ void main() {
|
||||
.thenAnswer((Invocation invocation) => streamController.stream);
|
||||
streamController.add(utf8.encode('result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0\n'));
|
||||
await generator.recompile(
|
||||
'/path/to/main.dart',
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null, /* invalidatedFiles */
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
|
||||
|
||||
@ -153,7 +158,12 @@ void main() {
|
||||
streamController.add(utf8.encode(
|
||||
'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0\n'
|
||||
));
|
||||
await generator.recompile('/path/to/main.dart', null /* invalidatedFiles */, outputPath: '/build/');
|
||||
await generator.recompile(
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
null /* invalidatedFiles */,
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
expect(mockFrontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
|
||||
|
||||
await _recompile(streamController, generator, mockFrontendServerStdIn,
|
||||
@ -187,16 +197,18 @@ Future<void> _recompile(
|
||||
streamController.add(utf8.encode(mockCompilerOutput));
|
||||
});
|
||||
final CompilerOutput output = await generator.recompile(
|
||||
null /* mainPath */,
|
||||
Uri.parse('/path/to/main.dart'),
|
||||
<Uri>[Uri.parse('/path/to/main.dart')],
|
||||
outputPath: '/build/',
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
expect(output.outputFilename, equals('/path/to/main.dart.dill'));
|
||||
final String commands = mockFrontendServerStdIn.getAndClear();
|
||||
final RegExp re = RegExp(r'^recompile (.*)\n/path/to/main.dart\n(.*)\n$');
|
||||
expect(commands, matches(re));
|
||||
final Match match = re.firstMatch(commands);
|
||||
expect(match[1] == match[2], isTrue);
|
||||
final RegExp whitespace = RegExp(r'\s+');
|
||||
final List<String> parts = commands.split(whitespace);
|
||||
|
||||
// Test that uuid matches at beginning and end.
|
||||
expect(parts[2], equals(parts[4]));
|
||||
mockFrontendServerStdIn.stdInWrites.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/devfs.dart';
|
||||
import 'package:flutter_tools/src/vmservice.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:vm_service/vm_service.dart' as vm_service;
|
||||
|
||||
import '../src/common.dart';
|
||||
@ -160,11 +161,12 @@ void main() {
|
||||
|
||||
final MockResidentCompiler residentCompiler = MockResidentCompiler();
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/foo.txt',
|
||||
mainUri: Uri.parse('lib/foo.txt'),
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
|
||||
expect(report.syncedBytes, 22);
|
||||
@ -221,11 +223,12 @@ void main() {
|
||||
expect(devFS.assetPathsToEvict, isEmpty);
|
||||
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/foo.txt',
|
||||
mainUri: Uri.parse('lib/foo.txt'),
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
vmService.expectMessages(<String>[
|
||||
'writeFile test lib/foo.txt.dill',
|
||||
@ -284,17 +287,18 @@ void main() {
|
||||
any,
|
||||
any,
|
||||
outputPath: anyNamed('outputPath'),
|
||||
packagesFilePath: anyNamed('packagesFilePath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) {
|
||||
return Future<CompilerOutput>.value(const CompilerOutput('example', 2, <Uri>[]));
|
||||
});
|
||||
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/foo.txt',
|
||||
mainUri: Uri.parse('lib/foo.txt'),
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
|
||||
expect(report.success, false);
|
||||
@ -316,18 +320,19 @@ void main() {
|
||||
any,
|
||||
any,
|
||||
outputPath: anyNamed('outputPath'),
|
||||
packagesFilePath: anyNamed('packagesFilePath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) {
|
||||
fs.file('example').createSync();
|
||||
return Future<CompilerOutput>.value(CompilerOutput('example', 0, <Uri>[sourceFile.uri]));
|
||||
});
|
||||
|
||||
final UpdateFSReport report = await devFS.update(
|
||||
mainPath: 'lib/main.dart',
|
||||
mainUri: Uri.parse('lib/main.dart'),
|
||||
generator: residentCompiler,
|
||||
pathToReload: 'lib/foo.txt.dill',
|
||||
trackWidgetCreation: false,
|
||||
invalidatedFiles: <Uri>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
|
||||
expect(report.success, true);
|
||||
|
||||
@ -103,7 +103,7 @@ void main() {
|
||||
MockLocalEngineArtifacts mockArtifacts;
|
||||
|
||||
when(mockDevFs.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -115,6 +115,7 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation _) => Future<UpdateFSReport>.value(
|
||||
UpdateFSReport(success: true, syncedBytes: 1000, invalidatedSourcesCount: 1)));
|
||||
when(mockDevFs.assetPathsToEvict).thenReturn(<String>{});
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
const String packagesContents = r'''
|
||||
xml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/xml-3.2.3/lib/
|
||||
yaml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.15/lib/
|
||||
example:file:///example/lib/
|
||||
''';
|
||||
|
||||
const String multiRootPackagesContents = r'''
|
||||
xml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/xml-3.2.3/lib/
|
||||
yaml:file:///Users/flutter_user/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.15/lib/
|
||||
example:org-dartlang-app:/
|
||||
''';
|
||||
|
||||
void main() {
|
||||
MockFileSystem mockFileSystem;
|
||||
MockFile mockFile;
|
||||
|
||||
setUp(() {
|
||||
mockFileSystem = MockFileSystem();
|
||||
mockFile = MockFile();
|
||||
when(mockFileSystem.path).thenReturn(globals.fs.path);
|
||||
when(mockFileSystem.file(any)).thenReturn(mockFile);
|
||||
when(mockFile.readAsBytesSync()).thenReturn(utf8.encode(packagesContents) as Uint8List);
|
||||
});
|
||||
|
||||
testUsingContext('Can map main.dart to correct package', () async {
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
|
||||
expect(packageUriMapper.map('/example/lib/main.dart').toString(),
|
||||
'package:example/main.dart');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => mockFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('single-root maps file from other package to null', () async {
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
|
||||
expect(packageUriMapper.map('/xml/lib/xml.dart'), null);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => mockFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('single-root maps non-main file from same package', () async {
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper('/example/lib/main.dart', '.packages', null, null);
|
||||
expect(packageUriMapper.map('/example/lib/src/foo.dart').toString(),
|
||||
'package:example/src/foo.dart');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => mockFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
|
||||
testUsingContext('multi-root maps main file from same package on multiroot scheme', () async {
|
||||
final MockFileSystem mockFileSystem = MockFileSystem();
|
||||
final MockFile mockFile = MockFile();
|
||||
when(mockFileSystem.path).thenReturn(globals.fs.path);
|
||||
when(mockFileSystem.file(any)).thenReturn(mockFile);
|
||||
when(mockFile.readAsBytesSync())
|
||||
.thenReturn(utf8.encode(multiRootPackagesContents) as Uint8List);
|
||||
final PackageUriMapper packageUriMapper = PackageUriMapper(
|
||||
'/example/lib/main.dart',
|
||||
'.packages',
|
||||
'org-dartlang-app',
|
||||
<String>['/example/lib/', '/gen/lib/']);
|
||||
expect(packageUriMapper.map('/example/lib/main.dart').toString(),
|
||||
'package:example/main.dart');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => mockFileSystem,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
});
|
||||
}
|
||||
|
||||
class MockFileSystem extends Mock implements FileSystem {}
|
||||
class MockFile extends Mock implements File {}
|
||||
@ -3,84 +3,123 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/terminal.dart';
|
||||
import 'package:flutter_tools/src/run_hot.dart';
|
||||
import 'package:package_config/package_config.dart';
|
||||
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/mocks.dart';
|
||||
|
||||
// assumption: tests have a timeout less than 100 days
|
||||
final DateTime inFuture = DateTime.now().add(const Duration(days: 100));
|
||||
|
||||
void main() {
|
||||
BufferLogger bufferLogger;
|
||||
|
||||
setUp(() {
|
||||
bufferLogger = BufferLogger(
|
||||
terminal: AnsiTerminal(
|
||||
stdio: MockStdio(),
|
||||
platform: FakePlatform(),
|
||||
),
|
||||
outputPreferences: OutputPreferences.test(),
|
||||
);
|
||||
});
|
||||
|
||||
for (final bool asyncScanning in <bool>[true, false]) {
|
||||
testWithoutContext('No last compile, asyncScanning: $asyncScanning', () async {
|
||||
final FileSystem fileSystem = MemoryFileSystem();
|
||||
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
|
||||
fileSystem: MemoryFileSystem(),
|
||||
fileSystem: fileSystem,
|
||||
platform: FakePlatform(),
|
||||
logger: bufferLogger,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
fileSystem.file('.packages').writeAsStringSync('\n');
|
||||
|
||||
expect(
|
||||
await projectFileInvalidator.findInvalidated(
|
||||
(await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: null,
|
||||
urisToMonitor: <Uri>[],
|
||||
packagesPath: '',
|
||||
packagesPath: '.packages',
|
||||
asyncScanning: asyncScanning,
|
||||
),
|
||||
packageConfig: PackageConfig.empty,
|
||||
)).uris,
|
||||
isEmpty,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('Empty project, asyncScanning: $asyncScanning', () async {
|
||||
final FileSystem fileSystem = MemoryFileSystem();
|
||||
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
|
||||
fileSystem: MemoryFileSystem(),
|
||||
fileSystem: fileSystem,
|
||||
platform: FakePlatform(),
|
||||
logger: bufferLogger,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
fileSystem.file('.packages').writeAsStringSync('\n');
|
||||
|
||||
expect(
|
||||
await projectFileInvalidator.findInvalidated(
|
||||
(await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: inFuture,
|
||||
urisToMonitor: <Uri>[],
|
||||
packagesPath: '',
|
||||
packagesPath: '.packages',
|
||||
asyncScanning: asyncScanning,
|
||||
),
|
||||
packageConfig: PackageConfig.empty,
|
||||
)).uris,
|
||||
isEmpty,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('Non-existent files are ignored, asyncScanning: $asyncScanning', () async {
|
||||
final FileSystem fileSystem = MemoryFileSystem();
|
||||
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
|
||||
fileSystem: MemoryFileSystem(),
|
||||
platform: FakePlatform(),
|
||||
logger: bufferLogger,
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
fileSystem.file('.packages').writeAsStringSync('\n');
|
||||
|
||||
expect(
|
||||
await projectFileInvalidator.findInvalidated(
|
||||
(await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: inFuture,
|
||||
urisToMonitor: <Uri>[Uri.parse('/not-there-anymore'),],
|
||||
packagesPath: '',
|
||||
packagesPath: '.packages',
|
||||
asyncScanning: asyncScanning,
|
||||
),
|
||||
packageConfig: PackageConfig.empty,
|
||||
)).uris,
|
||||
isEmpty,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('Picks up changes to the .packages file and updates PackageConfig'
|
||||
', asyncScanning: $asyncScanning', () async {
|
||||
final FileSystem fileSystem = MemoryFileSystem.test();
|
||||
final PackageConfig packageConfig = PackageConfig.empty;
|
||||
final ProjectFileInvalidator projectFileInvalidator = ProjectFileInvalidator(
|
||||
fileSystem: fileSystem,
|
||||
platform: FakePlatform(),
|
||||
logger: BufferLogger.test(),
|
||||
);
|
||||
fileSystem.file('.packages')
|
||||
.writeAsStringSync('\n');
|
||||
|
||||
final InvalidationResult invalidationResult = await projectFileInvalidator.findInvalidated(
|
||||
lastCompiled: null,
|
||||
urisToMonitor: <Uri>[],
|
||||
packagesPath: '.packages',
|
||||
asyncScanning: asyncScanning,
|
||||
packageConfig: packageConfig,
|
||||
);
|
||||
|
||||
expect(invalidationResult.packageConfig, isNot(packageConfig));
|
||||
|
||||
fileSystem.file('.packages')
|
||||
.writeAsStringSync('foo:lib/\n');
|
||||
final DateTime packagesUpdated = fileSystem.statSync('.packages')
|
||||
.modified;
|
||||
|
||||
final InvalidationResult nextInvalidationResult = await projectFileInvalidator
|
||||
.findInvalidated(
|
||||
lastCompiled: packagesUpdated.subtract(const Duration(seconds: 1)),
|
||||
urisToMonitor: <Uri>[],
|
||||
packagesPath: '.packages',
|
||||
asyncScanning: asyncScanning,
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
|
||||
expect(nextInvalidationResult.uris, contains(Uri.parse('.packages')));
|
||||
// The PackagConfig should have been recreated too
|
||||
expect(nextInvalidationResult.packageConfig,
|
||||
isNot(invalidationResult.packageConfig));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ void main() {
|
||||
|
||||
setUp(() {
|
||||
testbed = Testbed(setup: () {
|
||||
globals.fs.file('.packages').writeAsStringSync('\n');
|
||||
globals.fs.file(globals.fs.path.join('build', 'app.dill'))
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync('ABC');
|
||||
@ -69,9 +70,8 @@ void main() {
|
||||
when(mockDevFS.assetPathsToEvict).thenReturn(<String>{});
|
||||
// FlutterDevice Mocks.
|
||||
when(mockFlutterDevice.updateDevFS(
|
||||
// Intentionally provide empty list to match above mock.
|
||||
invalidatedFiles: <Uri>[],
|
||||
mainPath: anyNamed('mainPath'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -81,6 +81,7 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
dillOutputPath: anyNamed('dillOutputPath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return UpdateFSReport(
|
||||
success: true,
|
||||
@ -225,7 +226,7 @@ void main() {
|
||||
));
|
||||
await onAppStart.future;
|
||||
when(mockFlutterDevice.updateDevFS(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -236,6 +237,7 @@ void main() {
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
dillOutputPath: anyNamed('dillOutputPath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
|
||||
|
||||
final OperationResult result = await residentRunner.restart(fullRestart: false);
|
||||
@ -330,7 +332,7 @@ void main() {
|
||||
));
|
||||
await onAppStart.future;
|
||||
when(mockFlutterDevice.updateDevFS(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -341,6 +343,7 @@ void main() {
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
dillOutputPath: anyNamed('dillOutputPath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenThrow(vm_service.RPCError('something bad happened', 666, ''));
|
||||
|
||||
final OperationResult result = await residentRunner.restart(fullRestart: true);
|
||||
|
||||
@ -94,7 +94,7 @@ void main() {
|
||||
globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
|
||||
globals.fs.file(globals.fs.path.join('web', 'index.html')).createSync(recursive: true);
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -106,6 +106,7 @@ void main() {
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
trackWidgetCreation: true,
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation _) async {
|
||||
return UpdateFSReport(success: true, syncedBytes: 0)..invalidatedModules = <String>[];
|
||||
});
|
||||
@ -313,7 +314,7 @@ void main() {
|
||||
_setupMocks();
|
||||
launchChromeInstance(mockChrome);
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -325,9 +326,10 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
// Generated entrypoint file in temp dir.
|
||||
expect(invocation.namedArguments[#mainPath], contains('entrypoint.dart'));
|
||||
expect(invocation.namedArguments[#mainUri].toString(), contains('entrypoint.dart'));
|
||||
return UpdateFSReport(success: true)
|
||||
..invalidatedModules = <String>['example'];
|
||||
});
|
||||
@ -362,9 +364,9 @@ void main() {
|
||||
test('Can hot restart after attaching', () => testbed.run(() async {
|
||||
_setupMocks();
|
||||
launchChromeInstance(mockChrome);
|
||||
String entrypointFileName;
|
||||
Uri entrypointFileUri;
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -376,8 +378,9 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
entrypointFileName = invocation.namedArguments[#mainPath] as String;
|
||||
entrypointFileUri = invocation.namedArguments[#mainUri] as Uri;
|
||||
return UpdateFSReport(success: true)
|
||||
..invalidatedModules = <String>['example'];
|
||||
});
|
||||
@ -389,8 +392,8 @@ void main() {
|
||||
final OperationResult result = await residentWebRunner.restart(fullRestart: true);
|
||||
|
||||
// Ensure that generated entrypoint is generated correctly.
|
||||
expect(entrypointFileName, isNotNull);
|
||||
final String entrypointContents = globals.fs.file(entrypointFileName).readAsStringSync();
|
||||
expect(entrypointFileUri, isNotNull);
|
||||
final String entrypointContents = globals.fs.file(entrypointFileUri).readAsStringSync();
|
||||
expect(entrypointContents, contains('// Flutter web bootstrap script'));
|
||||
expect(entrypointContents, contains("import 'dart:ui' as ui;"));
|
||||
expect(entrypointContents, contains('await ui.webOnlyInitializePlatform();'));
|
||||
@ -417,7 +420,7 @@ void main() {
|
||||
_setupMocks();
|
||||
when(mockFlutterDevice.device).thenReturn(mockWebServerDevice);
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -429,6 +432,7 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return UpdateFSReport(success: true)
|
||||
..invalidatedModules = <String>['example'];
|
||||
@ -469,7 +473,7 @@ void main() {
|
||||
test('Exits when initial compile fails', () => testbed.run(() async {
|
||||
_setupMocks();
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -480,6 +484,7 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
trackWidgetCreation: true,
|
||||
)).thenAnswer((Invocation _) async {
|
||||
return UpdateFSReport(success: false, syncedBytes: 0)..invalidatedModules = <String>[];
|
||||
@ -527,7 +532,7 @@ void main() {
|
||||
));
|
||||
await connectionInfoCompleter.future;
|
||||
when(mockWebDevFS.update(
|
||||
mainPath: anyNamed('mainPath'),
|
||||
mainUri: anyNamed('mainUri'),
|
||||
target: anyNamed('target'),
|
||||
bundle: anyNamed('bundle'),
|
||||
firstBuildTime: anyNamed('firstBuildTime'),
|
||||
@ -538,6 +543,7 @@ void main() {
|
||||
projectRootPath: anyNamed('projectRootPath'),
|
||||
pathToReload: anyNamed('pathToReload'),
|
||||
invalidatedFiles: anyNamed('invalidatedFiles'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
trackWidgetCreation: true,
|
||||
)).thenAnswer((Invocation _) async {
|
||||
return UpdateFSReport(success: false, syncedBytes: 0)..invalidatedModules = <String>[];
|
||||
|
||||
@ -2,16 +2,23 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:file_testing/file_testing.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/compile.dart';
|
||||
import 'package:flutter_tools/src/project.dart';
|
||||
import 'package:flutter_tools/src/test/test_compiler.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/testbed.dart';
|
||||
|
||||
final Platform linuxPlatform = FakePlatform(
|
||||
operatingSystem: 'linux',
|
||||
environment: <String, String>{},
|
||||
);
|
||||
|
||||
void main() {
|
||||
group(TestCompiler, () {
|
||||
Testbed testbed;
|
||||
@ -20,6 +27,9 @@ void main() {
|
||||
|
||||
setUp(() {
|
||||
testbed = Testbed(
|
||||
overrides: <Type, Generator>{
|
||||
Platform: () => linuxPlatform,
|
||||
},
|
||||
setup: () async {
|
||||
globals.fs.file('pubspec.yaml').createSync();
|
||||
globals.fs.file('.packages').createSync();
|
||||
@ -37,37 +47,42 @@ void main() {
|
||||
|
||||
test('Reports a dill file when compile is successful', () => testbed.run(() async {
|
||||
when(residentCompiler.recompile(
|
||||
'test/foo.dart',
|
||||
any,
|
||||
<Uri>[Uri.parse('test/foo.dart')],
|
||||
outputPath: testCompiler.outputDill.path,
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
globals.fs.file('abc.dill').createSync();
|
||||
return const CompilerOutput('abc.dill', 0, <Uri>[]);
|
||||
});
|
||||
|
||||
expect(await testCompiler.compile('test/foo.dart'), 'test/foo.dart.dill');
|
||||
expect(globals.fs.file('test/foo.dart.dill').existsSync(), true);
|
||||
expect(await testCompiler.compile(Uri.parse('test/foo.dart')), 'test/foo.dart.dill');
|
||||
expect(globals.fs.file('test/foo.dart.dill'), exists);
|
||||
}));
|
||||
|
||||
test('Reports null when a compile fails', () => testbed.run(() async {
|
||||
when(residentCompiler.recompile(
|
||||
'test/foo.dart',
|
||||
any,
|
||||
<Uri>[Uri.parse('test/foo.dart')],
|
||||
outputPath: testCompiler.outputDill.path,
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
globals.fs.file('abc.dill').createSync();
|
||||
return const CompilerOutput('abc.dill', 1, <Uri>[]);
|
||||
});
|
||||
|
||||
expect(await testCompiler.compile('test/foo.dart'), null);
|
||||
expect(globals.fs.file('test/foo.dart.dill').existsSync(), false);
|
||||
expect(await testCompiler.compile(Uri.parse('test/foo.dart')), null);
|
||||
expect(globals.fs.file('test/foo.dart.dill'), isNot(exists));
|
||||
verify(residentCompiler.shutdown()).called(1);
|
||||
}));
|
||||
|
||||
test('Disposing test compiler shuts down backing compiler', () => testbed.run(() async {
|
||||
testCompiler.compiler = residentCompiler;
|
||||
|
||||
expect(testCompiler.compilerController.isClosed, false);
|
||||
|
||||
await testCompiler.dispose();
|
||||
|
||||
expect(testCompiler.compilerController.isClosed, true);
|
||||
verify(residentCompiler.shutdown()).called(1);
|
||||
}));
|
||||
|
||||
@ -360,7 +360,7 @@ void main() {
|
||||
any,
|
||||
any,
|
||||
outputPath: anyNamed('outputPath'),
|
||||
packagesFilePath: anyNamed('packagesFilePath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return const CompilerOutput('a', 0, <Uri>[]);
|
||||
});
|
||||
@ -402,11 +402,12 @@ void main() {
|
||||
webDevFS.webAssetServer.dartSdkSourcemap.createSync(recursive: true);
|
||||
|
||||
await webDevFS.update(
|
||||
mainPath: globals.fs.path.join('lib', 'main.dart'),
|
||||
mainUri: globals.fs.file(globals.fs.path.join('lib', 'main.dart')).uri,
|
||||
generator: residentCompiler,
|
||||
trackWidgetCreation: true,
|
||||
bundleFirstUpload: true,
|
||||
invalidatedFiles: <Uri>[],
|
||||
packageConfig: PackageConfig.empty,
|
||||
);
|
||||
|
||||
expect(webDevFS.webAssetServer.getFile('require.js'), isNotNull);
|
||||
@ -452,7 +453,7 @@ void main() {
|
||||
any,
|
||||
any,
|
||||
outputPath: anyNamed('outputPath'),
|
||||
packagesFilePath: anyNamed('packagesFilePath'),
|
||||
packageConfig: anyNamed('packageConfig'),
|
||||
)).thenAnswer((Invocation invocation) async {
|
||||
return const CompilerOutput('a', 0, <Uri>[]);
|
||||
});
|
||||
|
||||
@ -6,6 +6,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' as io show IOSink, ProcessSignal, Stdout, StdoutException;
|
||||
|
||||
import 'package:package_config/package_config.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
import 'package:flutter_tools/src/android/android_device.dart';
|
||||
@ -662,7 +663,7 @@ class MockResidentCompiler extends BasicMock implements ResidentCompiler {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompilerOutput> recompile(String mainPath, List<Uri> invalidatedFiles, { String outputPath, String packagesFilePath }) async {
|
||||
Future<CompilerOutput> recompile(Uri mainPath, List<Uri> invalidatedFiles, { String outputPath, PackageConfig packageConfig }) async {
|
||||
globals.fs.file(outputPath).createSync(recursive: true);
|
||||
globals.fs.file(outputPath).writeAsStringSync('compiled_kernel_output');
|
||||
return CompilerOutput(outputPath, 0, <Uri>[]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user