| 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 // This code was auto-generated, is not intended to be edited, and is subject to | 5 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. | 6 // significant change. Please see the README file for more information. |
| 7 | 7 |
| 8 library engine.source; | 8 library engine.source; |
| 9 | 9 |
| 10 import 'java_core.dart'; | 10 import 'java_core.dart'; |
| 11 import 'sdk.dart' show DartSdk; | 11 import 'sdk.dart' show DartSdk; |
| 12 import 'engine.dart' show AnalysisContext, TimestampedData; | 12 import 'engine.dart' show AnalysisContext, TimestampedData; |
| 13 | 13 |
| 14 /** | 14 /** |
| 15 * Instances of interface `LocalSourcePredicate` are used to determine if the gi
ven | |
| 16 * [Source] is "local" in some sense, so can be updated. | |
| 17 */ | |
| 18 abstract class LocalSourcePredicate { | |
| 19 /** | |
| 20 * Instance of [LocalSourcePredicate] that always returns `false`. | |
| 21 */ | |
| 22 static final LocalSourcePredicate FALSE = new LocalSourcePredicate_FALSE(); | |
| 23 | |
| 24 /** | |
| 25 * Instance of [LocalSourcePredicate] that always returns `true`. | |
| 26 */ | |
| 27 static final LocalSourcePredicate TRUE = new LocalSourcePredicate_TRUE(); | |
| 28 | |
| 29 /** | |
| 30 * Instance of [LocalSourcePredicate] that returns `true` for all [Source]s | |
| 31 * except of SDK. | |
| 32 */ | |
| 33 static final LocalSourcePredicate NOT_SDK = new LocalSourcePredicate_NOT_SDK()
; | |
| 34 | |
| 35 /** | |
| 36 * Determines if the given [Source] is local. | |
| 37 * | |
| 38 * @param source the [Source] to analyze | |
| 39 * @return `true` if the given [Source] is local | |
| 40 */ | |
| 41 bool isLocal(Source source); | |
| 42 } | |
| 43 | |
| 44 class LocalSourcePredicate_FALSE implements LocalSourcePredicate { | |
| 45 @override | |
| 46 bool isLocal(Source source) => false; | |
| 47 } | |
| 48 | |
| 49 class LocalSourcePredicate_TRUE implements LocalSourcePredicate { | |
| 50 @override | |
| 51 bool isLocal(Source source) => true; | |
| 52 } | |
| 53 | |
| 54 class LocalSourcePredicate_NOT_SDK implements LocalSourcePredicate { | |
| 55 @override | |
| 56 bool isLocal(Source source) => source.uriKind != UriKind.DART_URI; | |
| 57 } | |
| 58 | |
| 59 /** | |
| 60 * Instances of the class `SourceFactory` resolve possibly relative URI's agains
t an existing | |
| 61 * [Source]. | |
| 62 */ | |
| 63 class SourceFactory { | |
| 64 /** | |
| 65 * The analysis context that this source factory is associated with. | |
| 66 */ | |
| 67 AnalysisContext context; | |
| 68 | |
| 69 /** | |
| 70 * The resolvers used to resolve absolute URI's. | |
| 71 */ | |
| 72 final List<UriResolver> _resolvers; | |
| 73 | |
| 74 /** | |
| 75 * The predicate to determine is [Source] is local. | |
| 76 */ | |
| 77 LocalSourcePredicate _localSourcePredicate = LocalSourcePredicate.NOT_SDK; | |
| 78 | |
| 79 /** | |
| 80 * Initialize a newly created source factory. | |
| 81 * | |
| 82 * @param resolvers the resolvers used to resolve absolute URI's | |
| 83 */ | |
| 84 SourceFactory(this._resolvers); | |
| 85 | |
| 86 /** | |
| 87 * Return a source object representing the given absolute URI, or `null` if th
e URI is not a | |
| 88 * valid URI or if it is not an absolute URI. | |
| 89 * | |
| 90 * @param absoluteUri the absolute URI to be resolved | |
| 91 * @return a source object representing the absolute URI | |
| 92 */ | |
| 93 Source forUri(String absoluteUri) { | |
| 94 try { | |
| 95 Uri uri = parseUriWithException(absoluteUri); | |
| 96 if (uri.isAbsolute) { | |
| 97 return _internalResolveUri(null, uri); | |
| 98 } | |
| 99 } on URISyntaxException catch (exception) { | |
| 100 } | |
| 101 return null; | |
| 102 } | |
| 103 | |
| 104 /** | |
| 105 * Return a source object that is equal to the source object used to obtain th
e given encoding. | |
| 106 * | |
| 107 * @param encoding the encoding of a source object | |
| 108 * @return a source object that is described by the given encoding | |
| 109 * @throws IllegalArgumentException if the argument is not a valid encoding | |
| 110 * @see Source#getEncoding() | |
| 111 */ | |
| 112 Source fromEncoding(String encoding) { | |
| 113 if (encoding.length < 2) { | |
| 114 throw new IllegalArgumentException("Invalid encoding length"); | |
| 115 } | |
| 116 UriKind kind = UriKind.fromEncoding(encoding.codeUnitAt(0)); | |
| 117 if (kind == null) { | |
| 118 throw new IllegalArgumentException("Invalid source kind in encoding: ${kin
d}"); | |
| 119 } | |
| 120 try { | |
| 121 Uri uri = parseUriWithException(encoding.substring(1)); | |
| 122 for (UriResolver resolver in _resolvers) { | |
| 123 Source result = resolver.fromEncoding(kind, uri); | |
| 124 if (result != null) { | |
| 125 return result; | |
| 126 } | |
| 127 } | |
| 128 throw new IllegalArgumentException("No resolver for kind: ${kind}"); | |
| 129 } on JavaException catch (exception) { | |
| 130 throw new IllegalArgumentException("Invalid URI in encoding"); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 /** | |
| 135 * Return the [DartSdk] associated with this [SourceFactory], or `null` if the
re | |
| 136 * is no such SDK. | |
| 137 * | |
| 138 * @return the [DartSdk] associated with this [SourceFactory], or `null` if | |
| 139 * there is no such SDK | |
| 140 */ | |
| 141 DartSdk get dartSdk { | |
| 142 for (UriResolver resolver in _resolvers) { | |
| 143 if (resolver is DartUriResolver) { | |
| 144 DartUriResolver dartUriResolver = resolver; | |
| 145 return dartUriResolver.dartSdk; | |
| 146 } | |
| 147 } | |
| 148 return null; | |
| 149 } | |
| 150 | |
| 151 /** | |
| 152 * Determines if the given [Source] is local. | |
| 153 * | |
| 154 * @param source the [Source] to analyze | |
| 155 * @return `true` if the given [Source] is local | |
| 156 */ | |
| 157 bool isLocalSource(Source source) => _localSourcePredicate.isLocal(source); | |
| 158 | |
| 159 /** | |
| 160 * Return a source object representing the URI that results from resolving the
given (possibly | |
| 161 * relative) contained URI against the URI associated with an existing source
object, whether or | |
| 162 * not the resulting source exists, or `null` if either the contained URI is i
nvalid or if | |
| 163 * it cannot be resolved against the source object's URI. | |
| 164 * | |
| 165 * @param containingSource the source containing the given URI | |
| 166 * @param containedUri the (possibly relative) URI to be resolved against the
containing source | |
| 167 * @return the source representing the contained URI | |
| 168 */ | |
| 169 Source resolveUri(Source containingSource, String containedUri) { | |
| 170 if (containedUri == null || containedUri.isEmpty) { | |
| 171 return null; | |
| 172 } | |
| 173 try { | |
| 174 // Force the creation of an escaped URI to deal with spaces, etc. | |
| 175 return _internalResolveUri(containingSource, parseUriWithException(contain
edUri)); | |
| 176 } on URISyntaxException catch (exception) { | |
| 177 return null; | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 /** | |
| 182 * Return an absolute URI that represents the given source, or `null` if a val
id URI cannot | |
| 183 * be computed. | |
| 184 * | |
| 185 * @param source the source to get URI for | |
| 186 * @return the absolute URI representing the given source | |
| 187 */ | |
| 188 Uri restoreUri(Source source) { | |
| 189 for (UriResolver resolver in _resolvers) { | |
| 190 Uri uri = resolver.restoreAbsolute(source); | |
| 191 if (uri != null) { | |
| 192 return uri; | |
| 193 } | |
| 194 } | |
| 195 return null; | |
| 196 } | |
| 197 | |
| 198 /** | |
| 199 * Sets the [LocalSourcePredicate]. | |
| 200 * | |
| 201 * @param localSourcePredicate the predicate to determine is [Source] is local | |
| 202 */ | |
| 203 void set localSourcePredicate(LocalSourcePredicate localSourcePredicate) { | |
| 204 this._localSourcePredicate = localSourcePredicate; | |
| 205 } | |
| 206 | |
| 207 /** | |
| 208 * Return a source object representing the URI that results from resolving the
given (possibly | |
| 209 * relative) contained URI against the URI associated with an existing source
object, or | |
| 210 * `null` if either the contained URI is invalid or if it cannot be resolved a
gainst the | |
| 211 * source object's URI. | |
| 212 * | |
| 213 * @param containingSource the source containing the given URI | |
| 214 * @param containedUri the (possibly relative) URI to be resolved against the
containing source | |
| 215 * @return the source representing the contained URI | |
| 216 */ | |
| 217 Source _internalResolveUri(Source containingSource, Uri containedUri) { | |
| 218 if (containedUri.isAbsolute) { | |
| 219 for (UriResolver resolver in _resolvers) { | |
| 220 Source result = resolver.resolveAbsolute(containedUri); | |
| 221 if (result != null) { | |
| 222 return result; | |
| 223 } | |
| 224 } | |
| 225 return null; | |
| 226 } else { | |
| 227 return containingSource.resolveRelative(containedUri); | |
| 228 } | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 /** | |
| 233 * The abstract class `UriResolver` defines the behavior of objects that are use
d to resolve | 15 * The abstract class `UriResolver` defines the behavior of objects that are use
d to resolve |
| 234 * URI's for a source factory. Subclasses of this class are expected to resolve
a single scheme of | 16 * URI's for a source factory. Subclasses of this class are expected to resolve
a single scheme of |
| 235 * absolute URI. | 17 * absolute URI. |
| 236 */ | 18 */ |
| 237 abstract class UriResolver { | 19 abstract class UriResolver { |
| 238 /** | 20 /** |
| 239 * If this resolver should be used for URI's of the given kind, resolve the gi
ven absolute URI. | 21 * If this resolver should be used for URI's of the given kind, resolve the gi
ven absolute URI. |
| 240 * The URI does not need to have the scheme handled by this resolver if the ki
nd matches. Return a | 22 * The URI does not need to have the scheme handled by this resolver if the ki
nd matches. Return a |
| 241 * [Source] representing the file to which it was resolved, whether or not the | 23 * [Source] representing the file to which it was resolved, whether or not the |
| 242 * resulting source exists, or `null` if it could not be resolved because the
URI is | 24 * resulting source exists, or `null` if it could not be resolved because the
URI is |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 /** | 204 /** |
| 423 * Accept the contents of a source. | 205 * Accept the contents of a source. |
| 424 * | 206 * |
| 425 * @param contents the contents of the source | 207 * @param contents the contents of the source |
| 426 * @param modificationTime the time at which the contents were last set | 208 * @param modificationTime the time at which the contents were last set |
| 427 */ | 209 */ |
| 428 void accept(String contents, int modificationTime); | 210 void accept(String contents, int modificationTime); |
| 429 } | 211 } |
| 430 | 212 |
| 431 /** | 213 /** |
| 432 * The enumeration `SourceKind` defines the different kinds of sources that are
known to the | 214 * Instances of interface `LocalSourcePredicate` are used to determine if the gi
ven |
| 433 * analysis engine. | 215 * [Source] is "local" in some sense, so can be updated. |
| 434 */ | 216 */ |
| 435 class SourceKind extends Enum<SourceKind> { | 217 abstract class LocalSourcePredicate { |
| 436 /** | 218 /** |
| 437 * A source containing HTML. The HTML might or might not contain Dart scripts. | 219 * Instance of [LocalSourcePredicate] that always returns `false`. |
| 438 */ | 220 */ |
| 439 static const SourceKind HTML = const SourceKind('HTML', 0); | 221 static final LocalSourcePredicate FALSE = new LocalSourcePredicate_FALSE(); |
| 440 | 222 |
| 441 /** | 223 /** |
| 442 * A Dart compilation unit that is not a part of another library. Libraries mi
ght or might not | 224 * Instance of [LocalSourcePredicate] that always returns `true`. |
| 443 * contain any directives, including a library directive. | 225 */ |
| 444 */ | 226 static final LocalSourcePredicate TRUE = new LocalSourcePredicate_TRUE(); |
| 445 static const SourceKind LIBRARY = const SourceKind('LIBRARY', 1); | 227 |
| 446 | 228 /** |
| 447 /** | 229 * Instance of [LocalSourcePredicate] that returns `true` for all [Source]s |
| 448 * A Dart compilation unit that is part of another library. Parts contain a pa
rt-of directive. | 230 * except of SDK. |
| 449 */ | 231 */ |
| 450 static const SourceKind PART = const SourceKind('PART', 2); | 232 static final LocalSourcePredicate NOT_SDK = new LocalSourcePredicate_NOT_SDK()
; |
| 451 | 233 |
| 452 /** | 234 /** |
| 453 * An unknown kind of source. Used both when it is not possible to identify th
e kind of a source | 235 * Determines if the given [Source] is local. |
| 454 * and also when the kind of a source is not known without performing a comput
ation and the client | 236 * |
| 455 * does not want to spend the time to identify the kind. | 237 * @param source the [Source] to analyze |
| 456 */ | 238 * @return `true` if the given [Source] is local |
| 457 static const SourceKind UNKNOWN = const SourceKind('UNKNOWN', 3); | 239 */ |
| 458 | 240 bool isLocal(Source source); |
| 459 static const List<SourceKind> values = const [HTML, LIBRARY, PART, UNKNOWN]; | 241 } |
| 460 | 242 |
| 461 const SourceKind(String name, int ordinal) : super(name, ordinal); | 243 class LocalSourcePredicate_FALSE implements LocalSourcePredicate { |
| 462 } | 244 @override |
| 463 | 245 bool isLocal(Source source) => false; |
| 464 /** | 246 } |
| 465 * The enumeration `UriKind` defines the different kinds of URI's that are known
to the | 247 |
| 466 * analysis engine. These are used to keep track of the kind of URI associated w
ith a given source. | 248 class LocalSourcePredicate_TRUE implements LocalSourcePredicate { |
| 467 */ | 249 @override |
| 468 class UriKind extends Enum<UriKind> { | 250 bool isLocal(Source source) => true; |
| 469 /** | 251 } |
| 470 * A 'dart:' URI. | 252 |
| 471 */ | 253 class LocalSourcePredicate_NOT_SDK implements LocalSourcePredicate { |
| 472 static const UriKind DART_URI = const UriKind('DART_URI', 0, 0x64); | 254 @override |
| 473 | 255 bool isLocal(Source source) => source.uriKind != UriKind.DART_URI; |
| 474 /** | 256 } |
| 475 * A 'file:' URI. | 257 |
| 476 */ | 258 /** |
| 477 static const UriKind FILE_URI = const UriKind('FILE_URI', 1, 0x66); | 259 * Instances of the class `LineInfo` encapsulate information about line and colu
mn information |
| 478 | 260 * within a source file. |
| 479 /** | 261 */ |
| 480 * A 'package:' URI referencing source package itself. | 262 class LineInfo { |
| 481 */ | 263 /** |
| 482 static const UriKind PACKAGE_SELF_URI = const UriKind('PACKAGE_SELF_URI', 2, 0
x73); | 264 * An array containing the offsets of the first character of each line in the
source code. |
| 483 | 265 */ |
| 484 /** | 266 final List<int> _lineStarts; |
| 485 * A 'package:' URI. | 267 |
| 486 */ | 268 /** |
| 487 static const UriKind PACKAGE_URI = const UriKind('PACKAGE_URI', 3, 0x70); | 269 * Initialize a newly created set of line information to represent the data en
coded in the given |
| 488 | 270 * array. |
| 489 static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_SELF_UR
I, PACKAGE_URI]; | 271 * |
| 490 | 272 * @param lineStarts the offsets of the first character of each line in the so
urce code |
| 491 /** | 273 */ |
| 492 * Return the URI kind represented by the given encoding, or `null` if there i
s no kind with | 274 LineInfo(this._lineStarts) { |
| 493 * the given encoding. | 275 if (_lineStarts == null) { |
| 494 * | 276 throw new IllegalArgumentException("lineStarts must be non-null"); |
| 495 * @param encoding the single character encoding used to identify the URI kind
to be returned | 277 } else if (_lineStarts.length < 1) { |
| 496 * @return the URI kind represented by the given encoding | 278 throw new IllegalArgumentException("lineStarts must be non-empty"); |
| 497 */ | 279 } |
| 498 static UriKind fromEncoding(int encoding) { | 280 } |
| 499 while (true) { | 281 |
| 500 if (encoding == 0x64) { | 282 /** |
| 501 return DART_URI; | 283 * Return the location information for the character at the given offset. |
| 502 } else if (encoding == 0x66) { | 284 * |
| 503 return FILE_URI; | 285 * @param offset the offset of the character for which location information is
to be returned |
| 504 } else if (encoding == 0x73) { | 286 * @return the location information for the character at the given offset |
| 505 return PACKAGE_SELF_URI; | 287 */ |
| 506 } else if (encoding == 0x70) { | 288 LineInfo_Location getLocation(int offset) { |
| 507 return PACKAGE_URI; | 289 int lineCount = _lineStarts.length; |
| 508 } | 290 for (int i = 1; i < lineCount; i++) { |
| 509 break; | 291 if (offset < _lineStarts[i]) { |
| 292 return new LineInfo_Location(i, offset - _lineStarts[i - 1] + 1); |
| 293 } |
| 294 } |
| 295 return new LineInfo_Location(lineCount, offset - _lineStarts[lineCount - 1]
+ 1); |
| 296 } |
| 297 } |
| 298 |
| 299 /** |
| 300 * Instances of the class `Location` represent the location of a character as a
line and |
| 301 * column pair. |
| 302 */ |
| 303 class LineInfo_Location { |
| 304 /** |
| 305 * The one-based index of the line containing the character. |
| 306 */ |
| 307 final int lineNumber; |
| 308 |
| 309 /** |
| 310 * The one-based index of the column containing the character. |
| 311 */ |
| 312 final int columnNumber; |
| 313 |
| 314 /** |
| 315 * Initialize a newly created location to represent the location of the charac
ter at the given |
| 316 * line and column position. |
| 317 * |
| 318 * @param lineNumber the one-based index of the line containing the character |
| 319 * @param columnNumber the one-based index of the column containing the charac
ter |
| 320 */ |
| 321 LineInfo_Location(this.lineNumber, this.columnNumber); |
| 322 } |
| 323 |
| 324 /** |
| 325 * Instances of class `ContentCache` hold content used to override the default c
ontent of a |
| 326 * [Source]. |
| 327 */ |
| 328 class ContentCache { |
| 329 /** |
| 330 * A table mapping sources to the contents of those sources. This is used to o
verride the default |
| 331 * contents of a source. |
| 332 */ |
| 333 Map<Source, String> _contentMap = new Map<Source, String>(); |
| 334 |
| 335 /** |
| 336 * A table mapping sources to the modification stamps of those sources. This i
s used when the |
| 337 * default contents of a source has been overridden. |
| 338 */ |
| 339 Map<Source, int> _stampMap = new Map<Source, int>(); |
| 340 |
| 341 /** |
| 342 * Return the contents of the given source, or `null` if this cache does not o
verride the |
| 343 * contents of the source. |
| 344 * |
| 345 * <b>Note:</b> This method is not intended to be used except by |
| 346 * [AnalysisContext#getContents]. |
| 347 * |
| 348 * @param source the source whose content is to be returned |
| 349 * @return the contents of the given source |
| 350 */ |
| 351 String getContents(Source source) => _contentMap[source]; |
| 352 |
| 353 /** |
| 354 * Return the modification stamp of the given source, or `null` if this cache
does not |
| 355 * override the contents of the source. |
| 356 * |
| 357 * <b>Note:</b> This method is not intended to be used except by |
| 358 * [AnalysisContext#getModificationStamp]. |
| 359 * |
| 360 * @param source the source whose modification stamp is to be returned |
| 361 * @return the modification stamp of the given source |
| 362 */ |
| 363 int getModificationStamp(Source source) => _stampMap[source]; |
| 364 |
| 365 /** |
| 366 * Set the contents of the given source to the given contents. This has the ef
fect of overriding |
| 367 * the default contents of the source. If the contents are `null` the override
is removed so |
| 368 * that the default contents will be returned. |
| 369 * |
| 370 * @param source the source whose contents are being overridden |
| 371 * @param contents the new contents of the source |
| 372 * @return the original cached contents or `null` if none |
| 373 */ |
| 374 String setContents(Source source, String contents) { |
| 375 if (contents == null) { |
| 376 _stampMap.remove(source); |
| 377 return _contentMap.remove(source); |
| 378 } else { |
| 379 int newStamp = JavaSystem.currentTimeMillis(); |
| 380 int oldStamp = javaMapPut(_stampMap, source, newStamp); |
| 381 // Occasionally, if this method is called in rapid succession, the timesta
mps are equal. |
| 382 // Guard against this by artificially incrementing the new timestamp |
| 383 if (newStamp == oldStamp) { |
| 384 _stampMap[source] = newStamp + 1; |
| 385 } |
| 386 return javaMapPut(_contentMap, source, contents); |
| 387 } |
| 388 } |
| 389 } |
| 390 |
| 391 /** |
| 392 * Instances of the class `DartUriResolver` resolve `dart` URI's. |
| 393 */ |
| 394 class DartUriResolver extends UriResolver { |
| 395 /** |
| 396 * Return `true` if the given URI is a `dart-ext:` URI. |
| 397 * |
| 398 * @param uriContent the textual representation of the URI being tested |
| 399 * @return `true` if the given URI is a `dart-ext:` URI |
| 400 */ |
| 401 static bool isDartExtUri(String uriContent) => uriContent != null && uriConten
t.startsWith(_DART_EXT_SCHEME); |
| 402 |
| 403 /** |
| 404 * The Dart SDK against which URI's are to be resolved. |
| 405 */ |
| 406 final DartSdk _sdk; |
| 407 |
| 408 /** |
| 409 * The name of the `dart` scheme. |
| 410 */ |
| 411 static String _DART_SCHEME = "dart"; |
| 412 |
| 413 /** |
| 414 * The prefix of a URI using the dart-ext scheme to reference a native code li
brary. |
| 415 */ |
| 416 static String _DART_EXT_SCHEME = "dart-ext:"; |
| 417 |
| 418 /** |
| 419 * Return `true` if the given URI is a `dart:` URI. |
| 420 * |
| 421 * @param uri the URI being tested |
| 422 * @return `true` if the given URI is a `dart:` URI |
| 423 */ |
| 424 static bool isDartUri(Uri uri) => _DART_SCHEME == uri.scheme; |
| 425 |
| 426 /** |
| 427 * Initialize a newly created resolver to resolve Dart URI's against the given
platform within the |
| 428 * given Dart SDK. |
| 429 * |
| 430 * @param sdk the Dart SDK against which URI's are to be resolved |
| 431 */ |
| 432 DartUriResolver(this._sdk); |
| 433 |
| 434 @override |
| 435 Source fromEncoding(UriKind kind, Uri uri) { |
| 436 if (kind == UriKind.DART_URI) { |
| 437 return _sdk.fromEncoding(kind, uri); |
| 510 } | 438 } |
| 511 return null; | 439 return null; |
| 512 } | 440 } |
| 513 | 441 |
| 514 /** | 442 /** |
| 515 * The single character encoding used to identify this kind of URI. | 443 * Return the [DartSdk] against which URIs are to be resolved. |
| 516 */ | 444 * |
| 517 final int encoding; | 445 * @return the [DartSdk] against which URIs are to be resolved. |
| 518 | 446 */ |
| 519 /** | 447 DartSdk get dartSdk => _sdk; |
| 520 * Initialize a newly created URI kind to have the given encoding. | 448 |
| 521 * | 449 @override |
| 522 * @param encoding the single character encoding used to identify this kind of
URI. | 450 Source resolveAbsolute(Uri uri) { |
| 523 */ | 451 if (!isDartUri(uri)) { |
| 524 const UriKind(String name, int ordinal, this.encoding) : super(name, ordinal); | 452 return null; |
| 525 } | 453 } |
| 526 | 454 return _sdk.mapDartUri(uri.toString()); |
| 527 /** | 455 } |
| 456 } |
| 457 |
| 458 /** |
| 459 * Instances of the class `SourceFactory` resolve possibly relative URI's agains
t an existing |
| 460 * [Source]. |
| 461 */ |
| 462 class SourceFactory { |
| 463 /** |
| 464 * The analysis context that this source factory is associated with. |
| 465 */ |
| 466 AnalysisContext context; |
| 467 |
| 468 /** |
| 469 * The resolvers used to resolve absolute URI's. |
| 470 */ |
| 471 final List<UriResolver> _resolvers; |
| 472 |
| 473 /** |
| 474 * The predicate to determine is [Source] is local. |
| 475 */ |
| 476 LocalSourcePredicate _localSourcePredicate = LocalSourcePredicate.NOT_SDK; |
| 477 |
| 478 /** |
| 479 * Initialize a newly created source factory. |
| 480 * |
| 481 * @param resolvers the resolvers used to resolve absolute URI's |
| 482 */ |
| 483 SourceFactory(this._resolvers); |
| 484 |
| 485 /** |
| 486 * Return a source object representing the given absolute URI, or `null` if th
e URI is not a |
| 487 * valid URI or if it is not an absolute URI. |
| 488 * |
| 489 * @param absoluteUri the absolute URI to be resolved |
| 490 * @return a source object representing the absolute URI |
| 491 */ |
| 492 Source forUri(String absoluteUri) { |
| 493 try { |
| 494 Uri uri = parseUriWithException(absoluteUri); |
| 495 if (uri.isAbsolute) { |
| 496 return _internalResolveUri(null, uri); |
| 497 } |
| 498 } on URISyntaxException catch (exception) { |
| 499 } |
| 500 return null; |
| 501 } |
| 502 |
| 503 /** |
| 504 * Return a source object that is equal to the source object used to obtain th
e given encoding. |
| 505 * |
| 506 * @param encoding the encoding of a source object |
| 507 * @return a source object that is described by the given encoding |
| 508 * @throws IllegalArgumentException if the argument is not a valid encoding |
| 509 * @see Source#getEncoding() |
| 510 */ |
| 511 Source fromEncoding(String encoding) { |
| 512 if (encoding.length < 2) { |
| 513 throw new IllegalArgumentException("Invalid encoding length"); |
| 514 } |
| 515 UriKind kind = UriKind.fromEncoding(encoding.codeUnitAt(0)); |
| 516 if (kind == null) { |
| 517 throw new IllegalArgumentException("Invalid source kind in encoding: ${kin
d}"); |
| 518 } |
| 519 try { |
| 520 Uri uri = parseUriWithException(encoding.substring(1)); |
| 521 for (UriResolver resolver in _resolvers) { |
| 522 Source result = resolver.fromEncoding(kind, uri); |
| 523 if (result != null) { |
| 524 return result; |
| 525 } |
| 526 } |
| 527 throw new IllegalArgumentException("No resolver for kind: ${kind}"); |
| 528 } on JavaException catch (exception) { |
| 529 throw new IllegalArgumentException("Invalid URI in encoding"); |
| 530 } |
| 531 } |
| 532 |
| 533 /** |
| 534 * Return the [DartSdk] associated with this [SourceFactory], or `null` if the
re |
| 535 * is no such SDK. |
| 536 * |
| 537 * @return the [DartSdk] associated with this [SourceFactory], or `null` if |
| 538 * there is no such SDK |
| 539 */ |
| 540 DartSdk get dartSdk { |
| 541 for (UriResolver resolver in _resolvers) { |
| 542 if (resolver is DartUriResolver) { |
| 543 DartUriResolver dartUriResolver = resolver; |
| 544 return dartUriResolver.dartSdk; |
| 545 } |
| 546 } |
| 547 return null; |
| 548 } |
| 549 |
| 550 /** |
| 551 * Determines if the given [Source] is local. |
| 552 * |
| 553 * @param source the [Source] to analyze |
| 554 * @return `true` if the given [Source] is local |
| 555 */ |
| 556 bool isLocalSource(Source source) => _localSourcePredicate.isLocal(source); |
| 557 |
| 558 /** |
| 559 * Return a source object representing the URI that results from resolving the
given (possibly |
| 560 * relative) contained URI against the URI associated with an existing source
object, whether or |
| 561 * not the resulting source exists, or `null` if either the contained URI is i
nvalid or if |
| 562 * it cannot be resolved against the source object's URI. |
| 563 * |
| 564 * @param containingSource the source containing the given URI |
| 565 * @param containedUri the (possibly relative) URI to be resolved against the
containing source |
| 566 * @return the source representing the contained URI |
| 567 */ |
| 568 Source resolveUri(Source containingSource, String containedUri) { |
| 569 if (containedUri == null || containedUri.isEmpty) { |
| 570 return null; |
| 571 } |
| 572 try { |
| 573 // Force the creation of an escaped URI to deal with spaces, etc. |
| 574 return _internalResolveUri(containingSource, parseUriWithException(contain
edUri)); |
| 575 } on URISyntaxException catch (exception) { |
| 576 return null; |
| 577 } |
| 578 } |
| 579 |
| 580 /** |
| 581 * Return an absolute URI that represents the given source, or `null` if a val
id URI cannot |
| 582 * be computed. |
| 583 * |
| 584 * @param source the source to get URI for |
| 585 * @return the absolute URI representing the given source |
| 586 */ |
| 587 Uri restoreUri(Source source) { |
| 588 for (UriResolver resolver in _resolvers) { |
| 589 Uri uri = resolver.restoreAbsolute(source); |
| 590 if (uri != null) { |
| 591 return uri; |
| 592 } |
| 593 } |
| 594 return null; |
| 595 } |
| 596 |
| 597 /** |
| 598 * Sets the [LocalSourcePredicate]. |
| 599 * |
| 600 * @param localSourcePredicate the predicate to determine is [Source] is local |
| 601 */ |
| 602 void set localSourcePredicate(LocalSourcePredicate localSourcePredicate) { |
| 603 this._localSourcePredicate = localSourcePredicate; |
| 604 } |
| 605 |
| 606 /** |
| 607 * Return a source object representing the URI that results from resolving the
given (possibly |
| 608 * relative) contained URI against the URI associated with an existing source
object, or |
| 609 * `null` if either the contained URI is invalid or if it cannot be resolved a
gainst the |
| 610 * source object's URI. |
| 611 * |
| 612 * @param containingSource the source containing the given URI |
| 613 * @param containedUri the (possibly relative) URI to be resolved against the
containing source |
| 614 * @return the source representing the contained URI |
| 615 */ |
| 616 Source _internalResolveUri(Source containingSource, Uri containedUri) { |
| 617 if (containedUri.isAbsolute) { |
| 618 for (UriResolver resolver in _resolvers) { |
| 619 Source result = resolver.resolveAbsolute(containedUri); |
| 620 if (result != null) { |
| 621 return result; |
| 622 } |
| 623 } |
| 624 return null; |
| 625 } else { |
| 626 return containingSource.resolveRelative(containedUri); |
| 627 } |
| 628 } |
| 629 } |
| 630 |
| 631 /** |
| 632 * The interface `SourceContainer` is used by clients to define a collection of
sources |
| 633 * |
| 634 * Source containers are not used within analysis engine, but can be used by cli
ents to group |
| 635 * sources for the purposes of accessing composite dependency information. For e
xample, the Eclipse |
| 636 * client uses source containers to represent Eclipse projects, which allows it
to easily compute |
| 637 * project-level dependencies. |
| 638 */ |
| 639 abstract class SourceContainer { |
| 640 /** |
| 641 * Determine if the specified source is part of the receiver's collection of s
ources. |
| 642 * |
| 643 * @param source the source in question |
| 644 * @return `true` if the receiver contains the source, else `false` |
| 645 */ |
| 646 bool contains(Source source); |
| 647 } |
| 648 |
| 649 /** |
| 528 * A source range defines an [Element]'s source coordinates relative to its [Sou
rce]. | 650 * A source range defines an [Element]'s source coordinates relative to its [Sou
rce]. |
| 529 */ | 651 */ |
| 530 class SourceRange { | 652 class SourceRange { |
| 531 /** | 653 /** |
| 532 * An empty [SourceRange] with offset `0` and length `0`. | 654 * An empty [SourceRange] with offset `0` and length `0`. |
| 533 */ | 655 */ |
| 534 static SourceRange EMPTY = new SourceRange(0, 0); | 656 static SourceRange EMPTY = new SourceRange(0, 0); |
| 535 | 657 |
| 536 /** | 658 /** |
| 537 * The 0-based index of the first character of the source code for this elemen
t, relative to the | 659 * The 0-based index of the first character of the source code for this elemen
t, relative to the |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 builder.append("[offset="); | 772 builder.append("[offset="); |
| 651 builder.append(offset); | 773 builder.append(offset); |
| 652 builder.append(", length="); | 774 builder.append(", length="); |
| 653 builder.append(length); | 775 builder.append(length); |
| 654 builder.append("]"); | 776 builder.append("]"); |
| 655 return builder.toString(); | 777 return builder.toString(); |
| 656 } | 778 } |
| 657 } | 779 } |
| 658 | 780 |
| 659 /** | 781 /** |
| 660 * The interface `SourceContainer` is used by clients to define a collection of
sources | 782 * The enumeration `SourceKind` defines the different kinds of sources that are
known to the |
| 661 * | 783 * analysis engine. |
| 662 * Source containers are not used within analysis engine, but can be used by cli
ents to group | |
| 663 * sources for the purposes of accessing composite dependency information. For e
xample, the Eclipse | |
| 664 * client uses source containers to represent Eclipse projects, which allows it
to easily compute | |
| 665 * project-level dependencies. | |
| 666 */ | 784 */ |
| 667 abstract class SourceContainer { | 785 class SourceKind extends Enum<SourceKind> { |
| 668 /** | 786 /** |
| 669 * Determine if the specified source is part of the receiver's collection of s
ources. | 787 * A source containing HTML. The HTML might or might not contain Dart scripts. |
| 670 * | |
| 671 * @param source the source in question | |
| 672 * @return `true` if the receiver contains the source, else `false` | |
| 673 */ | 788 */ |
| 674 bool contains(Source source); | 789 static const SourceKind HTML = const SourceKind('HTML', 0); |
| 790 |
| 791 /** |
| 792 * A Dart compilation unit that is not a part of another library. Libraries mi
ght or might not |
| 793 * contain any directives, including a library directive. |
| 794 */ |
| 795 static const SourceKind LIBRARY = const SourceKind('LIBRARY', 1); |
| 796 |
| 797 /** |
| 798 * A Dart compilation unit that is part of another library. Parts contain a pa
rt-of directive. |
| 799 */ |
| 800 static const SourceKind PART = const SourceKind('PART', 2); |
| 801 |
| 802 /** |
| 803 * An unknown kind of source. Used both when it is not possible to identify th
e kind of a source |
| 804 * and also when the kind of a source is not known without performing a comput
ation and the client |
| 805 * does not want to spend the time to identify the kind. |
| 806 */ |
| 807 static const SourceKind UNKNOWN = const SourceKind('UNKNOWN', 3); |
| 808 |
| 809 static const List<SourceKind> values = const [HTML, LIBRARY, PART, UNKNOWN]; |
| 810 |
| 811 const SourceKind(String name, int ordinal) : super(name, ordinal); |
| 675 } | 812 } |
| 676 | 813 |
| 677 /** | 814 /** |
| 678 * Instances of the class `DartUriResolver` resolve `dart` URI's. | 815 * The enumeration `UriKind` defines the different kinds of URI's that are known
to the |
| 816 * analysis engine. These are used to keep track of the kind of URI associated w
ith a given source. |
| 679 */ | 817 */ |
| 680 class DartUriResolver extends UriResolver { | 818 class UriKind extends Enum<UriKind> { |
| 681 /** | 819 /** |
| 682 * Return `true` if the given URI is a `dart-ext:` URI. | 820 * A 'dart:' URI. |
| 683 * | |
| 684 * @param uriContent the textual representation of the URI being tested | |
| 685 * @return `true` if the given URI is a `dart-ext:` URI | |
| 686 */ | 821 */ |
| 687 static bool isDartExtUri(String uriContent) => uriContent != null && uriConten
t.startsWith(_DART_EXT_SCHEME); | 822 static const UriKind DART_URI = const UriKind('DART_URI', 0, 0x64); |
| 688 | 823 |
| 689 /** | 824 /** |
| 690 * The Dart SDK against which URI's are to be resolved. | 825 * A 'file:' URI. |
| 691 */ | 826 */ |
| 692 final DartSdk _sdk; | 827 static const UriKind FILE_URI = const UriKind('FILE_URI', 1, 0x66); |
| 693 | 828 |
| 694 /** | 829 /** |
| 695 * The name of the `dart` scheme. | 830 * A 'package:' URI referencing source package itself. |
| 696 */ | 831 */ |
| 697 static String _DART_SCHEME = "dart"; | 832 static const UriKind PACKAGE_SELF_URI = const UriKind('PACKAGE_SELF_URI', 2, 0
x73); |
| 698 | 833 |
| 699 /** | 834 /** |
| 700 * The prefix of a URI using the dart-ext scheme to reference a native code li
brary. | 835 * A 'package:' URI. |
| 701 */ | 836 */ |
| 702 static String _DART_EXT_SCHEME = "dart-ext:"; | 837 static const UriKind PACKAGE_URI = const UriKind('PACKAGE_URI', 3, 0x70); |
| 838 |
| 839 static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_SELF_UR
I, PACKAGE_URI]; |
| 703 | 840 |
| 704 /** | 841 /** |
| 705 * Return `true` if the given URI is a `dart:` URI. | 842 * Return the URI kind represented by the given encoding, or `null` if there i
s no kind with |
| 843 * the given encoding. |
| 706 * | 844 * |
| 707 * @param uri the URI being tested | 845 * @param encoding the single character encoding used to identify the URI kind
to be returned |
| 708 * @return `true` if the given URI is a `dart:` URI | 846 * @return the URI kind represented by the given encoding |
| 709 */ | 847 */ |
| 710 static bool isDartUri(Uri uri) => _DART_SCHEME == uri.scheme; | 848 static UriKind fromEncoding(int encoding) { |
| 711 | 849 while (true) { |
| 712 /** | 850 if (encoding == 0x64) { |
| 713 * Initialize a newly created resolver to resolve Dart URI's against the given
platform within the | 851 return DART_URI; |
| 714 * given Dart SDK. | 852 } else if (encoding == 0x66) { |
| 715 * | 853 return FILE_URI; |
| 716 * @param sdk the Dart SDK against which URI's are to be resolved | 854 } else if (encoding == 0x73) { |
| 717 */ | 855 return PACKAGE_SELF_URI; |
| 718 DartUriResolver(this._sdk); | 856 } else if (encoding == 0x70) { |
| 719 | 857 return PACKAGE_URI; |
| 720 @override | 858 } |
| 721 Source fromEncoding(UriKind kind, Uri uri) { | 859 break; |
| 722 if (kind == UriKind.DART_URI) { | |
| 723 return _sdk.fromEncoding(kind, uri); | |
| 724 } | 860 } |
| 725 return null; | 861 return null; |
| 726 } | 862 } |
| 727 | 863 |
| 728 /** | 864 /** |
| 729 * Return the [DartSdk] against which URIs are to be resolved. | 865 * The single character encoding used to identify this kind of URI. |
| 730 * | |
| 731 * @return the [DartSdk] against which URIs are to be resolved. | |
| 732 */ | 866 */ |
| 733 DartSdk get dartSdk => _sdk; | 867 final int encoding; |
| 734 | |
| 735 @override | |
| 736 Source resolveAbsolute(Uri uri) { | |
| 737 if (!isDartUri(uri)) { | |
| 738 return null; | |
| 739 } | |
| 740 return _sdk.mapDartUri(uri.toString()); | |
| 741 } | |
| 742 } | |
| 743 | |
| 744 /** | |
| 745 * Instances of the class `LineInfo` encapsulate information about line and colu
mn information | |
| 746 * within a source file. | |
| 747 */ | |
| 748 class LineInfo { | |
| 749 /** | |
| 750 * An array containing the offsets of the first character of each line in the
source code. | |
| 751 */ | |
| 752 final List<int> _lineStarts; | |
| 753 | 868 |
| 754 /** | 869 /** |
| 755 * Initialize a newly created set of line information to represent the data en
coded in the given | 870 * Initialize a newly created URI kind to have the given encoding. |
| 756 * array. | |
| 757 * | 871 * |
| 758 * @param lineStarts the offsets of the first character of each line in the so
urce code | 872 * @param encoding the single character encoding used to identify this kind of
URI. |
| 759 */ | 873 */ |
| 760 LineInfo(this._lineStarts) { | 874 const UriKind(String name, int ordinal, this.encoding) : super(name, ordinal); |
| 761 if (_lineStarts == null) { | |
| 762 throw new IllegalArgumentException("lineStarts must be non-null"); | |
| 763 } else if (_lineStarts.length < 1) { | |
| 764 throw new IllegalArgumentException("lineStarts must be non-empty"); | |
| 765 } | |
| 766 } | |
| 767 | |
| 768 /** | |
| 769 * Return the location information for the character at the given offset. | |
| 770 * | |
| 771 * @param offset the offset of the character for which location information is
to be returned | |
| 772 * @return the location information for the character at the given offset | |
| 773 */ | |
| 774 LineInfo_Location getLocation(int offset) { | |
| 775 int lineCount = _lineStarts.length; | |
| 776 for (int i = 1; i < lineCount; i++) { | |
| 777 if (offset < _lineStarts[i]) { | |
| 778 return new LineInfo_Location(i, offset - _lineStarts[i - 1] + 1); | |
| 779 } | |
| 780 } | |
| 781 return new LineInfo_Location(lineCount, offset - _lineStarts[lineCount - 1]
+ 1); | |
| 782 } | |
| 783 } | |
| 784 | |
| 785 /** | |
| 786 * Instances of the class `Location` represent the location of a character as a
line and | |
| 787 * column pair. | |
| 788 */ | |
| 789 class LineInfo_Location { | |
| 790 /** | |
| 791 * The one-based index of the line containing the character. | |
| 792 */ | |
| 793 final int lineNumber; | |
| 794 | |
| 795 /** | |
| 796 * The one-based index of the column containing the character. | |
| 797 */ | |
| 798 final int columnNumber; | |
| 799 | |
| 800 /** | |
| 801 * Initialize a newly created location to represent the location of the charac
ter at the given | |
| 802 * line and column position. | |
| 803 * | |
| 804 * @param lineNumber the one-based index of the line containing the character | |
| 805 * @param columnNumber the one-based index of the column containing the charac
ter | |
| 806 */ | |
| 807 LineInfo_Location(this.lineNumber, this.columnNumber); | |
| 808 } | |
| 809 | |
| 810 /** | |
| 811 * Instances of class `ContentCache` hold content used to override the default c
ontent of a | |
| 812 * [Source]. | |
| 813 */ | |
| 814 class ContentCache { | |
| 815 /** | |
| 816 * A table mapping sources to the contents of those sources. This is used to o
verride the default | |
| 817 * contents of a source. | |
| 818 */ | |
| 819 Map<Source, String> _contentMap = new Map<Source, String>(); | |
| 820 | |
| 821 /** | |
| 822 * A table mapping sources to the modification stamps of those sources. This i
s used when the | |
| 823 * default contents of a source has been overridden. | |
| 824 */ | |
| 825 Map<Source, int> _stampMap = new Map<Source, int>(); | |
| 826 | |
| 827 /** | |
| 828 * Return the contents of the given source, or `null` if this cache does not o
verride the | |
| 829 * contents of the source. | |
| 830 * | |
| 831 * <b>Note:</b> This method is not intended to be used except by | |
| 832 * [AnalysisContext#getContents]. | |
| 833 * | |
| 834 * @param source the source whose content is to be returned | |
| 835 * @return the contents of the given source | |
| 836 */ | |
| 837 String getContents(Source source) => _contentMap[source]; | |
| 838 | |
| 839 /** | |
| 840 * Return the modification stamp of the given source, or `null` if this cache
does not | |
| 841 * override the contents of the source. | |
| 842 * | |
| 843 * <b>Note:</b> This method is not intended to be used except by | |
| 844 * [AnalysisContext#getModificationStamp]. | |
| 845 * | |
| 846 * @param source the source whose modification stamp is to be returned | |
| 847 * @return the modification stamp of the given source | |
| 848 */ | |
| 849 int getModificationStamp(Source source) => _stampMap[source]; | |
| 850 | |
| 851 /** | |
| 852 * Set the contents of the given source to the given contents. This has the ef
fect of overriding | |
| 853 * the default contents of the source. If the contents are `null` the override
is removed so | |
| 854 * that the default contents will be returned. | |
| 855 * | |
| 856 * @param source the source whose contents are being overridden | |
| 857 * @param contents the new contents of the source | |
| 858 * @return the original cached contents or `null` if none | |
| 859 */ | |
| 860 String setContents(Source source, String contents) { | |
| 861 if (contents == null) { | |
| 862 _stampMap.remove(source); | |
| 863 return _contentMap.remove(source); | |
| 864 } else { | |
| 865 int newStamp = JavaSystem.currentTimeMillis(); | |
| 866 int oldStamp = javaMapPut(_stampMap, source, newStamp); | |
| 867 // Occasionally, if this method is called in rapid succession, the timesta
mps are equal. | |
| 868 // Guard against this by artificially incrementing the new timestamp | |
| 869 if (newStamp == oldStamp) { | |
| 870 _stampMap[source] = newStamp + 1; | |
| 871 } | |
| 872 return javaMapPut(_contentMap, source, contents); | |
| 873 } | |
| 874 } | |
| 875 } | 875 } |
| OLD | NEW |