| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2017, 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.gn; | 
 |    6  | 
 |    7 import 'dart:collection'; | 
 |    8 import 'dart:core'; | 
 |    9  | 
 |   10 import 'package:analyzer/file_system/file_system.dart'; | 
 |   11 import 'package:analyzer/src/generated/source.dart'; | 
 |   12 import 'package:analyzer/src/generated/source_io.dart'; | 
 |   13 import 'package:analyzer/src/util/fast_uri.dart'; | 
 |   14 import 'package:path/path.dart'; | 
 |   15  | 
 |   16 /** | 
 |   17  * The [UriResolver] used to resolve `file` URIs in a [GnWorkspace]. | 
 |   18  */ | 
 |   19 class GnFileUriResolver extends ResourceUriResolver { | 
 |   20   /** | 
 |   21    * The workspace associated with this resolver. | 
 |   22    */ | 
 |   23   final GnWorkspace workspace; | 
 |   24  | 
 |   25   /** | 
 |   26    * Initialize a newly created resolver to be associated with the given | 
 |   27    * [workspace]. | 
 |   28    */ | 
 |   29   GnFileUriResolver(GnWorkspace workspace) | 
 |   30       : workspace = workspace, | 
 |   31         super(workspace.provider); | 
 |   32  | 
 |   33   @override | 
 |   34   Source resolveAbsolute(Uri uri, [Uri actualUri]) { | 
 |   35     if (!ResourceUriResolver.isFileUri(uri)) { | 
 |   36       return null; | 
 |   37     } | 
 |   38     String path = provider.pathContext.fromUri(uri); | 
 |   39     File file = workspace.findFile(path); | 
 |   40     if (file != null) { | 
 |   41       return file.createSource(actualUri ?? uri); | 
 |   42     } | 
 |   43     return null; | 
 |   44   } | 
 |   45 } | 
 |   46  | 
 |   47 /** | 
 |   48  * The [UriResolver] used to resolve `package` URIs in a [GnWorkspace]. | 
 |   49  */ | 
 |   50 class GnPackageUriResolver extends UriResolver { | 
 |   51   /** | 
 |   52    * The workspace associated with this resolver. | 
 |   53    */ | 
 |   54   final GnWorkspace workspace; | 
 |   55  | 
 |   56   /** | 
 |   57    * The path context that should be used to manipulate file system paths. | 
 |   58    */ | 
 |   59   final Context pathContext; | 
 |   60  | 
 |   61   /** | 
 |   62    * The map of package sources indexed by package name. | 
 |   63    */ | 
 |   64   final Map<String, String> _packages; | 
 |   65  | 
 |   66   /** | 
 |   67    * The cache of absolute [Uri]s to [Source]s mappings. | 
 |   68    */ | 
 |   69   final Map<Uri, Source> _sourceCache = new HashMap<Uri, Source>(); | 
 |   70  | 
 |   71   /** | 
 |   72    * Initialize a newly created resolver to be associated with the given | 
 |   73    * [workspace]. | 
 |   74    */ | 
 |   75   GnPackageUriResolver(GnWorkspace workspace) | 
 |   76       : workspace = workspace, | 
 |   77         pathContext = workspace.provider.pathContext, | 
 |   78         _packages = workspace.packages; | 
 |   79  | 
 |   80   @override | 
 |   81   Source resolveAbsolute(Uri uri, [Uri actualUri]) { | 
 |   82     return _sourceCache.putIfAbsent(uri, () { | 
 |   83       if (uri.scheme != 'package') { | 
 |   84         return null; | 
 |   85       } | 
 |   86  | 
 |   87       String uriPath = uri.path; | 
 |   88       int slash = uriPath.indexOf('/'); | 
 |   89  | 
 |   90       // If the path either starts with a slash or has no slash, it is invalid. | 
 |   91       if (slash < 1) { | 
 |   92         return null; | 
 |   93       } | 
 |   94  | 
 |   95       String packageName = uriPath.substring(0, slash); | 
 |   96       String fileUriPart = uriPath.substring(slash + 1); | 
 |   97       String filePath = fileUriPart.replaceAll('/', pathContext.separator); | 
 |   98  | 
 |   99       if (!_packages.containsKey(packageName)) { | 
 |  100         return null; | 
 |  101       } | 
 |  102       String packageBase = _packages[packageName]; | 
 |  103       String path = pathContext.join(packageBase, filePath); | 
 |  104       File file = workspace.findFile(path); | 
 |  105       return file?.createSource(uri); | 
 |  106     }); | 
 |  107   } | 
 |  108  | 
 |  109   @override | 
 |  110   Uri restoreAbsolute(Source source) { | 
 |  111     Context context = workspace.provider.pathContext; | 
 |  112     String path = source.fullName; | 
 |  113  | 
 |  114     if (!context.isWithin(workspace.root, path)) { | 
 |  115       return null; | 
 |  116     } | 
 |  117  | 
 |  118     String package = _packages.keys.firstWhere( | 
 |  119         (key) => context.isWithin(_packages[key], path), | 
 |  120         orElse: () => null); | 
 |  121  | 
 |  122     if (package == null) { | 
 |  123       return null; | 
 |  124     } | 
 |  125  | 
 |  126     String sourcePath = context.relative(path, from: _packages[package]); | 
 |  127  | 
 |  128     return FastUri.parse('package:$package/$sourcePath'); | 
 |  129   } | 
 |  130 } | 
 |  131  | 
 |  132 /** | 
 |  133  * Information about a Gn workspace. | 
 |  134  */ | 
 |  135 class GnWorkspace { | 
 |  136   /** | 
 |  137    * The name of the directory that identifies the root of the workspace. | 
 |  138    */ | 
 |  139   static const String _jiriRootName = '.jiri_root'; | 
 |  140  | 
 |  141   /** | 
 |  142    * The resource provider used to access the file system. | 
 |  143    */ | 
 |  144   final ResourceProvider provider; | 
 |  145  | 
 |  146   /** | 
 |  147    * The absolute workspace root path (the directory containing the `.jiri_root` | 
 |  148    * directory). | 
 |  149    */ | 
 |  150   final String root; | 
 |  151  | 
 |  152   /** | 
 |  153    * The map of package sources indexed by package name. | 
 |  154    */ | 
 |  155   final Map<String, String> packages; | 
 |  156  | 
 |  157   GnWorkspace._(this.provider, this.root, this.packages); | 
 |  158  | 
 |  159   /** | 
 |  160    * Return a map of package sources. | 
 |  161    */ | 
 |  162   Map<String, List<Folder>> get packageMap { | 
 |  163     Map<String, List<Folder>> result = new HashMap<String, List<Folder>>(); | 
 |  164     packages.forEach((package, sourceDir) { | 
 |  165       result[package] = [provider.getFolder(sourceDir)]; | 
 |  166     }); | 
 |  167     return result; | 
 |  168   } | 
 |  169  | 
 |  170   /** | 
 |  171    * Return the file with the given [absolutePath]. | 
 |  172    * | 
 |  173    * Return `null` if the given [absolutePath] is not in the workspace [root]. | 
 |  174    */ | 
 |  175   File findFile(String absolutePath) { | 
 |  176     try { | 
 |  177       File writableFile = provider.getFile(absolutePath); | 
 |  178       return writableFile; | 
 |  179     } catch (_) { | 
 |  180       return null; | 
 |  181     } | 
 |  182   } | 
 |  183  | 
 |  184   /** | 
 |  185    * Locate the output directory. | 
 |  186    * | 
 |  187    * Return `null` if it could not be found. | 
 |  188    */ | 
 |  189   static String _getOutDirectory(ResourceProvider provider, String root) => | 
 |  190       provider | 
 |  191           .getFolder('$root/out') | 
 |  192           .getChildren() | 
 |  193           .where((resource) => resource is Folder) | 
 |  194           .map((resource) => resource as Folder) | 
 |  195           .firstWhere((Folder folder) { | 
 |  196         String baseName = basename(folder.path); | 
 |  197         // TODO(pylaligand): find a better way to locate the proper directory. | 
 |  198         return baseName.startsWith('debug') || baseName.startsWith('release'); | 
 |  199       }, orElse: () => null)?.path; | 
 |  200  | 
 |  201   /** | 
 |  202    * Return a map of package source locations indexed by package name. | 
 |  203    */ | 
 |  204   static Map<String, String> _getPackages( | 
 |  205       ResourceProvider provider, String outDirectory) { | 
 |  206     String packagesDir = '$outDirectory/gen/dart.sources'; | 
 |  207     Map<String, String> result = new HashMap<String, String>(); | 
 |  208     provider | 
 |  209         .getFolder(packagesDir) | 
 |  210         .getChildren() | 
 |  211         .where((resource) => resource is File) | 
 |  212         .map((resource) => resource as File) | 
 |  213         .forEach((file) { | 
 |  214       String packageName = basename(file.path); | 
 |  215       String source = file.readAsStringSync(); | 
 |  216       result[packageName] = source; | 
 |  217     }); | 
 |  218     return result; | 
 |  219   } | 
 |  220  | 
 |  221   /** | 
 |  222    * Find the Gn workspace that contains the given [path]. | 
 |  223    * | 
 |  224    * Return `null` if a workspace markers, such as the `.jiri_root` directory | 
 |  225    * cannot be found. | 
 |  226    */ | 
 |  227   static GnWorkspace find(ResourceProvider provider, String path) { | 
 |  228     Context context = provider.pathContext; | 
 |  229  | 
 |  230     // Ensure that the path is absolute and normalized. | 
 |  231     if (!context.isAbsolute(path)) { | 
 |  232       throw new ArgumentError('not absolute: $path'); | 
 |  233     } | 
 |  234     path = context.normalize(path); | 
 |  235  | 
 |  236     Folder folder = provider.getFolder(path); | 
 |  237     while (true) { | 
 |  238       Folder parent = folder.parent; | 
 |  239       if (parent == null) { | 
 |  240         return null; | 
 |  241       } | 
 |  242  | 
 |  243       // Found the .jiri_root file, must be a non-git workspace. | 
 |  244       if (folder.getChildAssumingFolder(_jiriRootName).exists) { | 
 |  245         String root = folder.path; | 
 |  246         String outDirectory = _getOutDirectory(provider, root); | 
 |  247         Map<String, String> packages = _getPackages(provider, outDirectory); | 
 |  248         return new GnWorkspace._(provider, root, packages); | 
 |  249       } | 
 |  250  | 
 |  251       // Go up the folder. | 
 |  252       folder = parent; | 
 |  253     } | 
 |  254   } | 
 |  255 } | 
| OLD | NEW |