| OLD | NEW | 
|---|
| 1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.package_map_resolver; | 5 library analyzer.source.package_map_resolver; | 
| 6 | 6 | 
| 7 import 'dart:core'; | 7 import 'dart:core'; | 
| 8 | 8 | 
| 9 import 'package:analyzer/file_system/file_system.dart'; | 9 import 'package:analyzer/file_system/file_system.dart'; | 
| 10 import 'package:analyzer/src/generated/source.dart'; | 10 import 'package:analyzer/src/generated/source.dart'; | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 34 | 34 | 
| 35   /** | 35   /** | 
| 36    * Create a new [PackageMapUriResolver]. | 36    * Create a new [PackageMapUriResolver]. | 
| 37    * | 37    * | 
| 38    * [packageMap] is a table mapping package names to the paths of the | 38    * [packageMap] is a table mapping package names to the paths of the | 
| 39    * directories containing the package | 39    * directories containing the package | 
| 40    */ | 40    */ | 
| 41   PackageMapUriResolver(this.resourceProvider, this.packageMap) { | 41   PackageMapUriResolver(this.resourceProvider, this.packageMap) { | 
| 42     asserts.notNull(resourceProvider); | 42     asserts.notNull(resourceProvider); | 
| 43     asserts.notNull(packageMap); | 43     asserts.notNull(packageMap); | 
|  | 44     packageMap.forEach((name, folders) { | 
|  | 45       if (folders.length != 1) { | 
|  | 46         throw new ArgumentError( | 
|  | 47             'Exactly one folder must be specified for a package.' | 
|  | 48             'Found $name = $folders'); | 
|  | 49       } | 
|  | 50     }); | 
| 44   } | 51   } | 
| 45 | 52 | 
| 46   @override | 53   @override | 
| 47   Source resolveAbsolute(Uri uri, [Uri actualUri]) { | 54   Source resolveAbsolute(Uri uri, [Uri actualUri]) { | 
| 48     if (!isPackageUri(uri)) { | 55     if (!isPackageUri(uri)) { | 
| 49       return null; | 56       return null; | 
| 50     } | 57     } | 
| 51     // Prepare path. | 58     // Prepare path. | 
| 52     String path = uri.path; | 59     String path = uri.path; | 
| 53     // Prepare path components. | 60     // Prepare path components. | 
| 54     int index = path.indexOf('/'); | 61     int index = path.indexOf('/'); | 
| 55     if (index == -1 || index == 0) { | 62     if (index == -1 || index == 0) { | 
| 56       return null; | 63       return null; | 
| 57     } | 64     } | 
| 58     // <pkgName>/<relPath> | 65     // <pkgName>/<relPath> | 
| 59     String pkgName = path.substring(0, index); | 66     String pkgName = path.substring(0, index); | 
| 60     String relPath = path.substring(index + 1); | 67     String relPath = path.substring(index + 1); | 
| 61     // Try to find an existing file. | 68     // If the package is known, return the corresponding file. | 
| 62     List<Folder> packageDirs = packageMap[pkgName]; | 69     List<Folder> packageDirs = packageMap[pkgName]; | 
| 63     if (packageDirs != null) { | 70     if (packageDirs != null) { | 
| 64       for (Folder packageDir in packageDirs) { | 71       Folder packageDir = packageDirs.single; | 
| 65         if (packageDir.exists) { | 72       File file = packageDir.getChildAssumingFile(relPath); | 
| 66           Resource result = packageDir.getChild(relPath); | 73       return file.createSource(uri); | 
| 67           if (result is File && result.exists) { |  | 
| 68             return result.createSource(uri); |  | 
| 69           } |  | 
| 70         } |  | 
| 71       } |  | 
| 72     } | 74     } | 
| 73     // Return a NonExistingSource instance. | 75     return null; | 
| 74     // This helps provide more meaningful error messages to users |  | 
| 75     // (a missing file error, as opposed to an invalid URI error). |  | 
| 76     String fullPath = packageDirs != null && packageDirs.isNotEmpty |  | 
| 77         ? packageDirs.first.canonicalizePath(relPath) |  | 
| 78         : relPath; |  | 
| 79     return new NonExistingSource(fullPath, uri, UriKind.PACKAGE_URI); |  | 
| 80   } | 76   } | 
| 81 | 77 | 
| 82   @override | 78   @override | 
| 83   Uri restoreAbsolute(Source source) { | 79   Uri restoreAbsolute(Source source) { | 
| 84     String sourcePath = source.fullName; | 80     String sourcePath = source.fullName; | 
| 85     Uri bestMatch; |  | 
| 86     int bestMatchLength = -1; |  | 
| 87     pathos.Context pathContext = resourceProvider.pathContext; | 81     pathos.Context pathContext = resourceProvider.pathContext; | 
| 88     for (String pkgName in packageMap.keys) { | 82     for (String pkgName in packageMap.keys) { | 
| 89       List<Folder> pkgFolders = packageMap[pkgName]; | 83       Folder pkgFolder = packageMap[pkgName][0]; | 
| 90       for (int i = 0; i < pkgFolders.length; i++) { | 84       String pkgFolderPath = pkgFolder.path; | 
| 91         Folder pkgFolder = pkgFolders[i]; | 85       if (sourcePath.startsWith(pkgFolderPath + pathContext.separator)) { | 
| 92         String pkgFolderPath = pkgFolder.path; | 86         String relPath = sourcePath.substring(pkgFolderPath.length + 1); | 
| 93         if (pkgFolderPath.length > bestMatchLength && | 87         List<String> relPathComponents = pathContext.split(relPath); | 
| 94             sourcePath.startsWith(pkgFolderPath + pathContext.separator)) { | 88         String relUriPath = pathos.posix.joinAll(relPathComponents); | 
| 95           String relPath = sourcePath.substring(pkgFolderPath.length + 1); | 89         return Uri.parse('$PACKAGE_SCHEME:$pkgName/$relUriPath'); | 
| 96           if (_isReversibleTranslation(pkgFolders, i, relPath)) { |  | 
| 97             List<String> relPathComponents = pathContext.split(relPath); |  | 
| 98             String relUriPath = pathos.posix.joinAll(relPathComponents); |  | 
| 99             bestMatch = Uri.parse('$PACKAGE_SCHEME:$pkgName/$relUriPath'); |  | 
| 100             bestMatchLength = pkgFolderPath.length; |  | 
| 101           } |  | 
| 102         } |  | 
| 103       } | 90       } | 
| 104     } | 91     } | 
| 105     return bestMatch; | 92     return null; | 
| 106   } | 93   } | 
| 107 | 94 | 
| 108   /** | 95   /** | 
| 109    * A translation from file path to package URI has just been found for |  | 
| 110    * using the [packageDirIndex]th element of [packageDirs], and appending the |  | 
| 111    * relative path [relPath].  Determine whether the translation is reversible; |  | 
| 112    * that is, whether translating the package URI pack to a file path will |  | 
| 113    * produce the file path we started with. |  | 
| 114    */ |  | 
| 115   bool _isReversibleTranslation( |  | 
| 116       List<Folder> packageDirs, int packageDirIndex, String relPath) { |  | 
| 117     // The translation is reversible provided there is no prior element of |  | 
| 118     // [packageDirs] containing a file matching [relPath]. |  | 
| 119     for (int i = 0; i < packageDirIndex; i++) { |  | 
| 120       Folder packageDir = packageDirs[i]; |  | 
| 121       if (packageDir.exists) { |  | 
| 122         Resource result = packageDir.getChild(relPath); |  | 
| 123         if (result is File && result.exists) { |  | 
| 124           return false; |  | 
| 125         } |  | 
| 126       } |  | 
| 127     } |  | 
| 128     return true; |  | 
| 129   } |  | 
| 130 |  | 
| 131   /** |  | 
| 132    * Returns `true` if [uri] is a `package` URI. | 96    * Returns `true` if [uri] is a `package` URI. | 
| 133    */ | 97    */ | 
| 134   static bool isPackageUri(Uri uri) { | 98   static bool isPackageUri(Uri uri) { | 
| 135     return uri.scheme == PACKAGE_SCHEME; | 99     return uri.scheme == PACKAGE_SCHEME; | 
| 136   } | 100   } | 
| 137 } | 101 } | 
| OLD | NEW | 
|---|