| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.source.embedder; | 5 library analyzer.source.embedder; |
| 6 | 6 |
| 7 import 'dart:collection' show HashMap; | 7 import 'dart:collection' show HashMap; |
| 8 import 'dart:core' hide Resource; | 8 import 'dart:core' hide Resource; |
| 9 | 9 |
| 10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
| 11 import 'package:analyzer/src/context/context.dart'; | 11 import 'package:analyzer/src/context/context.dart'; |
| 12 import 'package:analyzer/src/generated/engine.dart'; | 12 import 'package:analyzer/src/generated/engine.dart'; |
| 13 import 'package:analyzer/src/generated/java_core.dart'; | 13 import 'package:analyzer/src/generated/java_core.dart'; |
| 14 import 'package:analyzer/src/generated/java_engine.dart'; | 14 import 'package:analyzer/src/generated/java_engine.dart'; |
| 15 import 'package:analyzer/src/generated/java_io.dart' show JavaFile; | 15 import 'package:analyzer/src/generated/java_io.dart' show JavaFile; |
| 16 import 'package:analyzer/src/generated/sdk.dart'; | 16 import 'package:analyzer/src/generated/sdk.dart'; |
| 17 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
| 18 import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource; | 18 import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource; |
| 19 import 'package:path/path.dart' as pathos; | |
| 20 import 'package:yaml/yaml.dart'; | 19 import 'package:yaml/yaml.dart'; |
| 21 | 20 |
| 22 const String _DART_COLON_PREFIX = 'dart:'; | 21 const String _DART_COLON_PREFIX = 'dart:'; |
| 23 | 22 |
| 24 /// Given a packageMap, check in each package's lib directory for the | 23 /// Given a packageMap, check in each package's lib directory for the |
| 25 /// existence of an `_embedder.yaml` file. If the file contains a top level | 24 /// existence of an `_embedder.yaml` file. If the file contains a top level |
| 26 /// YamlMap, it will be added to the [embedderYamls] map. | 25 /// YamlMap, it will be added to the [embedderYamls] map. |
| 27 class EmbedderYamlLocator { | 26 class EmbedderYamlLocator { |
| 28 static const String EMBEDDER_FILE_NAME = '_embedder.yaml'; | 27 static const String EMBEDDER_FILE_NAME = '_embedder.yaml'; |
| 29 | 28 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 /// 'dart:io': '../../sdk/io/io.dart' | 108 /// 'dart:io': '../../sdk/io/io.dart' |
| 110 /// | 109 /// |
| 111 /// If a key doesn't begin with `dart:` it is ignored. | 110 /// If a key doesn't begin with `dart:` it is ignored. |
| 112 /// | 111 /// |
| 113 class EmbedderUriResolver extends DartUriResolver { | 112 class EmbedderUriResolver extends DartUriResolver { |
| 114 final Map<String, String> _urlMappings = <String, String>{}; | 113 final Map<String, String> _urlMappings = <String, String>{}; |
| 115 | 114 |
| 116 /// Construct a [EmbedderUriResolver] from a package map | 115 /// Construct a [EmbedderUriResolver] from a package map |
| 117 /// (see [PackageMapProvider]). | 116 /// (see [PackageMapProvider]). |
| 118 EmbedderUriResolver(Map<Folder, YamlMap> embedderYamls) | 117 EmbedderUriResolver(Map<Folder, YamlMap> embedderYamls) |
| 119 : super(new _EmbedderSdk()) { | 118 : super(new EmbedderSdk()) { |
| 120 (dartSdk as _EmbedderSdk)._resolver = this; | 119 (dartSdk as EmbedderSdk)._resolver = this; |
| 121 if (embedderYamls == null) { | 120 if (embedderYamls == null) { |
| 122 return; | 121 return; |
| 123 } | 122 } |
| 124 embedderYamls.forEach(_processEmbedderYaml); | 123 embedderYamls.forEach(_processEmbedderYaml); |
| 125 } | 124 } |
| 126 | 125 |
| 127 void _processEmbedderYaml(Folder libDir, YamlMap map) { | 126 void _processEmbedderYaml(Folder libDir, YamlMap map) { |
| 128 YamlNode embedder_libs = map['embedder_libs']; | 127 YamlNode embedder_libs = map['embedder_libs']; |
| 129 if (embedder_libs == null) { | 128 if (embedder_libs == null) { |
| 130 return; | 129 return; |
| 131 } | 130 } |
| 132 if (embedder_libs is! YamlMap) { | 131 if (embedder_libs is! YamlMap) { |
| 133 return; | 132 return; |
| 134 } | 133 } |
| 135 (embedder_libs as YamlMap) | 134 (embedder_libs as YamlMap) |
| 136 .forEach((k, v) => _processEmbedderLibs(k, v, libDir)); | 135 .forEach((k, v) => _processEmbedderLibs(k, v, libDir)); |
| 137 } | 136 } |
| 138 | 137 |
| 139 /// Install the mapping from [name] to [libDir]/[file]. | 138 /// Install the mapping from [name] to [libDir]/[file]. |
| 140 void _processEmbedderLibs(String name, String file, Folder libDir) { | 139 void _processEmbedderLibs(String name, String file, Folder libDir) { |
| 141 if (!name.startsWith(_DART_COLON_PREFIX)) { | 140 if (!name.startsWith(_DART_COLON_PREFIX)) { |
| 142 // SDK libraries must begin with 'dart:'. | 141 // SDK libraries must begin with 'dart:'. |
| 143 // TODO(pquitslund): Notify developer that something is wrong with the | 142 // TODO(pquitslund): Notify developer that something is wrong with the |
| 144 // _embedder.yaml file in libDir. | 143 // _embedder.yaml file in libDir. |
| 145 return; | 144 return; |
| 146 } | 145 } |
| 147 String key = name; | 146 String libPath = libDir.canonicalizePath(file); |
| 148 String value = libDir.canonicalizePath(file); | 147 _urlMappings[name] = libPath; |
| 149 _urlMappings[key] = value; | |
| 150 String shortName = name.substring(_DART_COLON_PREFIX.length); | 148 String shortName = name.substring(_DART_COLON_PREFIX.length); |
| 151 SdkLibraryImpl library = new SdkLibraryImpl(shortName); | 149 SdkLibraryImpl library = new SdkLibraryImpl(shortName); |
| 152 library.path = value; | 150 library.path = libPath; |
| 153 (dartSdk as _EmbedderSdk)._librariesMap.setLibrary(name, library); | 151 (dartSdk as EmbedderSdk)._librariesMap.setLibrary(name, library); |
| 154 } | 152 } |
| 155 | 153 |
| 156 /// Number of embedder libraries. | 154 /// Number of embedder libraries. |
| 157 int get length => _urlMappings.length; | 155 int get length => _urlMappings.length; |
| 158 | 156 |
| 159 /// Return the path mapping for [libName] or null if there is none. | |
| 160 String operator [](String libName) => _urlMappings[libName]; | |
| 161 | |
| 162 @override | |
| 163 Source resolveAbsolute(Uri importUri, [Uri actualUri]) { | |
| 164 String libraryName = _libraryName(importUri); | |
| 165 String partPath = _partPath(importUri); | |
| 166 // Lookup library name in mappings. | |
| 167 String mapping = _urlMappings[libraryName]; | |
| 168 if (mapping == null) { | |
| 169 // Not found. | |
| 170 return null; | |
| 171 } | |
| 172 // This mapping points to the main entry file of the dart: library. | |
| 173 Uri libraryEntry = new Uri.file(mapping); | |
| 174 if (!libraryEntry.isAbsolute) { | |
| 175 // We expect an absolute path. | |
| 176 return null; | |
| 177 } | |
| 178 | |
| 179 if (partPath != null) { | |
| 180 return _resolvePart(libraryEntry, partPath, importUri); | |
| 181 } else { | |
| 182 return _resolveEntry(libraryEntry, importUri); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 @override | 157 @override |
| 187 Uri restoreAbsolute(Source source) { | 158 Uri restoreAbsolute(Source source) { |
| 188 String extensionName = _findExtensionNameFor(source.fullName); | 159 Source sdkSource = dartSdk.fromFileUri(Uri.parse(source.fullName)); |
| 189 if (extensionName != null) { | 160 return sdkSource?.uri; |
| 190 return Uri.parse(extensionName); | |
| 191 } | |
| 192 // TODO(johnmccutchan): Handle restoring parts. | |
| 193 return null; | |
| 194 } | |
| 195 | |
| 196 /// Return the extension name for [fullName] or `null`. | |
| 197 String _findExtensionNameFor(String fullName) { | |
| 198 String result; | |
| 199 _urlMappings.forEach((extensionName, pathMapping) { | |
| 200 if (pathMapping == fullName) { | |
| 201 result = extensionName; | |
| 202 } | |
| 203 }); | |
| 204 return result; | |
| 205 } | |
| 206 | |
| 207 /// Return the library name of [importUri]. | |
| 208 String _libraryName(Uri importUri) { | |
| 209 String uri = importUri.toString(); | |
| 210 int index = uri.indexOf('/'); | |
| 211 if (index >= 0) { | |
| 212 return uri.substring(0, index); | |
| 213 } | |
| 214 return uri; | |
| 215 } | |
| 216 | |
| 217 /// Return the part path of [importUri]. | |
| 218 String _partPath(Uri importUri) { | |
| 219 String uri = importUri.toString(); | |
| 220 int index = uri.indexOf('/'); | |
| 221 if (index >= 0) { | |
| 222 return uri.substring(index + 1); | |
| 223 } | |
| 224 return null; | |
| 225 } | |
| 226 | |
| 227 /// Resolve an import of an sdk extension. | |
| 228 Source _resolveEntry(Uri libraryEntry, Uri importUri) { | |
| 229 // Library entry. | |
| 230 JavaFile javaFile = new JavaFile.fromUri(libraryEntry); | |
| 231 return new FileBasedSource(javaFile, importUri); | |
| 232 } | |
| 233 | |
| 234 /// Resolve a 'part' statement inside an sdk extension. | |
| 235 Source _resolvePart(Uri libraryEntry, String partPath, Uri importUri) { | |
| 236 // Library part. | |
| 237 String directory = pathos.dirname(libraryEntry.path); | |
| 238 Uri partUri = new Uri.file(pathos.join(directory, partPath)); | |
| 239 assert(partUri.isAbsolute); | |
| 240 JavaFile javaFile = new JavaFile.fromUri(partUri); | |
| 241 return new FileBasedSource(javaFile, importUri); | |
| 242 } | 161 } |
| 243 } | 162 } |
| 244 | 163 |
| 245 class _EmbedderSdk implements DartSdk { | 164 class EmbedderSdk implements DartSdk { |
| 246 // TODO(danrubel) Refactor this with DirectoryBasedDartSdk | 165 // TODO(danrubel) Refactor this with DirectoryBasedDartSdk |
| 247 | 166 |
| 248 /// The resolver associated with this embedder sdk. | 167 /// The resolver associated with this embedder sdk. |
| 249 EmbedderUriResolver _resolver; | 168 EmbedderUriResolver _resolver; |
| 250 | 169 |
| 251 /// The [AnalysisContext] which is used for all of the sources in this sdk. | 170 /// The [AnalysisContext] which is used for all of the sources in this sdk. |
| 252 InternalAnalysisContext _analysisContext; | 171 InternalAnalysisContext _analysisContext; |
| 253 | 172 |
| 254 /// The library map that is populated by visiting the AST structure parsed fro
m | 173 /// The library map that is populated by visiting the AST structure parsed fro
m |
| 255 /// the contents of the libraries file. | 174 /// the contents of the libraries file. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 278 @override | 197 @override |
| 279 String get sdkVersion => '0'; | 198 String get sdkVersion => '0'; |
| 280 | 199 |
| 281 @override | 200 @override |
| 282 List<String> get uris => _librariesMap.uris; | 201 List<String> get uris => _librariesMap.uris; |
| 283 | 202 |
| 284 @override | 203 @override |
| 285 Source fromFileUri(Uri uri) { | 204 Source fromFileUri(Uri uri) { |
| 286 JavaFile file = new JavaFile.fromUri(uri); | 205 JavaFile file = new JavaFile.fromUri(uri); |
| 287 String filePath = file.getAbsolutePath(); | 206 String filePath = file.getAbsolutePath(); |
| 288 String srcPath = filePath.replaceAll('\\', '/'); | |
| 289 | 207 |
| 290 String path; | 208 String path; |
| 291 for (SdkLibrary library in _librariesMap.sdkLibraries) { | 209 for (SdkLibrary library in _librariesMap.sdkLibraries) { |
| 292 String libraryPath = library.path; | 210 String libraryPath = library.path; |
| 293 if (srcPath == libraryPath) { | 211 if (filePath == libraryPath) { |
| 294 path = '$_DART_COLON_PREFIX${library.shortName}'; | 212 path = '$_DART_COLON_PREFIX${library.shortName}'; |
| 295 break; | 213 break; |
| 296 } | 214 } |
| 297 } | 215 } |
| 298 if (path == null) { | 216 if (path == null) { |
| 299 for (SdkLibrary library in _librariesMap.sdkLibraries) { | 217 for (SdkLibrary library in _librariesMap.sdkLibraries) { |
| 300 String libraryPath = library.path; | 218 String libraryPath = library.path; |
| 301 int index = libraryPath.lastIndexOf('/'); | 219 int index = libraryPath.lastIndexOf('/'); |
| 302 if (index == -1) { | 220 if (index == -1) { |
| 303 continue; | 221 continue; |
| 304 } | 222 } |
| 305 String prefix = libraryPath.substring(0, index + 1); | 223 String prefix = libraryPath.substring(0, index + 1); |
| 306 if (!srcPath.startsWith(prefix)) { | 224 if (!filePath.startsWith(prefix)) { |
| 307 continue; | 225 continue; |
| 308 } | 226 } |
| 309 var relPath = srcPath.substring(prefix.length); | 227 var relPath = filePath.substring(prefix.length); |
| 310 path = '$_DART_COLON_PREFIX${library.shortName}/$relPath'; | 228 path = '$_DART_COLON_PREFIX${library.shortName}/$relPath'; |
| 311 break; | 229 break; |
| 312 } | 230 } |
| 313 } | 231 } |
| 314 | 232 |
| 315 if (path != null) { | 233 if (path != null) { |
| 316 try { | 234 try { |
| 317 return new FileBasedSource(file, parseUriWithException(path)); | 235 return new FileBasedSource(file, parseUriWithException(path)); |
| 318 } on URISyntaxException catch (exception, stackTrace) { | 236 } on URISyntaxException catch (exception, stackTrace) { |
| 319 AnalysisEngine.instance.logger.logInformation( | 237 AnalysisEngine.instance.logger.logInformation( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 } | 276 } |
| 359 String filePath = srcPath.replaceAll('/', JavaFile.separator); | 277 String filePath = srcPath.replaceAll('/', JavaFile.separator); |
| 360 try { | 278 try { |
| 361 JavaFile file = new JavaFile(filePath); | 279 JavaFile file = new JavaFile(filePath); |
| 362 return new FileBasedSource(file, parseUriWithException(dartUri)); | 280 return new FileBasedSource(file, parseUriWithException(dartUri)); |
| 363 } on URISyntaxException { | 281 } on URISyntaxException { |
| 364 return null; | 282 return null; |
| 365 } | 283 } |
| 366 } | 284 } |
| 367 } | 285 } |
| OLD | NEW |