 Chromium Code Reviews
 Chromium Code Reviews Issue 2043963004:
  Package map processing abstraction.  (Closed) 
  Base URL: git@github.com:dart-lang/sdk.git@master
    
  
    Issue 2043963004:
  Package map processing abstraction.  (Closed) 
  Base URL: git@github.com:dart-lang/sdk.git@master| Index: pkg/analyzer/lib/src/context/context_factory.dart | 
| diff --git a/pkg/analyzer/lib/src/context/context_factory.dart b/pkg/analyzer/lib/src/context/context_factory.dart | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..4bb877db057aacc72b252748b2902aad3cc6561b | 
| --- /dev/null | 
| +++ b/pkg/analyzer/lib/src/context/context_factory.dart | 
| @@ -0,0 +1,137 @@ | 
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 
| +// for details. All rights reserved. Use of this source code is governed by a | 
| +// BSD-style license that can be found in the LICENSE file. | 
| + | 
| +library analyzer.src.context_factory; | 
| + | 
| +import 'dart:convert'; | 
| +import 'dart:core' hide Resource; | 
| + | 
| +import 'package:analyzer/file_system/file_system.dart'; | 
| +import 'package:analyzer/src/generated/sdk.dart'; | 
| +import 'package:yaml/yaml.dart'; | 
| +import 'package:analyzer/src/generated/engine.dart'; | 
| +import 'dart:io' as io; | 
| + | 
| +/// (Placeholder) | 
| +abstract class ContextFactory { | 
| + /// Create an analysis context for the given [source] directory or file, with | 
| + /// the given [defaultOptions]. | 
| + AnalysisContext createContext( | 
| + io.FileSystemEntity source, AnalysisOptions defaultOptions); | 
| +} | 
| + | 
| +/// Processes package maps, extracting SDK embedders and extenders, creating a | 
| +/// consolidated [libraryMap]. | 
| +class PackageMapProcessor { | 
| + static const String _EMBEDDED_LIB_MAP_KEY = 'embedded_libs'; | 
| + static const String _EMBEDDER_FILE_NAME = '_embedder.yaml'; | 
| + static const String _SDK_EXT_NAME = '_sdkext'; | 
| + | 
| + /// Map of processed embedder libraries. | 
| + final LibraryMap embeddedLibraries = new LibraryMap(); | 
| + | 
| + /// Map of processed SDK extension libraries. | 
| + final LibraryMap extendedLibraries = new LibraryMap(); | 
| + | 
| + /// Combined map of processed libraries. | 
| + LibraryMap get libraryMap { | 
| + LibraryMap libraryMap = new LibraryMap(); | 
| + for (String uri in embeddedLibraries.uris) { | 
| + libraryMap.setLibrary(uri, embeddedLibraries.getLibrary(uri)); | 
| + } | 
| + // Extenders extend but do not override. | 
| + for (String uri in extendedLibraries.uris) { | 
| 
Brian Wilkerson
2016/06/07 20:48:48
It would be more efficient to add the extensions t
 
pquitslund
2016/06/07 20:59:58
Done.
 | 
| + if (embeddedLibraries.getLibrary(uri) == null) { | 
| + libraryMap.setLibrary(uri, extendedLibraries.getLibrary(uri)); | 
| + } | 
| + } | 
| + return libraryMap; | 
| + } | 
| + | 
| + /// Create a processor for the given [packageMap]. | 
| + PackageMapProcessor(Map<String, List<Folder>> packageMap) { | 
| + packageMap?.forEach(_processPackage); | 
| + } | 
| + | 
| + /// Whether the package map contains an SDK embedder. | 
| + bool get hasEmbedder => embeddedLibraries.size() > 0; | 
| + | 
| + /// Whether the package map contains an SDK extension. | 
| + bool get hasSdkExtension => extendedLibraries.size() > 0; | 
| + | 
| + void _processEmbedderYaml(String embedderYaml, Folder libDir) { | 
| + try { | 
| + YamlNode map = loadYaml(embedderYaml); | 
| + if (map is YamlMap) { | 
| + YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY]; | 
| + if (embedded_libs is YamlMap) { | 
| + embedded_libs.forEach( | 
| + (k, v) => _processMapping(embeddedLibraries, k, v, libDir)); | 
| + } | 
| + } | 
| + } catch (_) { | 
| + // Ignored. | 
| + } | 
| + } | 
| + | 
| + void _processMapping( | 
| + LibraryMap libraryMap, String name, String file, Folder libDir) { | 
| + if (!_hasDartPrefix(name)) { | 
| + // SDK libraries must begin with 'dart:'. | 
| + return; | 
| + } | 
| + if (libraryMap.getLibrary(name) != null) { | 
| + // Libraries can't be redefined. | 
| + return; | 
| + } | 
| + String libPath = libDir.canonicalizePath(file); | 
| + SdkLibraryImpl library = new SdkLibraryImpl(name)..path = libPath; | 
| + libraryMap.setLibrary(name, library); | 
| + } | 
| + | 
| + void _processPackage(String name, List<Folder> libDirs) { | 
| + for (Folder libDir in libDirs) { | 
| + String embedderYaml = _readEmbedderYaml(libDir); | 
| + if (embedderYaml != null) { | 
| + _processEmbedderYaml(embedderYaml, libDir); | 
| + } | 
| + String sdkExt = _readDotSdkExt(libDir); | 
| + if (sdkExt != null) { | 
| + _processSdkExt(sdkExt, libDir); | 
| + } | 
| + } | 
| + } | 
| + | 
| + void _processSdkExt(String sdkExtJSON, Folder libDir) { | 
| + try { | 
| + var sdkExt = JSON.decode(sdkExtJSON); | 
| + if (sdkExt is Map) { | 
| + sdkExt.forEach( | 
| + (k, v) => _processMapping(extendedLibraries, k, v, libDir)); | 
| + } | 
| + } catch (_) { | 
| + // Ignored. | 
| + } | 
| + } | 
| + | 
| + static bool _hasDartPrefix(String uri) => | 
| + uri.startsWith(DartSdk.DART_LIBRARY_PREFIX); | 
| + | 
| + static String _readDotSdkExt(Folder libDir) => | 
| + _safeRead(libDir.getChild(_SDK_EXT_NAME)); | 
| + | 
| + static String _readEmbedderYaml(Folder libDir) => | 
| + _safeRead(libDir.getChild(_EMBEDDER_FILE_NAME)); | 
| + | 
| + static String _safeRead(Resource file) { | 
| + try { | 
| + if (file is File) { | 
| + return file.readAsStringSync(); | 
| + } | 
| + } on FileSystemException { | 
| + // File can't be read. | 
| + } | 
| + return null; | 
| + } | 
| +} |