Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
|
Brian Wilkerson
2016/01/28 18:55:41
I've been preserving the copyright from the origin
pquitslund
2016/01/28 18:58:20
Done.
| |
| 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.context.source; | |
| 6 | |
| 7 import 'package:analyzer/file_system/file_system.dart'; | |
| 8 import 'package:analyzer/file_system/physical_file_system.dart'; | |
| 9 import 'package:analyzer/source/package_map_resolver.dart'; | |
| 10 import 'package:analyzer/src/generated/engine.dart'; | |
| 11 import 'package:analyzer/src/generated/java_core.dart'; | |
| 12 import 'package:analyzer/src/generated/java_engine.dart'; | |
| 13 import 'package:analyzer/src/generated/sdk.dart'; | |
| 14 import 'package:analyzer/src/generated/source.dart'; | |
| 15 import 'package:analyzer/src/generated/utilities_dart.dart' as utils; | |
| 16 import 'package:package_config/packages.dart'; | |
| 17 | |
| 18 /** | |
| 19 * Instances of the class `SourceFactory` resolve possibly relative URI's | |
| 20 * against an existing [Source]. | |
| 21 */ | |
| 22 class SourceFactoryImpl implements SourceFactory { | |
|
Brian Wilkerson
2016/01/28 18:55:41
I'm assuming this was just copied and renamed from
pquitslund
2016/01/28 18:58:20
Nope. _resolvers => resolvers is all.
| |
| 23 /** | |
| 24 * The analysis context that this source factory is associated with. | |
| 25 */ | |
| 26 AnalysisContext context; | |
| 27 | |
| 28 /** | |
| 29 * URI processor used to find mappings for `package:` URIs found in a | |
| 30 * `.packages` config file. | |
| 31 */ | |
| 32 final Packages _packages; | |
| 33 | |
| 34 /** | |
| 35 * Resource provider used in working with package maps. | |
| 36 */ | |
| 37 final ResourceProvider _resourceProvider; | |
| 38 | |
| 39 /** | |
| 40 * The resolvers used to resolve absolute URI's. | |
| 41 */ | |
| 42 final List<UriResolver> resolvers; | |
| 43 | |
| 44 /** | |
| 45 * The predicate to determine is [Source] is local. | |
| 46 */ | |
| 47 LocalSourcePredicate _localSourcePredicate = LocalSourcePredicate.NOT_SDK; | |
| 48 | |
| 49 /** | |
| 50 * Initialize a newly created source factory with the given absolute URI | |
| 51 * [resolvers] and optional [packages] resolution helper. | |
| 52 */ | |
| 53 SourceFactoryImpl(this.resolvers, | |
| 54 [this._packages, ResourceProvider resourceProvider]) | |
| 55 : _resourceProvider = resourceProvider != null | |
| 56 ? resourceProvider | |
| 57 : PhysicalResourceProvider.INSTANCE; | |
| 58 | |
| 59 /** | |
| 60 * Return the [DartSdk] associated with this [SourceFactory], or `null` if | |
| 61 * there is no such SDK. | |
| 62 * | |
| 63 * @return the [DartSdk] associated with this [SourceFactory], or `null` if | |
| 64 * there is no such SDK | |
| 65 */ | |
| 66 DartSdk get dartSdk { | |
| 67 for (UriResolver resolver in resolvers) { | |
| 68 if (resolver is DartUriResolver) { | |
| 69 DartUriResolver dartUriResolver = resolver; | |
| 70 return dartUriResolver.dartSdk; | |
| 71 } | |
| 72 } | |
| 73 return null; | |
| 74 } | |
| 75 | |
| 76 /** | |
| 77 * Sets the [LocalSourcePredicate]. | |
| 78 * | |
| 79 * @param localSourcePredicate the predicate to determine is [Source] is local | |
| 80 */ | |
| 81 void set localSourcePredicate(LocalSourcePredicate localSourcePredicate) { | |
| 82 this._localSourcePredicate = localSourcePredicate; | |
| 83 } | |
| 84 | |
| 85 /// A table mapping package names to paths of directories containing | |
| 86 /// the package (or [null] if there is no registered package URI resolver). | |
| 87 Map<String, List<Folder>> get packageMap { | |
| 88 // Start by looking in .packages. | |
| 89 if (_packages != null) { | |
| 90 Map<String, List<Folder>> packageMap = <String, List<Folder>>{}; | |
| 91 _packages.asMap().forEach((String name, Uri uri) { | |
| 92 if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) { | |
| 93 packageMap[name] = <Folder>[ | |
| 94 _resourceProvider.getFolder(uri.toFilePath()) | |
| 95 ]; | |
| 96 } | |
| 97 }); | |
| 98 return packageMap; | |
| 99 } | |
| 100 | |
| 101 // Default to the PackageMapUriResolver. | |
| 102 PackageMapUriResolver resolver = resolvers | |
| 103 .firstWhere((r) => r is PackageMapUriResolver, orElse: () => null); | |
| 104 return resolver != null ? resolver.packageMap : null; | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Return a source factory that will resolve URI's in the same way that this | |
| 109 * source factory does. | |
| 110 */ | |
| 111 SourceFactory clone() { | |
| 112 SourceFactory factory = | |
| 113 new SourceFactory(resolvers, _packages, _resourceProvider); | |
| 114 factory.localSourcePredicate = _localSourcePredicate; | |
| 115 return factory; | |
| 116 } | |
| 117 | |
| 118 /** | |
| 119 * Return a source object representing the given absolute URI, or `null` if | |
| 120 * the URI is not a valid URI or if it is not an absolute URI. | |
| 121 * | |
| 122 * @param absoluteUri the absolute URI to be resolved | |
| 123 * @return a source object representing the absolute URI | |
| 124 */ | |
| 125 Source forUri(String absoluteUri) { | |
| 126 try { | |
| 127 Uri uri = parseUriWithException(absoluteUri); | |
| 128 if (uri.isAbsolute) { | |
| 129 return _internalResolveUri(null, uri); | |
| 130 } | |
| 131 } catch (exception, stackTrace) { | |
| 132 AnalysisEngine.instance.logger.logError( | |
| 133 "Could not resolve URI: $absoluteUri", | |
| 134 new CaughtException(exception, stackTrace)); | |
| 135 } | |
| 136 return null; | |
| 137 } | |
| 138 | |
| 139 /** | |
| 140 * Return a source object representing the given absolute URI, or `null` if | |
| 141 * the URI is not an absolute URI. | |
| 142 * | |
| 143 * @param absoluteUri the absolute URI to be resolved | |
| 144 * @return a source object representing the absolute URI | |
| 145 */ | |
| 146 Source forUri2(Uri absoluteUri) { | |
| 147 if (absoluteUri.isAbsolute) { | |
| 148 try { | |
| 149 return _internalResolveUri(null, absoluteUri); | |
| 150 } on AnalysisException catch (exception, stackTrace) { | |
| 151 AnalysisEngine.instance.logger.logError( | |
| 152 "Could not resolve URI: $absoluteUri", | |
| 153 new CaughtException(exception, stackTrace)); | |
| 154 } | |
| 155 } | |
| 156 return null; | |
| 157 } | |
| 158 | |
| 159 /** | |
| 160 * Return a source object that is equal to the source object used to obtain | |
| 161 * the given encoding. | |
| 162 * | |
| 163 * @param encoding the encoding of a source object | |
| 164 * @return a source object that is described by the given encoding | |
| 165 * @throws IllegalArgumentException if the argument is not a valid encoding | |
| 166 * See [Source.encoding]. | |
| 167 */ | |
| 168 Source fromEncoding(String encoding) { | |
| 169 Source source = forUri(encoding); | |
| 170 if (source == null) { | |
| 171 throw new IllegalArgumentException( | |
| 172 "Invalid source encoding: '$encoding'"); | |
| 173 } | |
| 174 return source; | |
| 175 } | |
| 176 | |
| 177 /** | |
| 178 * Determines if the given [Source] is local. | |
| 179 * | |
| 180 * @param source the [Source] to analyze | |
| 181 * @return `true` if the given [Source] is local | |
| 182 */ | |
| 183 bool isLocalSource(Source source) => _localSourcePredicate.isLocal(source); | |
| 184 | |
| 185 /** | |
| 186 * Return a source representing the URI that results from resolving the given | |
| 187 * (possibly relative) [containedUri] against the URI associated with the | |
| 188 * [containingSource], whether or not the resulting source exists, or `null` | |
| 189 * if either the [containedUri] is invalid or if it cannot be resolved against | |
| 190 * the [containingSource]'s URI. | |
| 191 */ | |
| 192 Source resolveUri(Source containingSource, String containedUri) { | |
| 193 if (containedUri == null || containedUri.isEmpty) { | |
| 194 return null; | |
| 195 } | |
| 196 try { | |
| 197 // Force the creation of an escaped URI to deal with spaces, etc. | |
| 198 return _internalResolveUri( | |
| 199 containingSource, parseUriWithException(containedUri)); | |
| 200 } on URISyntaxException { | |
| 201 return null; | |
| 202 } catch (exception, stackTrace) { | |
| 203 String containingFullName = | |
| 204 containingSource != null ? containingSource.fullName : '<null>'; | |
| 205 AnalysisEngine.instance.logger.logInformation( | |
| 206 "Could not resolve URI ($containedUri) " | |
| 207 "relative to source ($containingFullName)", | |
| 208 new CaughtException(exception, stackTrace)); | |
| 209 return null; | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 /** | |
| 214 * Return an absolute URI that represents the given source, or `null` if a | |
| 215 * valid URI cannot be computed. | |
| 216 * | |
| 217 * @param source the source to get URI for | |
| 218 * @return the absolute URI representing the given source | |
| 219 */ | |
| 220 Uri restoreUri(Source source) { | |
| 221 // First see if a resolver can restore the URI. | |
| 222 for (UriResolver resolver in resolvers) { | |
| 223 Uri uri = resolver.restoreAbsolute(source); | |
| 224 if (uri != null) { | |
| 225 // Now see if there's a package mapping. | |
| 226 Uri packageMappedUri = _getPackageMapping(uri); | |
| 227 if (packageMappedUri != null) { | |
| 228 return packageMappedUri; | |
| 229 } | |
| 230 // Fall back to the resolver's computed URI. | |
| 231 return uri; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 return null; | |
| 236 } | |
| 237 | |
| 238 Uri _getPackageMapping(Uri sourceUri) { | |
| 239 if (_packages == null) { | |
| 240 return null; | |
| 241 } | |
| 242 if (sourceUri.scheme != 'file') { | |
| 243 //TODO(pquitslund): verify this works for non-file URIs. | |
| 244 return null; | |
| 245 } | |
| 246 | |
| 247 Uri packageUri; | |
| 248 _packages.asMap().forEach((String name, Uri uri) { | |
| 249 if (packageUri == null) { | |
| 250 if (utils.startsWith(sourceUri, uri)) { | |
| 251 packageUri = Uri.parse( | |
| 252 'package:$name/${sourceUri.path.substring(uri.path.length)}'); | |
| 253 } | |
| 254 } | |
| 255 }); | |
| 256 return packageUri; | |
| 257 } | |
| 258 | |
| 259 /** | |
| 260 * Return a source object representing the URI that results from resolving | |
| 261 * the given (possibly relative) contained URI against the URI associated | |
| 262 * with an existing source object, or `null` if the URI could not be resolved. | |
| 263 * | |
| 264 * @param containingSource the source containing the given URI | |
| 265 * @param containedUri the (possibly relative) URI to be resolved against the | |
| 266 * containing source | |
| 267 * @return the source representing the contained URI | |
| 268 * @throws AnalysisException if either the contained URI is invalid or if it | |
| 269 * cannot be resolved against the source object's URI | |
| 270 */ | |
| 271 Source _internalResolveUri(Source containingSource, Uri containedUri) { | |
| 272 if (!containedUri.isAbsolute) { | |
| 273 if (containingSource == null) { | |
| 274 throw new AnalysisException( | |
| 275 "Cannot resolve a relative URI without a containing source: " | |
| 276 "$containedUri"); | |
| 277 } | |
| 278 containedUri = containingSource.resolveRelativeUri(containedUri); | |
| 279 } | |
| 280 | |
| 281 Uri actualUri = containedUri; | |
| 282 | |
| 283 // Check .packages and update target and actual URIs as appropriate. | |
| 284 if (_packages != null && containedUri.scheme == 'package') { | |
| 285 Uri packageUri = null; | |
| 286 try { | |
| 287 packageUri = | |
| 288 _packages.resolve(containedUri, notFound: (Uri packageUri) => null); | |
| 289 } on ArgumentError { | |
| 290 // Fall through to try resolvers. | |
| 291 } | |
| 292 | |
| 293 if (packageUri != null) { | |
| 294 // Ensure scheme is set. | |
| 295 if (packageUri.scheme == '') { | |
| 296 packageUri = packageUri.replace(scheme: 'file'); | |
| 297 } | |
| 298 containedUri = packageUri; | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 for (UriResolver resolver in resolvers) { | |
| 303 Source result = resolver.resolveAbsolute(containedUri, actualUri); | |
| 304 if (result != null) { | |
| 305 return result; | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 return null; | |
| 310 } | |
| 311 } | |
| OLD | NEW |