diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart index 1b43e00f5d8..452550897da 100644 --- a/pkg/analyzer/lib/source/embedder.dart +++ b/pkg/analyzer/lib/source/embedder.dart @@ -10,14 +10,13 @@ import 'dart:core' hide Resource; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/source/package_map_provider.dart' show PackageMapProvider; -import 'package:analyzer/src/context/context.dart'; -import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/java_core.dart'; -import 'package:analyzer/src/generated/java_engine.dart'; import 'package:analyzer/src/generated/java_io.dart' show JavaFile; import 'package:analyzer/src/generated/sdk.dart'; +import 'package:analyzer/src/generated/sdk_io.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource; +import 'package:analyzer/src/summary/idl.dart'; import 'package:yaml/yaml.dart'; const String _DART_COLON_PREFIX = 'dart:'; @@ -27,104 +26,28 @@ const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs'; bool definesEmbeddedLibs(Map map) => map[_EMBEDDED_LIB_MAP_KEY] != null; /// An SDK backed by URI mappings derived from an `_embedder.yaml` file. -class EmbedderSdk implements DartSdk { - /// The resolver associated with this SDK. - EmbedderUriResolver _resolver; - - /// The [AnalysisContext] used for this SDK's sources. - InternalAnalysisContext _analysisContext; - - final LibraryMap _librariesMap = new LibraryMap(); - +class EmbedderSdk extends AbstractDartSdk { final Map _urlMappings = new HashMap(); - /// Analysis options for this SDK. - AnalysisOptions analysisOptions; - EmbedderSdk([Map embedderYamls]) { embedderYamls?.forEach(_processEmbedderYaml); - _resolver = new EmbedderUriResolver._forSdk(this); } - @override - AnalysisContext get context { - if (_analysisContext == null) { - _analysisContext = new SdkAnalysisContext(analysisOptions); - SourceFactory factory = new SourceFactory([_resolver]); - _analysisContext.sourceFactory = factory; - - ChangeSet changeSet = new ChangeSet(); - for (String uri in uris) { - changeSet.addedSource(factory.forUri(uri)); - } - _analysisContext.applyChanges(changeSet); - } - return _analysisContext; - } - - @override - List get sdkLibraries => _librariesMap.sdkLibraries; - // TODO(danrubel) Determine SDK version @override String get sdkVersion => '0'; - @override - List get uris => _librariesMap.uris; - /// The url mappings for this SDK. Map get urlMappings => _urlMappings; @override - Source fromFileUri(Uri uri) { - JavaFile file = new JavaFile.fromUri(uri); - String filePath = file.getAbsolutePath(); - - String path; - for (SdkLibrary library in _librariesMap.sdkLibraries) { - String libraryPath = library.path.replaceAll('/', JavaFile.separator); - if (filePath == libraryPath) { - path = library.shortName; - break; - } - } - if (path == null) { - for (SdkLibrary library in _librariesMap.sdkLibraries) { - String libraryPath = library.path.replaceAll('/', JavaFile.separator); - int index = libraryPath.lastIndexOf(JavaFile.separator); - if (index == -1) { - continue; - } - String prefix = libraryPath.substring(0, index + 1); - if (!filePath.startsWith(prefix)) { - continue; - } - var relPath = filePath - .substring(prefix.length) - .replaceAll(JavaFile.separator, '/'); - path = '${library.shortName}/$relPath'; - break; - } - } - - if (path != null) { - try { - return new FileBasedSource(file, parseUriWithException(path)); - } on URISyntaxException catch (exception, stackTrace) { - AnalysisEngine.instance.logger.logInformation( - "Failed to create URI: $path", - new CaughtException(exception, stackTrace)); - return null; - } - } - return null; - } + String getRelativePathFromFile(JavaFile file) => file.getAbsolutePath(); @override - SdkLibrary getSdkLibrary(String dartUri) => _librariesMap.getLibrary(dartUri); + PackageBundle getSummarySdkBundle(bool strongMode) => null; @override - Source mapDartUri(String dartUri) { + FileBasedSource internalMapDartUri(String dartUri) { String libraryName; String relativePath; int index = dartUri.indexOf('/'); @@ -173,7 +96,7 @@ class EmbedderSdk implements DartSdk { _urlMappings[name] = libPath; SdkLibraryImpl library = new SdkLibraryImpl(name); library.path = libPath; - _librariesMap.setLibrary(name, library); + libraryMap.setLibrary(name, library); } /// Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the @@ -211,8 +134,8 @@ class EmbedderUriResolver implements DartUriResolver { /// Construct a [EmbedderUriResolver] from a package map /// (see [PackageMapProvider]). - EmbedderUriResolver(Map embedderMap) : - this._forSdk(new EmbedderSdk(embedderMap)); + EmbedderUriResolver(Map embedderMap) + : this._forSdk(new EmbedderSdk(embedderMap)); /// (Provisional API.) EmbedderUriResolver._forSdk(this._embedderSdk) { diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart index 0d053f6b1f2..be7c27a6a4b 100644 --- a/pkg/analyzer/lib/src/generated/sdk_io.dart +++ b/pkg/analyzer/lib/src/generated/sdk_io.dart @@ -24,6 +24,205 @@ import 'package:analyzer/src/summary/idl.dart' show PackageBundle; import 'package:analyzer/src/summary/summary_sdk.dart'; import 'package:path/path.dart' as pathos; +/** + * An abstract implementation of a Dart SDK in which the available libraries are + * stored in a library map. Subclasses are responsible for populating the + * library map. + */ +abstract class AbstractDartSdk implements DartSdk { + /** + * A mapping from Dart library URI's to the library represented by that URI. + */ + LibraryMap libraryMap = new LibraryMap(); + + /** + * The [AnalysisOptions] to use to create the [context]. + */ + AnalysisOptions _analysisOptions; + + /** + * The flag that specifies whether an SDK summary should be used. This is a + * temporary flag until summaries are enabled by default. + */ + bool _useSummary = false; + + /** + * The [AnalysisContext] which is used for all of the sources in this SDK. + */ + InternalAnalysisContext _analysisContext; + + /** + * The mapping from Dart URI's to the corresponding sources. + */ + Map _uriToSourceMap = new HashMap(); + + /** + * Set the [options] for this SDK analysis context. Throw [StateError] if the + * context has been already created. + */ + void set analysisOptions(AnalysisOptions options) { + if (_analysisContext != null) { + throw new StateError( + 'Analysis options cannot be changed after context creation.'); + } + _analysisOptions = options; + } + + @override + AnalysisContext get context { + if (_analysisContext == null) { + _analysisContext = new SdkAnalysisContext(_analysisOptions); + SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); + _analysisContext.sourceFactory = factory; + if (_useSummary) { + bool strongMode = _analysisOptions?.strongMode ?? false; + PackageBundle sdkBundle = getSummarySdkBundle(strongMode); + if (sdkBundle != null) { + _analysisContext.resultProvider = new SdkSummaryResultProvider( + _analysisContext, sdkBundle, strongMode); + } + } + } + return _analysisContext; + } + + @override + List get sdkLibraries => libraryMap.sdkLibraries; + + @override + List get uris => libraryMap.uris; + + /** + * Return `true` if the SDK summary will be used when available. + */ + bool get useSummary => _useSummary; + + /** + * Specify whether SDK summary should be used. + */ + void set useSummary(bool use) { + if (_analysisContext != null) { + throw new StateError( + 'The "useSummary" flag cannot be changed after context creation.'); + } + _useSummary = use; + } + + @override + Source fromFileUri(Uri uri) { + JavaFile file = new JavaFile.fromUri(uri); + + String path = _getPath(file); + if (path == null) { + return null; + } + try { + return new FileBasedSource(file, parseUriWithException(path)); + } on URISyntaxException catch (exception, stackTrace) { + AnalysisEngine.instance.logger.logInformation( + "Failed to create URI: $path", + new CaughtException(exception, stackTrace)); + } + return null; + } + + String getRelativePathFromFile(JavaFile file); + + @override + SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri); + + /** + * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. + * This method should not be used outside of `analyzer` and `analyzer_cli` + * packages. + */ + PackageBundle getSummarySdkBundle(bool strongMode); + + FileBasedSource internalMapDartUri(String dartUri) { + // TODO(brianwilkerson) Figure out how to unify the implementations in the + // two subclasses. + String libraryName; + String relativePath; + int index = dartUri.indexOf('/'); + if (index >= 0) { + libraryName = dartUri.substring(0, index); + relativePath = dartUri.substring(index + 1); + } else { + libraryName = dartUri; + relativePath = ""; + } + SdkLibrary library = getSdkLibrary(libraryName); + if (library == null) { + return null; + } + String srcPath; + if (relativePath.isEmpty) { + srcPath = library.path; + } else { + String libraryPath = library.path; + int index = libraryPath.lastIndexOf(JavaFile.separator); + if (index == -1) { + index = libraryPath.lastIndexOf('/'); + if (index == -1) { + return null; + } + } + String prefix = libraryPath.substring(0, index + 1); + srcPath = '$prefix$relativePath'; + } + String filePath = srcPath.replaceAll('/', JavaFile.separator); + try { + JavaFile file = new JavaFile(filePath); + return new FileBasedSource(file, parseUriWithException(dartUri)); + } on URISyntaxException { + return null; + } + } + + @override + Source mapDartUri(String dartUri) { + Source source = _uriToSourceMap[dartUri]; + if (source == null) { + source = internalMapDartUri(dartUri); + _uriToSourceMap[dartUri] = source; + } + return source; + } + + String _getPath(JavaFile file) { + List libraries = libraryMap.sdkLibraries; + int length = libraries.length; + List paths = new List(length); + String filePath = getRelativePathFromFile(file); + if (filePath == null) { + return null; + } + for (int i = 0; i < length; i++) { + SdkLibrary library = libraries[i]; + String libraryPath = library.path.replaceAll('/', JavaFile.separator); + if (filePath == libraryPath) { + return library.shortName; + } + paths[i] = libraryPath; + } + for (int i = 0; i < length; i++) { + SdkLibrary library = libraries[i]; + String libraryPath = paths[i]; + int index = libraryPath.lastIndexOf(JavaFile.separator); + if (index >= 0) { + String prefix = libraryPath.substring(0, index + 1); + if (filePath.startsWith(prefix)) { + String relPath = filePath + .substring(prefix.length) + .replaceAll(JavaFile.separator, '/'); + return '${library.shortName}/$relPath'; + } + } + } + return null; + } +} + /** * A Dart SDK installed in a specified directory. Typical Dart SDK layout is * something like... @@ -40,7 +239,7 @@ import 'package:path/path.dart' as pathos; * ... Dart utilities ... * Chromium/ <-- Dartium typically exists in a sibling directory */ -class DirectoryBasedDartSdk implements DartSdk { +class DirectoryBasedDartSdk extends AbstractDartSdk { /** * The default SDK, or `null` if the default SDK either has not yet been * created or cannot be created for some reason. @@ -192,11 +391,6 @@ class DirectoryBasedDartSdk implements DartSdk { return sdkDirectory; } - /** - * The [AnalysisContext] which is used for all of the sources in this sdk. - */ - InternalAnalysisContext _analysisContext; - /** * The directory containing the SDK. */ @@ -207,11 +401,6 @@ class DirectoryBasedDartSdk implements DartSdk { */ JavaFile _libraryDirectory; - /** - * The flag that specifies whether SDK summary should be used. - */ - bool _useSummary = false; - /** * The revision number of this SDK, or `"0"` if the revision number cannot be * discovered. @@ -238,21 +427,6 @@ class DirectoryBasedDartSdk implements DartSdk { */ JavaFile _vmExecutable; - /** - * A mapping from Dart library URI's to the library represented by that URI. - */ - LibraryMap _libraryMap; - - /** - * The mapping from Dart URI's to the corresponding sources. - */ - Map _uriToSourceMap = new HashMap(); - - /** - * The [AnalysisOptions] to use to create the [context]. - */ - AnalysisOptions _analysisOptions; - /** * Initialize a newly created SDK to represent the Dart SDK installed in the * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path @@ -260,37 +434,7 @@ class DirectoryBasedDartSdk implements DartSdk { */ DirectoryBasedDartSdk(JavaFile sdkDirectory, [bool useDart2jsPaths = false]) { this._sdkDirectory = sdkDirectory.getAbsoluteFile(); - _libraryMap = initialLibraryMap(useDart2jsPaths); - } - - /** - * Set the [options] for this SDK analysis context. Throw [StateError] if the - * context has been already created. - */ - void set analysisOptions(AnalysisOptions options) { - if (_analysisContext != null) { - throw new StateError( - 'Analysis options cannot be changed after context creation.'); - } - _analysisOptions = options; - } - - @override - AnalysisContext get context { - if (_analysisContext == null) { - _analysisContext = new SdkAnalysisContext(_analysisOptions); - SourceFactory factory = new SourceFactory([new DartUriResolver(this)]); - _analysisContext.sourceFactory = factory; - if (_useSummary) { - PackageBundle sdkBundle = getSummarySdkBundle(); - if (sdkBundle != null) { - bool strongMode = _analysisOptions?.strongMode ?? false; - _analysisContext.resultProvider = new SdkSummaryResultProvider( - _analysisContext, sdkBundle, strongMode); - } - } - } - return _analysisContext; + libraryMap = initialLibraryMap(useDart2jsPaths); } /** @@ -386,9 +530,6 @@ class DirectoryBasedDartSdk implements DartSdk { return _pubExecutable; } - @override - List get sdkLibraries => _libraryMap.sdkLibraries; - /** * Return the revision number of this SDK, or `"0"` if the revision number * cannot be discovered. @@ -411,25 +552,6 @@ class DirectoryBasedDartSdk implements DartSdk { return _sdkVersion; } - @override - List get uris => _libraryMap.uris; - - /** - * Whether an SDK summary should be used. - */ - bool get useSummary => _useSummary; - - /** - * Specify whether SDK summary should be used. - */ - void set useSummary(bool use) { - if (_analysisContext != null) { - throw new StateError( - 'The "useSummary" flag cannot be changed after context creation.'); - } - _useSummary = use; - } - /** * Return the name of the file containing the VM executable. */ @@ -470,45 +592,6 @@ class DirectoryBasedDartSdk implements DartSdk { _LIBRARIES_FILE); } - @override - Source fromFileUri(Uri uri) { - JavaFile file = new JavaFile.fromUri(uri); - String filePath = file.getAbsolutePath(); - String libPath = libraryDirectory.getAbsolutePath(); - if (!filePath.startsWith("$libPath${JavaFile.separator}")) { - return null; - } - filePath = filePath.substring(libPath.length + 1); - for (SdkLibrary library in _libraryMap.sdkLibraries) { - String libraryPath = library.path; - if (filePath.replaceAll('\\', '/') == libraryPath) { - String path = library.shortName; - try { - return new FileBasedSource(file, parseUriWithException(path)); - } on URISyntaxException catch (exception, stackTrace) { - AnalysisEngine.instance.logger.logInformation( - "Failed to create URI: $path", - new CaughtException(exception, stackTrace)); - return null; - } - } - libraryPath = new JavaFile(library.path).getParent(); - if (filePath.startsWith("$libraryPath${JavaFile.separator}")) { - String path = - "${library.shortName}/${filePath.substring(libraryPath.length + 1)}"; - try { - return new FileBasedSource(file, parseUriWithException(path)); - } on URISyntaxException catch (exception, stackTrace) { - AnalysisEngine.instance.logger.logInformation( - "Failed to create URI: $path", - new CaughtException(exception, stackTrace)); - return null; - } - } - } - return null; - } - /** * Return the directory where dartium can be found (the directory that will be * the working directory if Dartium is invoked without changing the default), @@ -536,16 +619,22 @@ class DirectoryBasedDartSdk implements DartSdk { } @override - SdkLibrary getSdkLibrary(String dartUri) => _libraryMap.getLibrary(dartUri); + String getRelativePathFromFile(JavaFile file) { + String filePath = file.getAbsolutePath(); + String libPath = libraryDirectory.getAbsolutePath(); + if (!filePath.startsWith("$libPath${JavaFile.separator}")) { + return null; + } + return filePath.substring(libPath.length + 1); + } /** * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise. * This method should not be used outside of `analyzer` and `analyzer_cli` * packages. */ - PackageBundle getSummarySdkBundle() { + PackageBundle getSummarySdkBundle(bool strongMode) { String rootPath = directory.getAbsolutePath(); - bool strongMode = _analysisOptions?.strongMode ?? false; String name = strongMode ? 'strong.sum' : 'spec.sum'; String path = pathos.join(rootPath, 'lib', '_internal', name); try { @@ -589,16 +678,7 @@ class DirectoryBasedDartSdk implements DartSdk { } @override - Source mapDartUri(String dartUri) { - Source source = _uriToSourceMap[dartUri]; - if (source == null) { - source = _mapDartUri(dartUri); - _uriToSourceMap[dartUri] = source; - } - return source; - } - - FileBasedSource _mapDartUri(String dartUri) { + FileBasedSource internalMapDartUri(String dartUri) { String libraryName; String relativePath; int index = dartUri.indexOf('/'); diff --git a/pkg/analyzer/test/source/embedder_test.dart b/pkg/analyzer/test/source/embedder_test.dart index 80072b8e56c..c16e6f9765a 100644 --- a/pkg/analyzer/test/source/embedder_test.dart +++ b/pkg/analyzer/test/source/embedder_test.dart @@ -9,149 +9,59 @@ import 'dart:core' hide Resource; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:analyzer/source/embedder.dart'; +import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:path/path.dart' as path; import 'package:unittest/unittest.dart'; +import '../reflective_tests.dart'; import '../resource_utils.dart'; import '../utils.dart'; main() { - group('EmbedderUriResolverTest', () { - setUp(() { - initializeTestEnvironment(path.context); - buildResourceProvider(); - }); - tearDown(() { - initializeTestEnvironment(); - clearResourceProvider(); - }); - test('test_NullEmbedderYamls', () { - var resolver = new EmbedderUriResolver(null); - expect(resolver.length, 0); - }); - test('test_NoEmbedderYamls', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/empty')] - }); - expect(locator.embedderYamls.length, 0); - }); - test('test_EmbedderYaml', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/tmp')] - }); - var resolver = new EmbedderUriResolver(locator.embedderYamls); - - expectResolved(dartUri, posixPath) { - Source source = resolver.resolveAbsolute(Uri.parse(dartUri)); - expect(source, isNotNull, reason: dartUri); - expect(source.fullName, posixToOSPath(posixPath)); - } - - // We have five mappings. - expect(resolver.length, 5); - // Check that they map to the correct paths. - expectResolved('dart:core', '/tmp/core.dart'); - expectResolved('dart:fox', '/tmp/slippy.dart'); - expectResolved('dart:bear', '/tmp/grizzly.dart'); - expectResolved('dart:relative', '/relative.dart'); - expectResolved('dart:deep', '/tmp/deep/directory/file.dart'); - }); - test('test_BadYAML', () { - var locator = new EmbedderYamlLocator(null); - locator.addEmbedderYaml(null, r'''{{{,{{}}},}}'''); - expect(locator.embedderYamls.length, 0); - }); - test('test_restoreAbsolute', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/tmp')] - }); - var resolver = new EmbedderUriResolver(locator.embedderYamls); - - expectRestore(String dartUri, [String expected]) { - var parsedUri = Uri.parse(dartUri); - var source = resolver.resolveAbsolute(parsedUri); - expect(source, isNotNull); - // Restore source's uri. - var restoreUri = resolver.restoreAbsolute(source); - expect(restoreUri, isNotNull, reason: dartUri); - // Verify that it is 'dart:fox'. - expect(restoreUri.toString(), expected ?? dartUri); - List split = (expected ?? dartUri).split(':'); - expect(restoreUri.scheme, split[0]); - expect(restoreUri.path, split[1]); - } - - expectRestore('dart:deep'); - expectRestore('dart:deep/file.dart', 'dart:deep'); - expectRestore('dart:deep/part.dart'); - expectRestore('dart:deep/deep/file.dart'); - }); - - test('test_EmbedderSdk_fromFileUri', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/tmp')] - }); - var resolver = new EmbedderUriResolver(locator.embedderYamls); - var sdk = resolver.dartSdk; - - expectSource(String posixPath, String dartUri) { - var uri = Uri.parse(posixToOSFileUri(posixPath)); - var source = sdk.fromFileUri(uri); - expect(source, isNotNull, reason: posixPath); - expect(source.uri.toString(), dartUri); - expect(source.fullName, posixToOSPath(posixPath)); - } - - expectSource('/tmp/slippy.dart', 'dart:fox'); - expectSource('/tmp/deep/directory/file.dart', 'dart:deep'); - expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart'); - }); - test('test_EmbedderSdk_getSdkLibrary', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/tmp')] - }); - var resolver = new EmbedderUriResolver(locator.embedderYamls); - var sdk = resolver.dartSdk; - var lib = sdk.getSdkLibrary('dart:fox'); - expect(lib, isNotNull); - expect(lib.path, posixToOSPath('/tmp/slippy.dart')); - expect(lib.shortName, 'dart:fox'); - }); - test('test_EmbedderSdk_mapDartUri', () { - var locator = new EmbedderYamlLocator({ - 'fox': [pathTranslator.getResource('/tmp')] - }); - var resolver = new EmbedderUriResolver(locator.embedderYamls); - var sdk = resolver.dartSdk; - - expectSource(String dartUri, String posixPath) { - var source = sdk.mapDartUri(dartUri); - expect(source, isNotNull, reason: posixPath); - expect(source.uri.toString(), dartUri); - expect(source.fullName, posixToOSPath(posixPath)); - } - - expectSource('dart:core', '/tmp/core.dart'); - expectSource('dart:fox', '/tmp/slippy.dart'); - expectSource('dart:deep', '/tmp/deep/directory/file.dart'); - expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart'); - }); - }); + runReflectiveTests(DartUriResolverTest); + runReflectiveTests(EmbedderSdkTest); + runReflectiveTests(EmbedderUriResolverTest); + runReflectiveTests(EmbedderYamlLocatorTest); } -TestPathTranslator pathTranslator; -ResourceProvider resourceProvider; +@reflectiveTest +class DartUriResolverTest extends EmbedderRelatedTest { + void test_embedderYaml() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls); + DartUriResolver resolver = new DartUriResolver(sdk); -buildResourceProvider() { - var rawProvider = new MemoryResourceProvider(isWindows: isWindows); - resourceProvider = new TestResourceProvider(rawProvider); - pathTranslator = new TestPathTranslator(rawProvider) - ..newFolder('/empty') - ..newFolder('/tmp') - ..newFile( - '/tmp/_embedder.yaml', - r''' + void expectResolved(dartUri, posixPath) { + Source source = resolver.resolveAbsolute(Uri.parse(dartUri)); + expect(source, isNotNull, reason: dartUri); + expect(source.fullName, posixToOSPath(posixPath)); + } + // Check that they map to the correct paths. + expectResolved('dart:core', '/tmp/core.dart'); + expectResolved('dart:fox', '/tmp/slippy.dart'); + expectResolved('dart:bear', '/tmp/grizzly.dart'); + expectResolved('dart:relative', '/relative.dart'); + expectResolved('dart:deep', '/tmp/deep/directory/file.dart'); + } +} + +abstract class EmbedderRelatedTest { + TestPathTranslator pathTranslator; + ResourceProvider resourceProvider; + + buildResourceProvider() { + MemoryResourceProvider rawProvider = + new MemoryResourceProvider(isWindows: isWindows); + resourceProvider = new TestResourceProvider(rawProvider); + pathTranslator = new TestPathTranslator(rawProvider) + ..newFolder('/empty') + ..newFolder('/tmp') + ..newFile( + '/tmp/_embedder.yaml', + r''' embedded_libs: "dart:core" : "core.dart" "dart:fox": "slippy.dart" @@ -160,9 +70,161 @@ embedded_libs: "dart:deep": "deep/directory/file.dart" "fart:loudly": "nomatter.dart" '''); + } + + clearResourceProvider() { + resourceProvider = null; + pathTranslator = null; + } + + void setUp() { + initializeTestEnvironment(path.context); + buildResourceProvider(); + } + + void tearDown() { + initializeTestEnvironment(); + clearResourceProvider(); + } } -clearResourceProvider() { - resourceProvider = null; - pathTranslator = null; +@reflectiveTest +class EmbedderSdkTest extends EmbedderRelatedTest { + void test_creation() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls); + + expect(sdk.urlMappings, hasLength(5)); + } + + void test_fromFileUri() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls); + + expectSource(String posixPath, String dartUri) { + Uri uri = Uri.parse(posixToOSFileUri(posixPath)); + Source source = sdk.fromFileUri(uri); + expect(source, isNotNull, reason: posixPath); + expect(source.uri.toString(), dartUri); + expect(source.fullName, posixToOSPath(posixPath)); + } + + expectSource('/tmp/slippy.dart', 'dart:fox'); + expectSource('/tmp/deep/directory/file.dart', 'dart:deep'); + expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart'); + } + + void test_getSdkLibrary() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls); + + SdkLibrary lib = sdk.getSdkLibrary('dart:fox'); + expect(lib, isNotNull); + expect(lib.path, posixToOSPath('/tmp/slippy.dart')); + expect(lib.shortName, 'dart:fox'); + } + + void test_mapDartUri() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + EmbedderSdk sdk = new EmbedderSdk(locator.embedderYamls); + + void expectSource(String dartUri, String posixPath) { + Source source = sdk.mapDartUri(dartUri); + expect(source, isNotNull, reason: posixPath); + expect(source.uri.toString(), dartUri); + expect(source.fullName, posixToOSPath(posixPath)); + } + + expectSource('dart:core', '/tmp/core.dart'); + expectSource('dart:fox', '/tmp/slippy.dart'); + expectSource('dart:deep', '/tmp/deep/directory/file.dart'); + expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart'); + } +} + +@reflectiveTest +class EmbedderUriResolverTest extends EmbedderRelatedTest { + void test_embedderYaml() { + var locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + var resolver = new EmbedderUriResolver(locator.embedderYamls); + + expectResolved(dartUri, posixPath) { + Source source = resolver.resolveAbsolute(Uri.parse(dartUri)); + expect(source, isNotNull, reason: dartUri); + expect(source.fullName, posixToOSPath(posixPath)); + } + + // We have five mappings. + expect(resolver, hasLength(5)); + // Check that they map to the correct paths. + expectResolved('dart:core', '/tmp/core.dart'); + expectResolved('dart:fox', '/tmp/slippy.dart'); + expectResolved('dart:bear', '/tmp/grizzly.dart'); + expectResolved('dart:relative', '/relative.dart'); + expectResolved('dart:deep', '/tmp/deep/directory/file.dart'); + } + + void test_nullEmbedderYamls() { + var resolver = new EmbedderUriResolver(null); + expect(resolver, hasLength(0)); + } + + void test_restoreAbsolute() { + var locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + var resolver = new EmbedderUriResolver(locator.embedderYamls); + + expectRestore(String dartUri, [String expected]) { + var parsedUri = Uri.parse(dartUri); + var source = resolver.resolveAbsolute(parsedUri); + expect(source, isNotNull); + // Restore source's uri. + var restoreUri = resolver.restoreAbsolute(source); + expect(restoreUri, isNotNull, reason: dartUri); + // Verify that it is 'dart:fox'. + expect(restoreUri.toString(), expected ?? dartUri); + List split = (expected ?? dartUri).split(':'); + expect(restoreUri.scheme, split[0]); + expect(restoreUri.path, split[1]); + } + + expectRestore('dart:deep'); + expectRestore('dart:deep/file.dart', 'dart:deep'); + expectRestore('dart:deep/part.dart'); + expectRestore('dart:deep/deep/file.dart'); + } +} + +@reflectiveTest +class EmbedderYamlLocatorTest extends EmbedderRelatedTest { + void test_empty() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/empty')] + }); + expect(locator.embedderYamls, hasLength(0)); + } + + void test_invalid() { + EmbedderYamlLocator locator = new EmbedderYamlLocator(null); + locator.addEmbedderYaml(null, r'''{{{,{{}}},}}'''); + expect(locator.embedderYamls, hasLength(0)); + } + + void test_valid() { + EmbedderYamlLocator locator = new EmbedderYamlLocator({ + 'fox': [pathTranslator.getResource('/tmp')] + }); + expect(locator.embedderYamls, hasLength(1)); + } } diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart index f6b3ddde3c7..879ec697879 100644 --- a/pkg/analyzer_cli/lib/src/build_mode.dart +++ b/pkg/analyzer_cli/lib/src/build_mode.dart @@ -257,7 +257,7 @@ class BuildMode { Driver.createAnalysisOptionsForCommandLineOptions(options); directorySdk.useSummary = !options.buildSummaryOnlyAst; sdk = directorySdk; - sdkBundle = directorySdk.getSummarySdkBundle(); + sdkBundle = directorySdk.getSummarySdkBundle(options.strongMode); } // In AST mode include SDK bundle to avoid parsing SDK sources.