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