Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: packages/analyzer/lib/src/dart/sdk/sdk.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4
5 library analyzer.src.generated.sdk2;
6
7 import 'dart:collection';
8 import 'dart:convert';
9 import 'dart:io' as io;
10
11 import 'package:analyzer/dart/ast/ast.dart';
12 import 'package:analyzer/error/listener.dart';
13 import 'package:analyzer/exception/exception.dart';
14 import 'package:analyzer/file_system/file_system.dart';
15 import 'package:analyzer/file_system/memory_file_system.dart';
16 import 'package:analyzer/src/context/context.dart';
17 import 'package:analyzer/src/dart/scanner/reader.dart';
18 import 'package:analyzer/src/dart/scanner/scanner.dart';
19 import 'package:analyzer/src/generated/engine.dart';
20 import 'package:analyzer/src/generated/java_engine_io.dart';
21 import 'package:analyzer/src/generated/parser.dart';
22 import 'package:analyzer/src/generated/sdk.dart';
23 import 'package:analyzer/src/generated/source_io.dart';
24 import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
25 import 'package:analyzer/src/summary/summary_sdk.dart';
26 import 'package:path/path.dart' as pathos;
27 import 'package:yaml/yaml.dart';
28
29 /**
30 * An abstract implementation of a Dart SDK in which the available libraries are
31 * stored in a library map. Subclasses are responsible for populating the
32 * library map.
33 */
34 abstract class AbstractDartSdk implements DartSdk {
35 /**
36 * The resource provider used to access the file system.
37 */
38 ResourceProvider resourceProvider;
39
40 /**
41 * A mapping from Dart library URI's to the library represented by that URI.
42 */
43 LibraryMap libraryMap = new LibraryMap();
44
45 /**
46 * The [AnalysisOptions] to use to create the [context].
47 */
48 AnalysisOptions _analysisOptions;
49
50 /**
51 * The flag that specifies whether an SDK summary should be used. This is a
52 * temporary flag until summaries are enabled by default.
53 */
54 bool _useSummary = false;
55
56 /**
57 * The [AnalysisContext] which is used for all of the sources in this SDK.
58 */
59 InternalAnalysisContext _analysisContext;
60
61 /**
62 * The mapping from Dart URI's to the corresponding sources.
63 */
64 Map<String, Source> _uriToSourceMap = new HashMap<String, Source>();
65
66 PackageBundle _sdkBundle;
67
68 /**
69 * Set the [options] for this SDK analysis context. Throw [StateError] if the
70 * context has been already created.
71 */
72 void set analysisOptions(AnalysisOptions options) {
73 if (_analysisContext != null) {
74 throw new StateError(
75 'Analysis options cannot be changed after context creation.');
76 }
77 _analysisOptions = options;
78 }
79
80 @override
81 AnalysisContext get context {
82 if (_analysisContext == null) {
83 _analysisContext = new SdkAnalysisContext(_analysisOptions);
84 SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
85 _analysisContext.sourceFactory = factory;
86 if (_useSummary) {
87 bool strongMode = _analysisOptions?.strongMode ?? false;
88 PackageBundle sdkBundle = getLinkedBundle();
89 if (sdkBundle != null) {
90 _analysisContext.resultProvider = new SdkSummaryResultProvider(
91 _analysisContext, sdkBundle, strongMode);
92 }
93 }
94 }
95 return _analysisContext;
96 }
97
98 @override
99 List<SdkLibrary> get sdkLibraries => libraryMap.sdkLibraries;
100
101 /**
102 * Return the path separator used by the resource provider.
103 */
104 String get separator => resourceProvider.pathContext.separator;
105
106 @override
107 List<String> get uris => libraryMap.uris;
108
109 /**
110 * Return `true` if the SDK summary will be used when available.
111 */
112 bool get useSummary => _useSummary;
113
114 /**
115 * Specify whether SDK summary should be used.
116 */
117 void set useSummary(bool use) {
118 if (_analysisContext != null) {
119 throw new StateError(
120 'The "useSummary" flag cannot be changed after context creation.');
121 }
122 _useSummary = use;
123 }
124
125 /**
126 * Add the extensions from one or more sdk extension files to this sdk. The
127 * [extensions] should be a table mapping the names of extensions to the paths
128 * where those extensions can be found.
129 */
130 void addExtensions(Map<String, String> extensions) {
131 extensions.forEach((String uri, String path) {
132 SdkLibraryImpl library = new SdkLibraryImpl(uri);
133 library.path = path;
134 libraryMap.setLibrary(uri, library);
135 });
136 }
137
138 @override
139 Source fromFileUri(Uri uri) {
140 File file =
141 resourceProvider.getFile(resourceProvider.pathContext.fromUri(uri));
142 String path = _getPath(file);
143 if (path == null) {
144 return null;
145 }
146 try {
147 return file.createSource(Uri.parse(path));
148 } on FormatException catch (exception, stackTrace) {
149 AnalysisEngine.instance.logger.logInformation(
150 "Failed to create URI: $path",
151 new CaughtException(exception, stackTrace));
152 }
153 return null;
154 }
155
156 @override
157 PackageBundle getLinkedBundle() {
158 if (_useSummary) {
159 bool strongMode = _analysisOptions?.strongMode ?? false;
160 _sdkBundle ??= getSummarySdkBundle(strongMode);
161 return _sdkBundle;
162 }
163 return null;
164 }
165
166 String getRelativePathFromFile(File file);
167
168 @override
169 SdkLibrary getSdkLibrary(String dartUri) => libraryMap.getLibrary(dartUri);
170
171 /**
172 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
173 * This method should not be used outside of `analyzer` and `analyzer_cli`
174 * packages.
175 */
176 PackageBundle getSummarySdkBundle(bool strongMode);
177
178 Source internalMapDartUri(String dartUri) {
179 // TODO(brianwilkerson) Figure out how to unify the implementations in the
180 // two subclasses.
181 String libraryName;
182 String relativePath;
183 int index = dartUri.indexOf('/');
184 if (index >= 0) {
185 libraryName = dartUri.substring(0, index);
186 relativePath = dartUri.substring(index + 1);
187 } else {
188 libraryName = dartUri;
189 relativePath = "";
190 }
191 SdkLibrary library = getSdkLibrary(libraryName);
192 if (library == null) {
193 return null;
194 }
195 String srcPath;
196 if (relativePath.isEmpty) {
197 srcPath = library.path;
198 } else {
199 String libraryPath = library.path;
200 int index = libraryPath.lastIndexOf(separator);
201 if (index == -1) {
202 index = libraryPath.lastIndexOf('/');
203 if (index == -1) {
204 return null;
205 }
206 }
207 String prefix = libraryPath.substring(0, index + 1);
208 srcPath = '$prefix$relativePath';
209 }
210 String filePath = srcPath.replaceAll('/', separator);
211 try {
212 File file = resourceProvider.getFile(filePath);
213 return file.createSource(Uri.parse(dartUri));
214 } on FormatException {
215 return null;
216 }
217 }
218
219 @override
220 Source mapDartUri(String dartUri) {
221 Source source = _uriToSourceMap[dartUri];
222 if (source == null) {
223 source = internalMapDartUri(dartUri);
224 _uriToSourceMap[dartUri] = source;
225 }
226 return source;
227 }
228
229 String _getPath(File file) {
230 List<SdkLibrary> libraries = libraryMap.sdkLibraries;
231 int length = libraries.length;
232 List<String> paths = new List(length);
233 String filePath = getRelativePathFromFile(file);
234 if (filePath == null) {
235 return null;
236 }
237 for (int i = 0; i < length; i++) {
238 SdkLibrary library = libraries[i];
239 String libraryPath = library.path.replaceAll('/', separator);
240 if (filePath == libraryPath) {
241 return library.shortName;
242 }
243 paths[i] = libraryPath;
244 }
245 for (int i = 0; i < length; i++) {
246 SdkLibrary library = libraries[i];
247 String libraryPath = paths[i];
248 int index = libraryPath.lastIndexOf(separator);
249 if (index >= 0) {
250 String prefix = libraryPath.substring(0, index + 1);
251 if (filePath.startsWith(prefix)) {
252 String relPath =
253 filePath.substring(prefix.length).replaceAll(separator, '/');
254 return '${library.shortName}/$relPath';
255 }
256 }
257 }
258 return null;
259 }
260 }
261
262 /**
263 * An SDK backed by URI mappings derived from an `_embedder.yaml` file.
264 */
265 class EmbedderSdk extends AbstractDartSdk {
266 static const String _DART_COLON_PREFIX = 'dart:';
267
268 static const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs';
269 final Map<String, String> _urlMappings = new HashMap<String, String>();
270
271 PackageBundle _embedderBundle;
272
273 EmbedderSdk(
274 ResourceProvider resourceProvider, Map<Folder, YamlMap> embedderYamls) {
275 this.resourceProvider = resourceProvider;
276 embedderYamls?.forEach(_processEmbedderYaml);
277 if (embedderYamls?.length == 1) {
278 Folder libFolder = embedderYamls.keys.first;
279 _loadEmbedderBundle(libFolder);
280 }
281 }
282
283 @override
284 // TODO(danrubel) Determine SDK version
285 String get sdkVersion => '0';
286
287 /**
288 * The url mappings for this SDK.
289 */
290 Map<String, String> get urlMappings => _urlMappings;
291
292 @override
293 String getRelativePathFromFile(File file) => file.path;
294
295 @override
296 PackageBundle getSummarySdkBundle(bool strongMode) {
297 if (strongMode) {
298 return _embedderBundle;
299 }
300 return null;
301 }
302
303 @override
304 Source internalMapDartUri(String dartUri) {
305 String libraryName;
306 String relativePath;
307 int index = dartUri.indexOf('/');
308 if (index >= 0) {
309 libraryName = dartUri.substring(0, index);
310 relativePath = dartUri.substring(index + 1);
311 } else {
312 libraryName = dartUri;
313 relativePath = "";
314 }
315 SdkLibrary library = getSdkLibrary(libraryName);
316 if (library == null) {
317 return null;
318 }
319 String srcPath;
320 if (relativePath.isEmpty) {
321 srcPath = library.path;
322 } else {
323 String libraryPath = library.path;
324 int index = libraryPath.lastIndexOf(separator);
325 if (index == -1) {
326 index = libraryPath.lastIndexOf('/');
327 if (index == -1) {
328 return null;
329 }
330 }
331 String prefix = libraryPath.substring(0, index + 1);
332 srcPath = '$prefix$relativePath';
333 }
334 String filePath = srcPath.replaceAll('/', separator);
335 try {
336 File file = resourceProvider.getFile(filePath);
337 return file.createSource(Uri.parse(dartUri));
338 } on FormatException {
339 return null;
340 }
341 }
342
343 void _loadEmbedderBundle(Folder libFolder) {
344 File bundleFile = libFolder.parent.getChildAssumingFile('sdk.ds');
345 if (bundleFile.exists) {
346 try {
347 List<int> bytes = bundleFile.readAsBytesSync();
348 _embedderBundle = new PackageBundle.fromBuffer(bytes);
349 } on FileSystemException {}
350 }
351 }
352
353 /**
354 * Install the mapping from [name] to [libDir]/[file].
355 */
356 void _processEmbeddedLibs(String name, String file, Folder libDir) {
357 if (!name.startsWith(_DART_COLON_PREFIX)) {
358 // SDK libraries must begin with 'dart:'.
359 return;
360 }
361 String libPath = libDir.canonicalizePath(file);
362 _urlMappings[name] = libPath;
363 SdkLibraryImpl library = new SdkLibraryImpl(name);
364 library.path = libPath;
365 libraryMap.setLibrary(name, library);
366 }
367
368 /**
369 * Given the 'embedderYamls' from [EmbedderYamlLocator] check each one for the
370 * top level key 'embedded_libs'. Under the 'embedded_libs' key are key value
371 * pairs. Each key is a 'dart:' library uri and each value is a path
372 * (relative to the directory containing `_embedder.yaml`) to a dart script
373 * for the given library. For example:
374 *
375 * embedded_libs:
376 * 'dart:io': '../../sdk/io/io.dart'
377 *
378 * If a key doesn't begin with `dart:` it is ignored.
379 */
380 void _processEmbedderYaml(Folder libDir, YamlMap map) {
381 YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY];
382 if (embedded_libs is YamlMap) {
383 embedded_libs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
384 }
385 }
386 }
387
388 /**
389 * A Dart SDK installed in a specified directory. Typical Dart SDK layout is
390 * something like...
391 *
392 * dart-sdk/
393 * bin/
394 * dart[.exe] <-- VM
395 * lib/
396 * core/
397 * core.dart
398 * ... other core library files ...
399 * ... other libraries ...
400 * util/
401 * ... Dart utilities ...
402 * Chromium/ <-- Dartium typically exists in a sibling directory
403 */
404 class FolderBasedDartSdk extends AbstractDartSdk {
405 /**
406 * The name of the directory within the SDK directory that contains
407 * executables.
408 */
409 static String _BIN_DIRECTORY_NAME = "bin";
410
411 /**
412 * The name of the directory within the SDK directory that contains
413 * documentation for the libraries.
414 */
415 static String _DOCS_DIRECTORY_NAME = "docs";
416
417 /**
418 * The name of the directory within the SDK directory that contains the
419 * sdk_library_metadata directory.
420 */
421 static String _INTERNAL_DIR = "_internal";
422
423 /**
424 * The name of the sdk_library_metadata directory that contains the package
425 * holding the libraries.dart file.
426 */
427 static String _SDK_LIBRARY_METADATA_DIR = "sdk_library_metadata";
428
429 /**
430 * The name of the directory within the sdk_library_metadata that contains
431 * libraries.dart.
432 */
433 static String _SDK_LIBRARY_METADATA_LIB_DIR = "lib";
434
435 /**
436 * The name of the directory within the SDK directory that contains the
437 * libraries.
438 */
439 static String _LIB_DIRECTORY_NAME = "lib";
440
441 /**
442 * The name of the libraries file.
443 */
444 static String _LIBRARIES_FILE = "libraries.dart";
445
446 /**
447 * The name of the pub executable on windows.
448 */
449 static String _PUB_EXECUTABLE_NAME_WIN = "pub.bat";
450
451 /**
452 * The name of the pub executable on non-windows operating systems.
453 */
454 static String _PUB_EXECUTABLE_NAME = "pub";
455
456 /**
457 * The name of the file within the SDK directory that contains the version
458 * number of the SDK.
459 */
460 static String _VERSION_FILE_NAME = "version";
461
462 /**
463 * The directory containing the SDK.
464 */
465 Folder _sdkDirectory;
466
467 /**
468 * The directory within the SDK directory that contains the libraries.
469 */
470 Folder _libraryDirectory;
471
472 /**
473 * The revision number of this SDK, or `"0"` if the revision number cannot be
474 * discovered.
475 */
476 String _sdkVersion;
477
478 /**
479 * The file containing the pub executable.
480 */
481 File _pubExecutable;
482
483 /**
484 * Initialize a newly created SDK to represent the Dart SDK installed in the
485 * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path
486 * should be used when it is available
487 */
488 FolderBasedDartSdk(ResourceProvider resourceProvider, this._sdkDirectory,
489 [bool useDart2jsPaths = false]) {
490 this.resourceProvider = resourceProvider;
491 libraryMap = initialLibraryMap(useDart2jsPaths);
492 }
493
494 /**
495 * Return the directory containing the SDK.
496 */
497 Folder get directory => _sdkDirectory;
498
499 /**
500 * Return the directory containing documentation for the SDK.
501 */
502 Folder get docDirectory =>
503 _sdkDirectory.getChildAssumingFolder(_DOCS_DIRECTORY_NAME);
504
505 /**
506 * Return the directory within the SDK directory that contains the libraries.
507 */
508 Folder get libraryDirectory {
509 if (_libraryDirectory == null) {
510 _libraryDirectory =
511 _sdkDirectory.getChildAssumingFolder(_LIB_DIRECTORY_NAME);
512 }
513 return _libraryDirectory;
514 }
515
516 /**
517 * Return the file containing the Pub executable, or `null` if it does not exi st.
518 */
519 File get pubExecutable {
520 if (_pubExecutable == null) {
521 _pubExecutable = _sdkDirectory
522 .getChildAssumingFolder(_BIN_DIRECTORY_NAME)
523 .getChildAssumingFile(OSUtilities.isWindows()
524 ? _PUB_EXECUTABLE_NAME_WIN
525 : _PUB_EXECUTABLE_NAME);
526 }
527 return _pubExecutable;
528 }
529
530 /**
531 * Return the revision number of this SDK, or `"0"` if the revision number
532 * cannot be discovered.
533 */
534 @override
535 String get sdkVersion {
536 if (_sdkVersion == null) {
537 _sdkVersion = DartSdk.DEFAULT_VERSION;
538 File revisionFile =
539 _sdkDirectory.getChildAssumingFile(_VERSION_FILE_NAME);
540 try {
541 String revision = revisionFile.readAsStringSync();
542 if (revision != null) {
543 _sdkVersion = revision.trim();
544 }
545 } on FileSystemException {
546 // Fall through to return the default.
547 }
548 }
549 return _sdkVersion;
550 }
551
552 /**
553 * Determine the search order for trying to locate the [_LIBRARIES_FILE].
554 */
555 Iterable<File> get _libraryMapLocations sync* {
556 yield libraryDirectory
557 .getChildAssumingFolder(_INTERNAL_DIR)
558 .getChildAssumingFolder(_SDK_LIBRARY_METADATA_DIR)
559 .getChildAssumingFolder(_SDK_LIBRARY_METADATA_LIB_DIR)
560 .getChildAssumingFile(_LIBRARIES_FILE);
561 yield libraryDirectory
562 .getChildAssumingFolder(_INTERNAL_DIR)
563 .getChildAssumingFile(_LIBRARIES_FILE);
564 }
565
566 @override
567 String getRelativePathFromFile(File file) {
568 String filePath = file.path;
569 String libPath = libraryDirectory.path;
570 if (!filePath.startsWith("$libPath$separator")) {
571 return null;
572 }
573 return filePath.substring(libPath.length + 1);
574 }
575
576 /**
577 * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
578 * This method should not be used outside of `analyzer` and `analyzer_cli`
579 * packages.
580 */
581 PackageBundle getSummarySdkBundle(bool strongMode) {
582 String rootPath = directory.path;
583 String name = strongMode ? 'strong.sum' : 'spec.sum';
584 String path =
585 resourceProvider.pathContext.join(rootPath, 'lib', '_internal', name);
586 try {
587 File file = resourceProvider.getFile(path);
588 if (file.exists) {
589 List<int> bytes = file.readAsBytesSync();
590 return new PackageBundle.fromBuffer(bytes);
591 }
592 } catch (exception, stackTrace) {
593 AnalysisEngine.instance.logger.logError(
594 'Failed to load SDK analysis summary from $path',
595 new CaughtException(exception, stackTrace));
596 }
597 return null;
598 }
599
600 /**
601 * Read all of the configuration files to initialize the library maps. The
602 * flag [useDart2jsPaths] is `true` if the dart2js path should be used when it
603 * is available. Return the initialized library map.
604 */
605 LibraryMap initialLibraryMap(bool useDart2jsPaths) {
606 List<String> searchedPaths = <String>[];
607 var lastStackTrace = null;
608 var lastException = null;
609 for (File librariesFile in _libraryMapLocations) {
610 try {
611 String contents = librariesFile.readAsStringSync();
612 return new SdkLibrariesReader(useDart2jsPaths)
613 .readFromFile(librariesFile, contents);
614 } catch (exception, stackTrace) {
615 searchedPaths.add(librariesFile.path);
616 lastException = exception;
617 lastStackTrace = stackTrace;
618 }
619 }
620 StringBuffer buffer = new StringBuffer();
621 buffer.writeln('Could not initialize the library map from $searchedPaths');
622 if (resourceProvider is MemoryResourceProvider) {
623 (resourceProvider as MemoryResourceProvider).writeOn(buffer);
624 }
625 AnalysisEngine.instance.logger.logError(
626 buffer.toString(), new CaughtException(lastException, lastStackTrace));
627 return new LibraryMap();
628 }
629
630 @override
631 Source internalMapDartUri(String dartUri) {
632 String libraryName;
633 String relativePath;
634 int index = dartUri.indexOf('/');
635 if (index >= 0) {
636 libraryName = dartUri.substring(0, index);
637 relativePath = dartUri.substring(index + 1);
638 } else {
639 libraryName = dartUri;
640 relativePath = "";
641 }
642 SdkLibrary library = getSdkLibrary(libraryName);
643 if (library == null) {
644 return null;
645 }
646 try {
647 File file = libraryDirectory.getChildAssumingFile(library.path);
648 if (!relativePath.isEmpty) {
649 file = file.parent.getChildAssumingFile(relativePath);
650 }
651 return file.createSource(Uri.parse(dartUri));
652 } on FormatException {
653 return null;
654 }
655 }
656
657 /**
658 * Return the default directory for the Dart SDK, or `null` if the directory
659 * cannot be determined (or does not exist). The default directory is provided
660 * by a system property named `com.google.dart.sdk`.
661 */
662 static Folder defaultSdkDirectory(ResourceProvider resourceProvider) {
663 // TODO(brianwilkerson) This is currently only being used in the analysis
664 // server's Driver class to find the default SDK. The command-line analyzer
665 // uses cli_utils to find the SDK. Not sure why they're different.
666 String sdkProperty = getSdkProperty(resourceProvider);
667 if (sdkProperty == null) {
668 return null;
669 }
670 Folder sdkDirectory = resourceProvider.getFolder(sdkProperty);
671 if (!sdkDirectory.exists) {
672 return null;
673 }
674 return sdkDirectory;
675 }
676
677 static String getSdkProperty(ResourceProvider resourceProvider) {
678 String exec = io.Platform.resolvedExecutable;
679 if (exec.length == 0) {
680 return null;
681 }
682 pathos.Context pathContext = resourceProvider.pathContext;
683 if (pathContext.style != pathos.context.style) {
684 // This will only be true if pathContext == posix and
685 // pathos.context == windows, which only happens when running tests.
686 if (exec.startsWith(new RegExp('[a-zA-Z]:'))) {
687 exec = exec.substring(2);
688 }
689 exec = pathContext.fromUri(pathos.context.toUri(exec));
690 }
691 // Might be "xcodebuild/ReleaseIA32/dart" with "sdk" sibling
692 String outDir = pathContext.dirname(pathContext.dirname(exec));
693 String sdkPath = pathContext.join(pathContext.dirname(outDir), "sdk");
694 if (resourceProvider.getFolder(sdkPath).exists) {
695 return sdkPath;
696 }
697 // probably be "dart-sdk/bin/dart"
698 return pathContext.dirname(pathContext.dirname(exec));
699 }
700 }
701
702 /**
703 * An object used to locate SDK extensions.
704 *
705 * Given a package map, it will check in each package's `lib` directory for the
706 * existence of a `_sdkext` file. This file must contain a JSON encoded map.
707 * Each key in the map is a `dart:` library name. Each value is a path (relative
708 * to the directory containing `_sdkext`) to a dart script for the given
709 * library. For example:
710 * ```
711 * {
712 * "dart:sky": "../sdk_ext/dart_sky.dart"
713 * }
714 * ```
715 * If a key doesn't begin with `dart:` it is ignored.
716 */
717 class SdkExtensionFinder {
718 /**
719 * The name of the extension file.
720 */
721 static const String SDK_EXT_NAME = '_sdkext';
722
723 /**
724 * The prefix required for all keys in an extension file that will not be
725 * ignored.
726 */
727 static const String DART_COLON_PREFIX = 'dart:';
728
729 /**
730 * A table mapping the names of extensions to the paths where those extensions
731 * can be found.
732 */
733 final Map<String, String> _urlMappings = <String, String>{};
734
735 /**
736 * The absolute paths of the extension files that contributed to the
737 * [_urlMappings].
738 */
739 final List<String> extensionFilePaths = <String>[];
740
741 /**
742 * Initialize a newly created finder to look in the packages in the given
743 * [packageMap] for SDK extension files.
744 */
745 SdkExtensionFinder(Map<String, List<Folder>> packageMap) {
746 if (packageMap == null) {
747 return;
748 }
749 packageMap.forEach(_processPackage);
750 }
751
752 /**
753 * Return a table mapping the names of extensions to the paths where those
754 * extensions can be found.
755 */
756 Map<String, String> get urlMappings =>
757 new Map<String, String>.from(_urlMappings);
758
759 /**
760 * Given a package [name] and a list of folders ([libDirs]), add any found sdk
761 * extensions.
762 */
763 void _processPackage(String name, List<Folder> libDirs) {
764 for (var libDir in libDirs) {
765 var sdkExt = _readDotSdkExt(libDir);
766 if (sdkExt != null) {
767 _processSdkExt(sdkExt, libDir);
768 }
769 }
770 }
771
772 /**
773 * Given the JSON for an SDK extension ([sdkExtJSON]) and a folder ([libDir]),
774 * setup the uri mapping.
775 */
776 void _processSdkExt(String sdkExtJSON, Folder libDir) {
777 var sdkExt;
778 try {
779 sdkExt = JSON.decode(sdkExtJSON);
780 } catch (e) {
781 return;
782 }
783 if ((sdkExt == null) || (sdkExt is! Map)) {
784 return;
785 }
786 bool contributed = false;
787 sdkExt.forEach((k, v) {
788 if (k is String && v is String && _processSdkExtension(libDir, k, v)) {
789 contributed = true;
790 }
791 });
792 if (contributed) {
793 extensionFilePaths.add(libDir.getChild(SDK_EXT_NAME).path);
794 }
795 }
796
797 /**
798 * Install the mapping from [name] to [libDir]/[file].
799 */
800 bool _processSdkExtension(Folder libDir, String name, String file) {
801 if (!name.startsWith(DART_COLON_PREFIX)) {
802 // SDK extensions must begin with 'dart:'.
803 return false;
804 }
805 _urlMappings[name] = libDir.canonicalizePath(file);
806 return true;
807 }
808
809 /**
810 * Read the contents of [libDir]/[SDK_EXT_NAME] as a string, or `null` if the
811 * file doesn't exist.
812 */
813 String _readDotSdkExt(Folder libDir) {
814 File file = libDir.getChild(SDK_EXT_NAME);
815 try {
816 return file.readAsStringSync();
817 } on FileSystemException {
818 // File can't be read.
819 return null;
820 }
821 }
822 }
823
824 /**
825 * An object used to read and parse the libraries file
826 * (dart-sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart) for informat ion
827 * about the libraries in an SDK. The library information is represented as a
828 * Dart file containing a single top-level variable whose value is a const map.
829 * The keys of the map are the names of libraries defined in the SDK and the
830 * values in the map are info objects defining the library. For example, a
831 * subset of a typical SDK might have a libraries file that looks like the
832 * following:
833 *
834 * final Map<String, LibraryInfo> LIBRARIES = const <LibraryInfo> {
835 * // Used by VM applications
836 * "builtin" : const LibraryInfo(
837 * "builtin/builtin_runtime.dart",
838 * category: "Server",
839 * platforms: VM_PLATFORM),
840 *
841 * "compiler" : const LibraryInfo(
842 * "compiler/compiler.dart",
843 * category: "Tools",
844 * platforms: 0),
845 * };
846 */
847 class SdkLibrariesReader {
848 /**
849 * A flag indicating whether the dart2js path should be used when it is
850 * available.
851 */
852 final bool _useDart2jsPaths;
853
854 /**
855 * Initialize a newly created library reader to use the dart2js path if
856 * [_useDart2jsPaths] is `true`.
857 */
858 SdkLibrariesReader(this._useDart2jsPaths);
859
860 /**
861 * Return the library map read from the given [file], given that the content
862 * of the file is already known to be [libraryFileContents].
863 */
864 LibraryMap readFromFile(File file, String libraryFileContents) =>
865 readFromSource(file.createSource(), libraryFileContents);
866
867 /**
868 * Return the library map read from the given [source], given that the content
869 * of the file is already known to be [libraryFileContents].
870 */
871 LibraryMap readFromSource(Source source, String libraryFileContents) {
872 BooleanErrorListener errorListener = new BooleanErrorListener();
873 Scanner scanner = new Scanner(
874 source, new CharSequenceReader(libraryFileContents), errorListener);
875 Parser parser = new Parser(source, errorListener);
876 CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
877 SdkLibrariesReader_LibraryBuilder libraryBuilder =
878 new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);
879 // If any syntactic errors were found then don't try to visit the AST
880 // structure.
881 if (!errorListener.errorReported) {
882 unit.accept(libraryBuilder);
883 }
884 return libraryBuilder.librariesMap;
885 }
886 }
OLDNEW
« no previous file with comments | « packages/analyzer/lib/src/dart/scanner/scanner.dart ('k') | packages/analyzer/lib/src/error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698