Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: analyzer/lib/src/generated/source.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « analyzer/lib/src/generated/sdk_io.dart ('k') | analyzer/lib/src/generated/source_io.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "dart:math" as math;
12
13 import 'package:analyzer/file_system/file_system.dart';
14 import 'package:analyzer/file_system/physical_file_system.dart';
15 import 'package:analyzer/source/package_map_resolver.dart';
16 import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
17 import 'package:analyzer/task/model.dart';
18 import 'package:package_config/packages.dart';
19 import 'package:path/path.dart' as pathos;
20
21 import 'engine.dart';
22 import 'java_core.dart';
23 import 'java_engine.dart';
24 import 'java_io.dart' show JavaFile;
25 import 'sdk.dart' show DartSdk;
26 import 'source_io.dart' show FileBasedSource;
27
28 /**
29 * A function that is used to visit [ContentCache] entries.
30 */
31 typedef void ContentCacheVisitor(String fullPath, int stamp, String contents);
32
33 /**
34 * A cache used to override the default content of a [Source].
35 */
36 class ContentCache {
37 /**
38 * A table mapping the full path of sources to the contents of those sources.
39 * This is used to override the default contents of a source.
40 */
41 HashMap<String, String> _contentMap = new HashMap<String, String>();
42
43 /**
44 * A table mapping the full path of sources to the modification stamps of
45 * those sources. This is used when the default contents of a source has been
46 * overridden.
47 */
48 HashMap<String, int> _stampMap = new HashMap<String, int>();
49
50 /**
51 * Visit all entries of this cache.
52 */
53 void accept(ContentCacheVisitor visitor) {
54 _contentMap.forEach((String fullPath, String contents) {
55 int stamp = _stampMap[fullPath];
56 visitor(fullPath, stamp, contents);
57 });
58 }
59
60 /**
61 * Return the contents of the given [source], or `null` if this cache does not
62 * override the contents of the source.
63 *
64 * <b>Note:</b> This method is not intended to be used except by
65 * [AnalysisContext.getContents].
66 */
67 String getContents(Source source) => _contentMap[source.fullName];
68
69 /**
70 * Return the modification stamp of the given [source], or `null` if this
71 * cache does not override the contents of the source.
72 *
73 * <b>Note:</b> This method is not intended to be used except by
74 * [AnalysisContext.getModificationStamp].
75 */
76 int getModificationStamp(Source source) => _stampMap[source.fullName];
77
78 /**
79 * Set the contents of the given [source] to the given [contents]. This has
80 * the effect of overriding the default contents of the source. If the
81 * contents are `null` the override is removed so that the default contents
82 * will be returned.
83 */
84 String setContents(Source source, String contents) {
85 String fullName = source.fullName;
86 if (contents == null) {
87 _stampMap.remove(fullName);
88 return _contentMap.remove(fullName);
89 } else {
90 int newStamp = JavaSystem.currentTimeMillis();
91 int oldStamp = _stampMap[fullName];
92 _stampMap[fullName] = newStamp;
93 // Occasionally, if this method is called in rapid succession, the
94 // timestamps are equal. Guard against this by artificially incrementing
95 // the new timestamp.
96 if (newStamp == oldStamp) {
97 _stampMap[fullName] = newStamp + 1;
98 }
99 String oldContent = _contentMap[fullName];
100 _contentMap[fullName] = contents;
101 return oldContent;
102 }
103 }
104 }
105
106 class CustomUriResolver extends UriResolver {
107 final Map<String, String> _urlMappings;
108
109 CustomUriResolver(this._urlMappings);
110
111 @override
112 Source resolveAbsolute(Uri uri) {
113 String mapping = _urlMappings[uri.toString()];
114 if (mapping == null) return null;
115
116 Uri fileUri = new Uri.file(mapping);
117 if (!fileUri.isAbsolute) return null;
118
119 JavaFile javaFile = new JavaFile.fromUri(fileUri);
120 return new FileBasedSource(javaFile);
121 }
122 }
123
124 /**
125 * Instances of the class `DartUriResolver` resolve `dart` URI's.
126 */
127 class DartUriResolver extends UriResolver {
128 /**
129 * The name of the `dart` scheme.
130 */
131 static String DART_SCHEME = "dart";
132
133 /**
134 * The prefix of a URI using the dart-ext scheme to reference a native code li brary.
135 */
136 static String _DART_EXT_SCHEME = "dart-ext:";
137
138 /**
139 * The Dart SDK against which URI's are to be resolved.
140 */
141 final DartSdk _sdk;
142
143 /**
144 * Initialize a newly created resolver to resolve Dart URI's against the given platform within the
145 * given Dart SDK.
146 *
147 * @param sdk the Dart SDK against which URI's are to be resolved
148 */
149 DartUriResolver(this._sdk);
150
151 /**
152 * Return the [DartSdk] against which URIs are to be resolved.
153 *
154 * @return the [DartSdk] against which URIs are to be resolved.
155 */
156 DartSdk get dartSdk => _sdk;
157
158 @override
159 Source resolveAbsolute(Uri uri) {
160 if (!isDartUri(uri)) {
161 return null;
162 }
163 return _sdk.mapDartUri(uri.toString());
164 }
165
166 /**
167 * Return `true` if the given URI is a `dart-ext:` URI.
168 *
169 * @param uriContent the textual representation of the URI being tested
170 * @return `true` if the given URI is a `dart-ext:` URI
171 */
172 static bool isDartExtUri(String uriContent) =>
173 uriContent != null && uriContent.startsWith(_DART_EXT_SCHEME);
174
175 /**
176 * Return `true` if the given URI is a `dart:` URI.
177 *
178 * @param uri the URI being tested
179 * @return `true` if the given URI is a `dart:` URI
180 */
181 static bool isDartUri(Uri uri) => DART_SCHEME == uri.scheme;
182 }
183
184 /**
185 * Instances of the class `LineInfo` encapsulate information about line and colu mn information
186 * within a source file.
187 */
188 class LineInfo {
189 /**
190 * An array containing the offsets of the first character of each line in the source code.
191 */
192 final List<int> _lineStarts;
193
194 /**
195 * The zero-based [_lineStarts] index resulting from the last call to
196 * [getLocation].
197 */
198 int _previousLine = 0;
199
200 /**
201 * Initialize a newly created set of line information to represent the data en coded in the given
202 * array.
203 *
204 * @param lineStarts the offsets of the first character of each line in the so urce code
205 */
206 LineInfo(this._lineStarts) {
207 if (_lineStarts == null) {
208 throw new IllegalArgumentException("lineStarts must be non-null");
209 } else if (_lineStarts.length < 1) {
210 throw new IllegalArgumentException("lineStarts must be non-empty");
211 }
212 }
213
214 /**
215 * Return the location information for the character at the given offset.
216 *
217 * @param offset the offset of the character for which location information is to be returned
218 * @return the location information for the character at the given offset
219 */
220 LineInfo_Location getLocation(int offset) {
221 var min = 0;
222 var max = _lineStarts.length - 1;
223
224 // Subsequent calls to [getLocation] are often for offsets near each other.
225 // To take advantage of that, we cache the index of the line start we found
226 // when this was last called. If the current offset is on that line or
227 // later, we'll skip those early indices completely when searching.
228 if (offset >= _lineStarts[_previousLine]) {
229 min = _previousLine;
230
231 // Before kicking off a full binary search, do a quick check here to see
232 // if the new offset is on that exact line.
233 if (min == _lineStarts.length - 1 || offset < _lineStarts[min + 1]) {
234 return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
235 }
236 }
237
238 // Binary search to fine the line containing this offset.
239 while (min < max) {
240 var midpoint = (max - min + 1) ~/ 2 + min;
241
242 if (_lineStarts[midpoint] > offset) {
243 max = midpoint - 1;
244 } else {
245 min = midpoint;
246 }
247 }
248
249 _previousLine = min;
250
251 return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
252 }
253 }
254
255 /**
256 * Instances of the class `Location` represent the location of a character as a line and
257 * column pair.
258 */
259 class LineInfo_Location {
260 /**
261 * The one-based index of the line containing the character.
262 */
263 final int lineNumber;
264
265 /**
266 * The one-based index of the column containing the character.
267 */
268 final int columnNumber;
269
270 /**
271 * Initialize a newly created location to represent the location of the charac ter at the given
272 * line and column position.
273 *
274 * @param lineNumber the one-based index of the line containing the character
275 * @param columnNumber the one-based index of the column containing the charac ter
276 */
277 LineInfo_Location(this.lineNumber, this.columnNumber);
278 }
279
280 /**
281 * Instances of interface `LocalSourcePredicate` are used to determine if the gi ven
282 * [Source] is "local" in some sense, so can be updated.
283 */
284 abstract class LocalSourcePredicate {
285 /**
286 * Instance of [LocalSourcePredicate] that always returns `false`.
287 */
288 static final LocalSourcePredicate FALSE = new LocalSourcePredicate_FALSE();
289
290 /**
291 * Instance of [LocalSourcePredicate] that always returns `true`.
292 */
293 static final LocalSourcePredicate TRUE = new LocalSourcePredicate_TRUE();
294
295 /**
296 * Instance of [LocalSourcePredicate] that returns `true` for all [Source]s
297 * except of SDK.
298 */
299 static final LocalSourcePredicate NOT_SDK =
300 new LocalSourcePredicate_NOT_SDK();
301
302 /**
303 * Determines if the given [Source] is local.
304 *
305 * @param source the [Source] to analyze
306 * @return `true` if the given [Source] is local
307 */
308 bool isLocal(Source source);
309 }
310
311 class LocalSourcePredicate_FALSE implements LocalSourcePredicate {
312 @override
313 bool isLocal(Source source) => false;
314 }
315
316 class LocalSourcePredicate_NOT_SDK implements LocalSourcePredicate {
317 @override
318 bool isLocal(Source source) => source.uriKind != UriKind.DART_URI;
319 }
320
321 class LocalSourcePredicate_TRUE implements LocalSourcePredicate {
322 @override
323 bool isLocal(Source source) => true;
324 }
325
326 /**
327 * An implementation of an non-existing [Source].
328 */
329 class NonExistingSource extends Source {
330 @override
331 final String fullName;
332
333 @override
334 final Uri uri;
335
336 final UriKind uriKind;
337
338 NonExistingSource(this.fullName, this.uri, this.uriKind);
339
340 @override
341 TimestampedData<String> get contents {
342 throw new UnsupportedOperationException('$fullName does not exist.');
343 }
344
345 @override
346 String get encoding {
347 throw new UnsupportedOperationException('$fullName does not exist.');
348 }
349
350 @override
351 int get hashCode => fullName.hashCode;
352
353 @override
354 bool get isInSystemLibrary => false;
355
356 @override
357 int get modificationStamp => -1;
358
359 @override
360 String get shortName => pathos.basename(fullName);
361
362 @override
363 bool operator ==(Object other) {
364 if (other is NonExistingSource) {
365 return other.uriKind == uriKind && other.fullName == fullName;
366 }
367 return false;
368 }
369
370 @override
371 bool exists() => false;
372
373 @override
374 Uri resolveRelativeUri(Uri relativeUri) {
375 throw new UnsupportedOperationException('$fullName does not exist.');
376 }
377 }
378
379 /**
380 * The interface `Source` defines the behavior of objects representing source co de that can be
381 * analyzed by the analysis engine.
382 *
383 * Implementations of this interface need to be aware of some assumptions made b y the analysis
384 * engine concerning sources:
385 * * Sources are not required to be unique. That is, there can be multiple insta nces representing
386 * the same source.
387 * * Sources are long lived. That is, the engine is allowed to hold on to a sour ce for an extended
388 * period of time and that source must continue to report accurate and up-to-dat e information.
389 * Because of these assumptions, most implementations will not maintain any stat e but will delegate
390 * to an authoritative system of record in order to implement this API. For exam ple, a source that
391 * represents files on disk would typically query the file system to determine t he state of the
392 * file.
393 *
394 * If the instances that implement this API are the system of record, then they will typically be
395 * unique. In that case, sources that are created that represent non-existent fi les must also be
396 * retained so that if those files are created at a later date the long-lived so urces representing
397 * those files will know that they now exist.
398 */
399 abstract class Source implements AnalysisTarget {
400 /**
401 * An empty list of sources.
402 */
403 @deprecated // Use Source.EMPTY_LIST
404 static const List<Source> EMPTY_ARRAY = EMPTY_LIST;
405
406 /**
407 * An empty list of sources.
408 */
409 static const List<Source> EMPTY_LIST = const <Source>[];
410
411 /**
412 * Get the contents and timestamp of this source.
413 *
414 * Clients should consider using the the method [AnalysisContext.getContents]
415 * because contexts can have local overrides of the content of a source that t he source is not
416 * aware of.
417 *
418 * @return the contents and timestamp of the source
419 * @throws Exception if the contents of this source could not be accessed
420 */
421 TimestampedData<String> get contents;
422
423 /**
424 * Return an encoded representation of this source that can be used to create a source that is
425 * equal to this source.
426 *
427 * @return an encoded representation of this source
428 * See [SourceFactory.fromEncoding].
429 */
430 String get encoding;
431
432 /**
433 * Return the full (long) version of the name that can be displayed to the use r to denote this
434 * source. For example, for a source representing a file this would typically be the absolute path
435 * of the file.
436 *
437 * @return a name that can be displayed to the user to denote this source
438 */
439 String get fullName;
440
441 /**
442 * Return a hash code for this source.
443 *
444 * @return a hash code for this source
445 * See [Object.hashCode].
446 */
447 @override
448 int get hashCode;
449
450 /**
451 * Return `true` if this source is in one of the system libraries.
452 *
453 * @return `true` if this is in a system library
454 */
455 bool get isInSystemLibrary;
456
457 /**
458 * Return the modification stamp for this source, or a negative value if the
459 * source does not exist. A modification stamp is a non-negative integer with
460 * the property that if the contents of the source have not been modified
461 * since the last time the modification stamp was accessed then the same value
462 * will be returned, but if the contents of the source have been modified one
463 * or more times (even if the net change is zero) the stamps will be different .
464 *
465 * Clients should consider using the the method
466 * [AnalysisContext.getModificationStamp] because contexts can have local
467 * overrides of the content of a source that the source is not aware of.
468 */
469 int get modificationStamp;
470
471 /**
472 * Return a short version of the name that can be displayed to the user to den ote this source. For
473 * example, for a source representing a file this would typically be the name of the file.
474 *
475 * @return a name that can be displayed to the user to denote this source
476 */
477 String get shortName;
478
479 @override
480 Source get source => this;
481
482 /**
483 * Return the URI from which this source was originally derived.
484 *
485 * @return the URI from which this source was originally derived
486 */
487 Uri get uri;
488
489 /**
490 * Return the kind of URI from which this source was originally derived. If th is source was
491 * created from an absolute URI, then the returned kind will reflect the schem e of the absolute
492 * URI. If it was created from a relative URI, then the returned kind will be the same as the kind
493 * of the source against which the relative URI was resolved.
494 *
495 * @return the kind of URI from which this source was originally derived
496 */
497 UriKind get uriKind;
498
499 /**
500 * Return `true` if the given object is a source that represents the same sour ce code as
501 * this source.
502 *
503 * @param object the object to be compared with this object
504 * @return `true` if the given object is a source that represents the same sou rce code as
505 * this source
506 * See [Object.==].
507 */
508 @override
509 bool operator ==(Object object);
510
511 /**
512 * Return `true` if this source exists.
513 *
514 * Clients should consider using the the method [AnalysisContext.exists] becau se
515 * contexts can have local overrides of the content of a source that the sourc e is not aware of
516 * and a source with local content is considered to exist even if there is no file on disk.
517 *
518 * @return `true` if this source exists
519 */
520 bool exists();
521
522 /**
523 * Resolve the relative URI against the URI associated with this source object .
524 *
525 * Note: This method is not intended for public use, it is only visible out of necessity. It is
526 * only intended to be invoked by a [SourceFactory]. Source factories will
527 * only invoke this method if the URI is relative, so implementations of this method are not
528 * required to, and generally do not, verify the argument. The result of invok ing this method with
529 * an absolute URI is intentionally left unspecified.
530 *
531 * @param relativeUri the relative URI to be resolved against this source
532 * @return the URI to which given URI was resolved
533 * @throws AnalysisException if the relative URI could not be resolved
534 */
535 Uri resolveRelativeUri(Uri relativeUri);
536 }
537
538 /**
539 * The interface `ContentReceiver` defines the behavior of objects that can rece ive the
540 * content of a source.
541 */
542 abstract class Source_ContentReceiver {
543 /**
544 * Accept the contents of a source.
545 *
546 * @param contents the contents of the source
547 * @param modificationTime the time at which the contents were last set
548 */
549 void accept(String contents, int modificationTime);
550 }
551
552 /**
553 * The interface `SourceContainer` is used by clients to define a collection of sources
554 *
555 * Source containers are not used within analysis engine, but can be used by cli ents to group
556 * sources for the purposes of accessing composite dependency information. For e xample, the Eclipse
557 * client uses source containers to represent Eclipse projects, which allows it to easily compute
558 * project-level dependencies.
559 */
560 abstract class SourceContainer {
561 /**
562 * Determine if the specified source is part of the receiver's collection of s ources.
563 *
564 * @param source the source in question
565 * @return `true` if the receiver contains the source, else `false`
566 */
567 bool contains(Source source);
568 }
569
570 /**
571 * Instances of the class `SourceFactory` resolve possibly relative URI's agains t an existing
572 * [Source].
573 */
574 class SourceFactory {
575 /**
576 * The analysis context that this source factory is associated with.
577 */
578 AnalysisContext context;
579
580 /**
581 * URI processor used to find mappings for `package:` URIs found in a `.packag es` config
582 * file.
583 */
584 final Packages _packages;
585
586 /**
587 * Resource provider used in working with package maps.
588 */
589 final ResourceProvider _resourceProvider;
590
591 /**
592 * The resolvers used to resolve absolute URI's.
593 */
594 final List<UriResolver> _resolvers;
595
596 /**
597 * The predicate to determine is [Source] is local.
598 */
599 LocalSourcePredicate _localSourcePredicate = LocalSourcePredicate.NOT_SDK;
600
601 /**
602 * Initialize a newly created source factory with the given absolute URI [reso lvers] and
603 * optional [packages] resolution helper.
604 */
605 SourceFactory(this._resolvers,
606 [this._packages, ResourceProvider resourceProvider])
607 : _resourceProvider = resourceProvider != null
608 ? resourceProvider
609 : PhysicalResourceProvider.INSTANCE;
610
611 /**
612 * Return the [DartSdk] associated with this [SourceFactory], or `null` if the re
613 * is no such SDK.
614 *
615 * @return the [DartSdk] associated with this [SourceFactory], or `null` if
616 * there is no such SDK
617 */
618 DartSdk get dartSdk {
619 for (UriResolver resolver in _resolvers) {
620 if (resolver is DartUriResolver) {
621 DartUriResolver dartUriResolver = resolver;
622 return dartUriResolver.dartSdk;
623 }
624 }
625 return null;
626 }
627
628 /**
629 * Sets the [LocalSourcePredicate].
630 *
631 * @param localSourcePredicate the predicate to determine is [Source] is local
632 */
633 void set localSourcePredicate(LocalSourcePredicate localSourcePredicate) {
634 this._localSourcePredicate = localSourcePredicate;
635 }
636
637 /// A table mapping package names to paths of directories containing
638 /// the package (or [null] if there is no registered package URI resolver).
639 Map<String, List<Folder>> get packageMap {
640 // Start by looking in .packages.
641 if (_packages != null) {
642 Map<String, List<Folder>> packageMap = <String, List<Folder>>{};
643 _packages.asMap().forEach((String name, Uri uri) {
644 if (uri.scheme == 'file' || uri.scheme == '' /* unspecified */) {
645 packageMap[name] =
646 <Folder>[_resourceProvider.getFolder(uri.toFilePath())];
647 }
648 });
649 return packageMap;
650 }
651
652 // Default to the PackageMapUriResolver.
653 PackageMapUriResolver resolver = _resolvers.firstWhere(
654 (r) => r is PackageMapUriResolver, orElse: () => null);
655 return resolver != null ? resolver.packageMap : null;
656 }
657
658 /**
659 * Return a source object representing the given absolute URI, or `null` if th e URI is not a
660 * valid URI or if it is not an absolute URI.
661 *
662 * @param absoluteUri the absolute URI to be resolved
663 * @return a source object representing the absolute URI
664 */
665 Source forUri(String absoluteUri) {
666 try {
667 Uri uri = parseUriWithException(absoluteUri);
668 if (uri.isAbsolute) {
669 return _internalResolveUri(null, uri);
670 }
671 } catch (exception, stackTrace) {
672 AnalysisEngine.instance.logger.logError(
673 "Could not resolve URI: $absoluteUri",
674 new CaughtException(exception, stackTrace));
675 }
676 return null;
677 }
678
679 /**
680 * Return a source object representing the given absolute URI, or `null` if th e URI is not
681 * an absolute URI.
682 *
683 * @param absoluteUri the absolute URI to be resolved
684 * @return a source object representing the absolute URI
685 */
686 Source forUri2(Uri absoluteUri) {
687 if (absoluteUri.isAbsolute) {
688 try {
689 return _internalResolveUri(null, absoluteUri);
690 } on AnalysisException catch (exception, stackTrace) {
691 AnalysisEngine.instance.logger.logError(
692 "Could not resolve URI: $absoluteUri",
693 new CaughtException(exception, stackTrace));
694 }
695 }
696 return null;
697 }
698
699 /**
700 * Return a source object that is equal to the source object used to obtain th e given encoding.
701 *
702 * @param encoding the encoding of a source object
703 * @return a source object that is described by the given encoding
704 * @throws IllegalArgumentException if the argument is not a valid encoding
705 * See [Source.encoding].
706 */
707 Source fromEncoding(String encoding) {
708 Source source = forUri(encoding);
709 if (source == null) {
710 throw new IllegalArgumentException(
711 "Invalid source encoding: '$encoding'");
712 }
713 return source;
714 }
715
716 /**
717 * Determines if the given [Source] is local.
718 *
719 * @param source the [Source] to analyze
720 * @return `true` if the given [Source] is local
721 */
722 bool isLocalSource(Source source) => _localSourcePredicate.isLocal(source);
723
724 /**
725 * Return a source object representing the URI that results from resolving the given (possibly
726 * relative) contained URI against the URI associated with an existing source object, whether or
727 * not the resulting source exists, or `null` if either the contained URI is i nvalid or if
728 * it cannot be resolved against the source object's URI.
729 *
730 * @param containingSource the source containing the given URI
731 * @param containedUri the (possibly relative) URI to be resolved against the containing source
732 * @return the source representing the contained URI
733 */
734 Source resolveUri(Source containingSource, String containedUri) {
735 if (containedUri == null || containedUri.isEmpty) {
736 return null;
737 }
738 try {
739 // Force the creation of an escaped URI to deal with spaces, etc.
740 return _internalResolveUri(
741 containingSource, parseUriWithException(containedUri));
742 } catch (exception, stackTrace) {
743 String containingFullName =
744 containingSource != null ? containingSource.fullName : '<null>';
745 AnalysisEngine.instance.logger.logError(
746 "Could not resolve URI ($containedUri) relative to source ($containing FullName)",
747 new CaughtException(exception, stackTrace));
748 return null;
749 }
750 }
751
752 /**
753 * Return an absolute URI that represents the given source, or `null` if a val id URI cannot
754 * be computed.
755 *
756 * @param source the source to get URI for
757 * @return the absolute URI representing the given source
758 */
759 Uri restoreUri(Source source) {
760 // First see if a resolver can restore the URI.
761 for (UriResolver resolver in _resolvers) {
762 Uri uri = resolver.restoreAbsolute(source);
763 if (uri != null) {
764 // Now see if there's a package mapping.
765 Uri packageMappedUri = _getPackageMapping(uri);
766 if (packageMappedUri != null) {
767 return packageMappedUri;
768 }
769 // Fall back to the resolver's computed URI.
770 return uri;
771 }
772 }
773
774 return null;
775 }
776
777 Uri _getPackageMapping(Uri sourceUri) {
778 if (_packages == null) {
779 return null;
780 }
781 if (sourceUri.scheme != 'file') {
782 //TODO(pquitslund): verify this works for non-file URIs.
783 return null;
784 }
785
786 Uri packageUri;
787 _packages.asMap().forEach((String name, Uri uri) {
788 if (packageUri == null) {
789 if (utils.startsWith(sourceUri, uri)) {
790 packageUri = Uri.parse(
791 'package:$name/${sourceUri.path.substring(uri.path.length)}');
792 }
793 }
794 });
795 return packageUri;
796 }
797
798 /**
799 * Return a source object representing the URI that results from resolving the given (possibly
800 * relative) contained URI against the URI associated with an existing source object, or
801 * `null` if the URI could not be resolved.
802 *
803 * @param containingSource the source containing the given URI
804 * @param containedUri the (possibly relative) URI to be resolved against the containing source
805 * @return the source representing the contained URI
806 * @throws AnalysisException if either the contained URI is invalid or if it c annot be resolved
807 * against the source object's URI
808 */
809 Source _internalResolveUri(Source containingSource, Uri containedUri) {
810 if (!containedUri.isAbsolute) {
811 if (containingSource == null) {
812 throw new AnalysisException(
813 "Cannot resolve a relative URI without a containing source: $contain edUri");
814 }
815 containedUri = containingSource.resolveRelativeUri(containedUri);
816 }
817 // Now check .packages.
818 if (_packages != null && containedUri.scheme == 'package') {
819 Uri packageUri =
820 _packages.resolve(containedUri, notFound: (Uri packageUri) => null);
821 // Ensure scheme is set.
822 if (packageUri != null && packageUri.scheme == '') {
823 packageUri = packageUri.replace(scheme: 'file');
824 }
825 containedUri = packageUri;
826 }
827 for (UriResolver resolver in _resolvers) {
828 Source result = resolver.resolveAbsolute(containedUri);
829 if (result != null) {
830 return result;
831 }
832 }
833 return null;
834 }
835 }
836
837 /**
838 * The enumeration `SourceKind` defines the different kinds of sources that are known to the
839 * analysis engine.
840 */
841 class SourceKind extends Enum<SourceKind> {
842 /**
843 * A source containing HTML. The HTML might or might not contain Dart scripts.
844 */
845 static const SourceKind HTML = const SourceKind('HTML', 0);
846
847 /**
848 * A Dart compilation unit that is not a part of another library. Libraries mi ght or might not
849 * contain any directives, including a library directive.
850 */
851 static const SourceKind LIBRARY = const SourceKind('LIBRARY', 1);
852
853 /**
854 * A Dart compilation unit that is part of another library. Parts contain a pa rt-of directive.
855 */
856 static const SourceKind PART = const SourceKind('PART', 2);
857
858 /**
859 * An unknown kind of source. Used both when it is not possible to identify th e kind of a source
860 * and also when the kind of a source is not known without performing a comput ation and the client
861 * does not want to spend the time to identify the kind.
862 */
863 static const SourceKind UNKNOWN = const SourceKind('UNKNOWN', 3);
864
865 static const List<SourceKind> values = const [HTML, LIBRARY, PART, UNKNOWN];
866
867 const SourceKind(String name, int ordinal) : super(name, ordinal);
868 }
869
870 /**
871 * A source range defines an [Element]'s source coordinates relative to its [Sou rce].
872 */
873 class SourceRange {
874 /**
875 * An empty [SourceRange] with offset `0` and length `0`.
876 */
877 static SourceRange EMPTY = new SourceRange(0, 0);
878
879 /**
880 * The 0-based index of the first character of the source code for this elemen t, relative to the
881 * source buffer in which this element is contained.
882 */
883 final int offset;
884
885 /**
886 * The number of characters of the source code for this element, relative to t he source buffer in
887 * which this element is contained.
888 */
889 final int length;
890
891 /**
892 * Initialize a newly created source range using the given offset and the give n length.
893 *
894 * @param offset the given offset
895 * @param length the given length
896 */
897 SourceRange(this.offset, this.length);
898
899 /**
900 * @return the 0-based index of the after-last character of the source code fo r this element,
901 * relative to the source buffer in which this element is contained.
902 */
903 int get end => offset + length;
904
905 @override
906 int get hashCode => 31 * offset + length;
907
908 @override
909 bool operator ==(Object obj) {
910 if (obj is! SourceRange) {
911 return false;
912 }
913 SourceRange sourceRange = obj as SourceRange;
914 return sourceRange.offset == offset && sourceRange.length == length;
915 }
916
917 /**
918 * @return `true` if <code>x</code> is in [offset, offset + length) interval.
919 */
920 bool contains(int x) => offset <= x && x < offset + length;
921
922 /**
923 * @return `true` if <code>x</code> is in (offset, offset + length) interval.
924 */
925 bool containsExclusive(int x) => offset < x && x < offset + length;
926
927 /**
928 * @return `true` if <code>otherRange</code> covers this [SourceRange].
929 */
930 bool coveredBy(SourceRange otherRange) => otherRange.covers(this);
931
932 /**
933 * @return `true` if this [SourceRange] covers <code>otherRange</code>.
934 */
935 bool covers(SourceRange otherRange) =>
936 offset <= otherRange.offset && otherRange.end <= end;
937
938 /**
939 * @return `true` if this [SourceRange] ends in <code>otherRange</code>.
940 */
941 bool endsIn(SourceRange otherRange) {
942 int thisEnd = end;
943 return otherRange.contains(thisEnd);
944 }
945
946 /**
947 * @return the expanded instance of [SourceRange], which has the same center.
948 */
949 SourceRange getExpanded(int delta) =>
950 new SourceRange(offset - delta, delta + length + delta);
951
952 /**
953 * @return the instance of [SourceRange] with end moved on "delta".
954 */
955 SourceRange getMoveEnd(int delta) => new SourceRange(offset, length + delta);
956
957 /**
958 * @return the expanded translated of [SourceRange], with moved start and the same length.
959 */
960 SourceRange getTranslated(int delta) =>
961 new SourceRange(offset + delta, length);
962
963 /**
964 * @return the minimal [SourceRange] that cover this and the given [SourceRang e]s.
965 */
966 SourceRange getUnion(SourceRange other) {
967 int newOffset = math.min(offset, other.offset);
968 int newEnd = math.max(offset + length, other.offset + other.length);
969 return new SourceRange(newOffset, newEnd - newOffset);
970 }
971
972 /**
973 * @return `true` if this [SourceRange] intersects with given.
974 */
975 bool intersects(SourceRange other) {
976 if (other == null) {
977 return false;
978 }
979 if (end <= other.offset) {
980 return false;
981 }
982 if (offset >= other.end) {
983 return false;
984 }
985 return true;
986 }
987
988 /**
989 * Return `true` if this [SourceRange] starts in the [otherRange].
990 */
991 bool startsIn(SourceRange otherRange) => otherRange.contains(offset);
992
993 @override
994 String toString() => '[offset=$offset, length=$length]';
995 }
996
997 /**
998 * The enumeration `UriKind` defines the different kinds of URI's that are known to the
999 * analysis engine. These are used to keep track of the kind of URI associated w ith a given source.
1000 */
1001 class UriKind extends Enum<UriKind> {
1002 /**
1003 * A 'dart:' URI.
1004 */
1005 static const UriKind DART_URI = const UriKind('DART_URI', 0, 0x64);
1006
1007 /**
1008 * A 'file:' URI.
1009 */
1010 static const UriKind FILE_URI = const UriKind('FILE_URI', 1, 0x66);
1011
1012 /**
1013 * A 'package:' URI.
1014 */
1015 static const UriKind PACKAGE_URI = const UriKind('PACKAGE_URI', 2, 0x70);
1016
1017 static const List<UriKind> values = const [DART_URI, FILE_URI, PACKAGE_URI];
1018
1019 /**
1020 * The single character encoding used to identify this kind of URI.
1021 */
1022 final int encoding;
1023
1024 /**
1025 * Initialize a newly created URI kind to have the given encoding.
1026 *
1027 * @param encoding the single character encoding used to identify this kind of URI.
1028 */
1029 const UriKind(String name, int ordinal, this.encoding) : super(name, ordinal);
1030
1031 /**
1032 * Return the URI kind represented by the given encoding, or `null` if there i s no kind with
1033 * the given encoding.
1034 *
1035 * @param encoding the single character encoding used to identify the URI kind to be returned
1036 * @return the URI kind represented by the given encoding
1037 */
1038 static UriKind fromEncoding(int encoding) {
1039 while (true) {
1040 if (encoding == 0x64) {
1041 return DART_URI;
1042 } else if (encoding == 0x66) {
1043 return FILE_URI;
1044 } else if (encoding == 0x70) {
1045 return PACKAGE_URI;
1046 }
1047 break;
1048 }
1049 return null;
1050 }
1051 }
1052
1053 /**
1054 * The abstract class `UriResolver` defines the behavior of objects that are use d to resolve
1055 * URI's for a source factory. Subclasses of this class are expected to resolve a single scheme of
1056 * absolute URI.
1057 */
1058 abstract class UriResolver {
1059 /**
1060 * Resolve the given absolute URI. Return a [Source] representing the file to which
1061 * it was resolved, whether or not the resulting source exists, or `null` if i t could not be
1062 * resolved because the URI is invalid.
1063 *
1064 * @param uri the URI to be resolved
1065 * @return a [Source] representing the file to which given URI was resolved
1066 */
1067 Source resolveAbsolute(Uri uri);
1068
1069 /**
1070 * Return an absolute URI that represents the given source, or `null` if a val id URI cannot
1071 * be computed.
1072 *
1073 * @param source the source to get URI for
1074 * @return the absolute URI representing the given source
1075 */
1076 Uri restoreAbsolute(Source source) => null;
1077 }
OLDNEW
« no previous file with comments | « analyzer/lib/src/generated/sdk_io.dart ('k') | analyzer/lib/src/generated/source_io.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698