| Index: pkg/analyzer-experimental/lib/src/generated/engine.dart
|
| diff --git a/pkg/analyzer-experimental/lib/src/generated/engine.dart b/pkg/analyzer-experimental/lib/src/generated/engine.dart
|
| index b1f1265dbb0984d2e0524063b44b29e5ed4ab2d0..51caa35a630e16c18a75ab5d4f6f0a3cd19d24ef 100644
|
| --- a/pkg/analyzer-experimental/lib/src/generated/engine.dart
|
| +++ b/pkg/analyzer-experimental/lib/src/generated/engine.dart
|
| @@ -4,14 +4,16 @@
|
| library engine;
|
|
|
| import 'java_core.dart';
|
| +import 'java_engine.dart';
|
| import 'dart:collection' show HasNextIterator;
|
| import 'error.dart';
|
| import 'source.dart';
|
| import 'scanner.dart' show Token, CharBufferScanner, StringScanner;
|
| -import 'ast.dart' show CompilationUnit;
|
| +import 'ast.dart' show CompilationUnit, Directive, PartOfDirective;
|
| import 'parser.dart' show Parser;
|
| import 'element.dart';
|
| import 'resolver.dart' show Namespace, NamespaceBuilder, LibraryResolver;
|
| +import 'html_scanner.dart' show HtmlScanner, HtmlScanResult, HtmlParser, HtmlParseResult;
|
|
|
| /**
|
| * The unique instance of the class {@code AnalysisEngine} serves as the entry point for the
|
| @@ -19,6 +21,18 @@ import 'resolver.dart' show Namespace, NamespaceBuilder, LibraryResolver;
|
| */
|
| class AnalysisEngine {
|
| /**
|
| + * The suffix used for Dart source files.
|
| + */
|
| + static String SUFFIX_DART = "dart";
|
| + /**
|
| + * The short suffix used for HTML files.
|
| + */
|
| + static String SUFFIX_HTM = "htm";
|
| + /**
|
| + * The long suffix used for HTML files.
|
| + */
|
| + static String SUFFIX_HTML = "html";
|
| + /**
|
| * The unique instance of this class.
|
| */
|
| static AnalysisEngine _UniqueInstance = new AnalysisEngine();
|
| @@ -28,6 +42,29 @@ class AnalysisEngine {
|
| */
|
| static AnalysisEngine get instance => _UniqueInstance;
|
| /**
|
| + * Return {@code true} if the given file name is assumed to contain Dart source code.
|
| + * @param fileName the name of the file being tested
|
| + * @return {@code true} if the given file name is assumed to contain Dart source code
|
| + */
|
| + static bool isDartFileName(String fileName) {
|
| + if (fileName == null) {
|
| + return false;
|
| + }
|
| + return javaStringEqualsIgnoreCase(FileNameUtilities.getExtension(fileName), SUFFIX_DART);
|
| + }
|
| + /**
|
| + * Return {@code true} if the given file name is assumed to contain HTML.
|
| + * @param fileName the name of the file being tested
|
| + * @return {@code true} if the given file name is assumed to contain HTML
|
| + */
|
| + static bool isHtmlFileName(String fileName) {
|
| + if (fileName == null) {
|
| + return false;
|
| + }
|
| + String extension = FileNameUtilities.getExtension(fileName);
|
| + return javaStringEqualsIgnoreCase(extension, SUFFIX_HTML) || javaStringEqualsIgnoreCase(extension, SUFFIX_HTM);
|
| + }
|
| + /**
|
| * The logger that should receive information about errors within the analysis engine.
|
| */
|
| Logger _logger = Logger.NULL;
|
| @@ -59,16 +96,24 @@ class AnalysisEngine {
|
| /**
|
| * The interface {@code AnalysisContext} defines the behavior of objects that represent a context in
|
| * which analysis can be performed. The context includes such information as the version of the SDK
|
| - * being analyzed against as well as the package-root used to resolve 'package:' URI's. This
|
| - * information is included indirectly through the {@link SourceFactory source factory}.
|
| + * being analyzed against as well as the package-root used to resolve 'package:' URI's. (The latter
|
| + * is included indirectly through the {@link SourceFactory source factory}.)
|
| * <p>
|
| * Analysis engine allows for having more than one context. This can be used, for example, to
|
| * perform one analysis based on the state of files on disk and a separate analysis based on the
|
| * state of those files in open editors. It can also be used to perform an analysis based on a
|
| - * proposed future state, such as after a refactoring.
|
| + * proposed future state, such as the state after a refactoring.
|
| */
|
| abstract class AnalysisContext {
|
| /**
|
| + * Respond to the given set of changes by removing any cached information that might now be
|
| + * out-of-date. The result indicates what operations need to be performed as a result of this
|
| + * change without actually performing those operations.
|
| + * @param changeSet a description of the changes that have occurred
|
| + * @return a result (not {@code null}) indicating operations to be performed
|
| + */
|
| + ChangeResult changed(ChangeSet changeSet);
|
| + /**
|
| * Clear any cached information that is dependent on resolution. This method should be invoked if
|
| * the assumptions used by resolution have changed but the contents of the file have not changed.
|
| * Use {@link #sourceChanged(Source)} and {@link #sourcesDeleted(SourceContainer)} to indicate
|
| @@ -90,11 +135,6 @@ abstract class AnalysisContext {
|
| */
|
| AnalysisContext extractAnalysisContext(SourceContainer container);
|
| /**
|
| - * Answer the collection of sources that have been added to the receiver via{@link #sourceAvailable(Source)} and not removed from the receiver via{@link #sourceDeleted(Source)} or {@link #sourcesDeleted(SourceContainer)}.
|
| - * @return a collection of sources (not {@code null}, contains no {@code null}s)
|
| - */
|
| - Collection<Source> get availableSources;
|
| - /**
|
| * Return the element referenced by the given location.
|
| * @param location the reference describing the element to be returned
|
| * @return the element referenced by the given location
|
| @@ -123,6 +163,18 @@ abstract class AnalysisContext {
|
| */
|
| SourceKind getKnownKindOf(Source source);
|
| /**
|
| + * Return the sources for the defining compilation units of any libraries of which the given
|
| + * source is a part. The array will normally contain a single library because most Dart sources
|
| + * are only included in a single library, but it is possible to have a part that is contained in
|
| + * multiple identically named libraries. If the source represents the defining compilation unit of
|
| + * a library, then the returned array will contain the given source as its only element. If the
|
| + * source does not represent a Dart source or is not known to this context, the returned array
|
| + * will be empty.
|
| + * @param source the source contained in the returned libraries
|
| + * @return the sources for the libraries containing the given source
|
| + */
|
| + List<Source> getLibrariesContaining(Source source);
|
| + /**
|
| * Return the element model corresponding to the library defined by the given source. If the
|
| * element model does not yet exist it will be created. The process of creating an element model
|
| * for a library can long-running, depending on the size of the library and the number of
|
| @@ -182,6 +234,15 @@ abstract class AnalysisContext {
|
| */
|
| CompilationUnit parse(Source source);
|
| /**
|
| + * Parse a single HTML source to produce an AST structure. The resulting HTML AST structure may or
|
| + * may not be resolved, and may have a slightly different structure depending upon whether it is
|
| + * resolved.
|
| + * @param source the HTML source to be parsed
|
| + * @return the parse result (not {@code null})
|
| + * @throws AnalysisException if the analysis could not be performed
|
| + */
|
| + HtmlParseResult parseHtml(Source source);
|
| + /**
|
| * Parse and resolve a single source within the given context to produce a fully resolved AST.
|
| * @param source the source to be parsed and resolved
|
| * @param library the library defining the context in which the source file is to be resolved
|
| @@ -198,6 +259,13 @@ abstract class AnalysisContext {
|
| */
|
| Token scan(Source source, AnalysisErrorListener errorListener);
|
| /**
|
| + * Scan a single source to produce an HTML token stream.
|
| + * @param source the source to be scanned
|
| + * @return the scan result (not {@code null})
|
| + * @throws AnalysisException if the analysis could not be performed
|
| + */
|
| + HtmlScanResult scanHtml(Source source);
|
| + /**
|
| * Set the source factory used to create the sources that can be analyzed in this context to the
|
| * given source factory.
|
| * @param sourceFactory the source factory used to create the sources that can be analyzed in this
|
| @@ -205,30 +273,6 @@ abstract class AnalysisContext {
|
| */
|
| void set sourceFactory(SourceFactory sourceFactory4);
|
| /**
|
| - * Cache the fact that content for the given source is now available, is of interest to the
|
| - * client, and should be analyzed. Do not modify or discard any information about this source that
|
| - * is already cached.
|
| - * @param source the source that is now available
|
| - */
|
| - void sourceAvailable(Source source);
|
| - /**
|
| - * Respond to the fact that the content of the given source has changed by removing any cached
|
| - * information that might now be out-of-date.
|
| - * @param source the source whose content has changed
|
| - */
|
| - void sourceChanged(Source source);
|
| - /**
|
| - * Respond to the fact that the given source has been deleted and should no longer be analyzed by
|
| - * removing any cached information that might now be out-of-date.
|
| - * @param source the source that was deleted
|
| - */
|
| - void sourceDeleted(Source source);
|
| - /**
|
| - * Discard cached information for all files in the specified source container.
|
| - * @param container the source container that was deleted (not {@code null})
|
| - */
|
| - void sourcesDeleted(SourceContainer container);
|
| - /**
|
| * Given a collection of sources with content that has changed, return an {@link Iterable}identifying the sources that need to be resolved.
|
| * @param changedSources an array of sources (not {@code null}, contains no {@code null}s)
|
| * @return An iterable returning the sources to be resolved
|
| @@ -244,18 +288,18 @@ class AnalysisException extends JavaException {
|
| * Initialize a newly created exception.
|
| */
|
| AnalysisException() : super() {
|
| - _jtd_constructor_117_impl();
|
| + _jtd_constructor_119_impl();
|
| }
|
| - _jtd_constructor_117_impl() {
|
| + _jtd_constructor_119_impl() {
|
| }
|
| /**
|
| * Initialize a newly created exception to have the given message.
|
| * @param message the message associated with the exception
|
| */
|
| AnalysisException.con1(String message) : super(message) {
|
| - _jtd_constructor_118_impl(message);
|
| + _jtd_constructor_120_impl(message);
|
| }
|
| - _jtd_constructor_118_impl(String message) {
|
| + _jtd_constructor_120_impl(String message) {
|
| }
|
| /**
|
| * Initialize a newly created exception to have the given message and cause.
|
| @@ -263,18 +307,136 @@ class AnalysisException extends JavaException {
|
| * @param cause the underlying exception that caused this exception
|
| */
|
| AnalysisException.con2(String message, Exception cause) : super(message, cause) {
|
| - _jtd_constructor_119_impl(message, cause);
|
| + _jtd_constructor_121_impl(message, cause);
|
| }
|
| - _jtd_constructor_119_impl(String message, Exception cause) {
|
| + _jtd_constructor_121_impl(String message, Exception cause) {
|
| }
|
| /**
|
| * Initialize a newly created exception to have the given cause.
|
| * @param cause the underlying exception that caused this exception
|
| */
|
| AnalysisException.con3(Exception cause) : super.withCause(cause) {
|
| - _jtd_constructor_120_impl(cause);
|
| + _jtd_constructor_122_impl(cause);
|
| }
|
| - _jtd_constructor_120_impl(Exception cause) {
|
| + _jtd_constructor_122_impl(Exception cause) {
|
| + }
|
| +}
|
| +/**
|
| + * Instances of {@code ChangeResult} are returned by {@link AnalysisContext#changed(ChangeSet)} to
|
| + * indicate what operations need to be performed as a result of the change.
|
| + */
|
| +class ChangeResult {
|
| +}
|
| +/**
|
| + * Instances of the class {@code ChangeSet} indicate what sources have been added, changed, or
|
| + * removed.
|
| + */
|
| +class ChangeSet {
|
| + /**
|
| + * A table mapping the sources that have been added to their contents.
|
| + */
|
| + Map<Source, String> _added3 = new Map<Source, String>();
|
| + /**
|
| + * A table mapping the sources that have been changed to their contents.
|
| + */
|
| + Map<Source, String> _changed3 = new Map<Source, String>();
|
| + /**
|
| + * A list containing the sources that have been removed..
|
| + */
|
| + List<Source> _removed2 = new List<Source>();
|
| + /**
|
| + * A list containing the source containers specifying additional sources that have been removed.
|
| + */
|
| + List<SourceContainer> _removedContainers = new List<SourceContainer>();
|
| + /**
|
| + * Initialize a newly created change set to be empty.
|
| + */
|
| + ChangeSet() : super() {
|
| + }
|
| + /**
|
| + * Record that the specified source has been added and that it's content is the default contents
|
| + * of the source.
|
| + * @param source the source that was added
|
| + */
|
| + void added(Source source) {
|
| + added2(source, null);
|
| + }
|
| + /**
|
| + * Record that the specified source has been added and that it has the given content. If the
|
| + * content is non-{@code null}, this has the effect of overriding the default contents of the
|
| + * source. If the contents are {@code null}, any previous the override is removed so that the
|
| + * default contents will be used.
|
| + * @param source the source that was added
|
| + * @param content the content of the new source
|
| + */
|
| + void added2(Source source, String content) {
|
| + if (source != null) {
|
| + _added3[source] = content;
|
| + }
|
| + }
|
| + /**
|
| + * Record that the specified source has been changed and that it's content is the default contents
|
| + * of the source.
|
| + * @param source the source that was changed
|
| + */
|
| + void changed(Source source) {
|
| + changed2(source, null);
|
| + }
|
| + /**
|
| + * Record that the specified source has been changed and that it now has the given content. If the
|
| + * content is non-{@code null}, this has the effect of overriding the default contents of the
|
| + * source. If the contents are {@code null}, any previous the override is removed so that the
|
| + * default contents will be used.
|
| + * @param source the source that was changed
|
| + * @param content the new content of the source
|
| + */
|
| + void changed2(Source source, String content) {
|
| + if (source != null) {
|
| + _changed3[source] = content;
|
| + }
|
| + }
|
| + /**
|
| + * Return a table mapping the sources that have been added to their contents.
|
| + * @return a table mapping the sources that have been added to their contents
|
| + */
|
| + Map<Source, String> get addedWithContent => _added3;
|
| + /**
|
| + * Return a table mapping the sources that have been changed to their contents.
|
| + * @return a table mapping the sources that have been changed to their contents
|
| + */
|
| + Map<Source, String> get changedWithContent => _changed3;
|
| + /**
|
| + * Return a list containing the sources that were removed.
|
| + * @return a list containing the sources that were removed
|
| + */
|
| + List<Source> get removed => _removed2;
|
| + /**
|
| + * Return a list containing the source containers that were removed.
|
| + * @return a list containing the source containers that were removed
|
| + */
|
| + List<SourceContainer> get removedContainers => _removedContainers;
|
| + /**
|
| + * Return {@code true} if this change set does not contain any changes.
|
| + * @return {@code true} if this change set does not contain any changes
|
| + */
|
| + bool isEmpty() => _added3.isEmpty && _changed3.isEmpty && _removed2.isEmpty && _removedContainers.isEmpty;
|
| + /**
|
| + * Record that the specified source has been removed.
|
| + * @param source the source that was removed
|
| + */
|
| + void removed3(Source source) {
|
| + if (source != null) {
|
| + _removed2.add(source);
|
| + }
|
| + }
|
| + /**
|
| + * Record that the specified source container has been removed.
|
| + * @param container the source container that was removed
|
| + */
|
| + void removedContainer(SourceContainer container) {
|
| + if (container != null) {
|
| + _removedContainers.add(container);
|
| + }
|
| }
|
| }
|
| /**
|
| @@ -287,11 +449,20 @@ class AnalysisContextImpl implements AnalysisContext {
|
| */
|
| SourceFactory _sourceFactory;
|
| /**
|
| + * A table mapping sources known to the context to the information known about the source.
|
| + */
|
| + Map<Source, SourceInfo> _sourceMap = new Map<Source, SourceInfo>();
|
| + /**
|
| * A cache mapping sources to the compilation units that were produced for the contents of the
|
| * source.
|
| */
|
| Map<Source, CompilationUnit> _parseCache = new Map<Source, CompilationUnit>();
|
| /**
|
| + * A cache mapping sources to the html parse results that were produced for the contents of the
|
| + * source.
|
| + */
|
| + Map<Source, HtmlParseResult> _htmlParseCache = new Map<Source, HtmlParseResult>();
|
| + /**
|
| * A cache mapping sources (of the defining compilation units of libraries) to the library
|
| * elements for those libraries.
|
| */
|
| @@ -302,11 +473,6 @@ class AnalysisContextImpl implements AnalysisContext {
|
| */
|
| Map<Source, Namespace> _publicNamespaceCache = new Map<Source, Namespace>();
|
| /**
|
| - * A cache of the available sources of interest to the client. Sources are added to this
|
| - * collection via {@link #sourceAvailable(Source)} and removed from this collection via{@link #sourceDeleted(Source)} and {@link #directoryDeleted(File)}
|
| - */
|
| - Set<Source> _availableSources = new Set<Source>();
|
| - /**
|
| * The object used to synchronize access to all of the caches.
|
| */
|
| Object _cacheLock = new Object();
|
| @@ -323,40 +489,63 @@ class AnalysisContextImpl implements AnalysisContext {
|
| */
|
| AnalysisContextImpl() : super() {
|
| }
|
| + ChangeResult changed(ChangeSet changeSet) {
|
| + if (changeSet.isEmpty()) {
|
| + return new ChangeResult();
|
| + }
|
| + {
|
| + for (MapEntry<Source, String> entry in getMapEntrySet(changeSet.addedWithContent)) {
|
| + _sourceFactory.setContents(entry.getKey(), entry.getValue());
|
| + }
|
| + for (MapEntry<Source, String> entry in getMapEntrySet(changeSet.changedWithContent)) {
|
| + _sourceFactory.setContents(entry.getKey(), entry.getValue());
|
| + }
|
| + for (Source source in changeSet.addedWithContent.keys.toSet()) {
|
| + sourceAvailable(source);
|
| + }
|
| + for (Source source in changeSet.changedWithContent.keys.toSet()) {
|
| + sourceChanged(source);
|
| + }
|
| + for (Source source in changeSet.removed) {
|
| + sourceDeleted(source);
|
| + }
|
| + for (SourceContainer container in changeSet.removedContainers) {
|
| + sourcesDeleted(container);
|
| + }
|
| + }
|
| + return new ChangeResult();
|
| + }
|
| void clearResolution() {
|
| {
|
| _parseCache.clear();
|
| + _htmlParseCache.clear();
|
| _libraryElementCache.clear();
|
| _publicNamespaceCache.clear();
|
| }
|
| }
|
| void discard() {
|
| {
|
| + _sourceMap.clear();
|
| _parseCache.clear();
|
| + _htmlParseCache.clear();
|
| _libraryElementCache.clear();
|
| _publicNamespaceCache.clear();
|
| - _availableSources.clear();
|
| }
|
| }
|
| AnalysisContext extractAnalysisContext(SourceContainer container) {
|
| - AnalysisContext newContext = AnalysisEngine.instance.createAnalysisContext();
|
| + AnalysisContextImpl newContext = AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
|
| + List<Source> sourcesToRemove = new List<Source>();
|
| {
|
| - JavaIterator<Source> iter = new JavaIterator(_availableSources);
|
| - while (iter.hasNext) {
|
| - Source source = iter.next();
|
| + for (MapEntry<Source, SourceInfo> entry in getMapEntrySet(_sourceMap)) {
|
| + Source source = entry.getKey();
|
| if (container.contains(source)) {
|
| - iter.remove();
|
| - newContext.sourceAvailable(source);
|
| + sourcesToRemove.add(source);
|
| + newContext._sourceMap[source] = new SourceInfo.con2(entry.getValue());
|
| }
|
| }
|
| }
|
| return newContext;
|
| }
|
| - Collection<Source> get availableSources {
|
| - {
|
| - return new List<Source>.from(_availableSources);
|
| - }
|
| - }
|
| Element getElement(ElementLocation location) {
|
| throw new UnsupportedOperationException();
|
| }
|
| @@ -384,14 +573,28 @@ class AnalysisContextImpl implements AnalysisContext {
|
| }
|
| return null;
|
| }
|
| + List<Source> getLibrariesContaining(Source source) {
|
| + {
|
| + SourceInfo info = _sourceMap[source];
|
| + if (info == null) {
|
| + return Source.EMPTY_ARRAY;
|
| + }
|
| + return info.librarySources;
|
| + }
|
| + }
|
| LibraryElement getLibraryElement(Source source) {
|
| {
|
| LibraryElement element = _libraryElementCache[source];
|
| if (element == null) {
|
| - RecordingErrorListener listener = new RecordingErrorListener();
|
| - LibraryResolver resolver = new LibraryResolver(this, listener);
|
| + if (getOrComputeKindOf(source) != SourceKind.LIBRARY) {
|
| + return null;
|
| + }
|
| + LibraryResolver resolver = new LibraryResolver.con1(this);
|
| try {
|
| element = resolver.resolveLibrary(source, true);
|
| + if (element != null) {
|
| + _libraryElementCache[source] = element;
|
| + }
|
| } on AnalysisException catch (exception) {
|
| AnalysisEngine.instance.logger.logError2("Could not resolve the library ${source.fullName}", exception);
|
| }
|
| @@ -433,13 +636,13 @@ class AnalysisContextImpl implements AnalysisContext {
|
| * @return the public namespace of the given library
|
| */
|
| Namespace getPublicNamespace(LibraryElement library) {
|
| - Source source7 = library.definingCompilationUnit.source;
|
| + Source source8 = library.definingCompilationUnit.source;
|
| {
|
| - Namespace namespace = _publicNamespaceCache[source7];
|
| + Namespace namespace = _publicNamespaceCache[source8];
|
| if (namespace == null) {
|
| NamespaceBuilder builder = new NamespaceBuilder();
|
| namespace = builder.createPublicNamespace(library);
|
| - _publicNamespaceCache[source7] = namespace;
|
| + _publicNamespaceCache[source8] = namespace;
|
| }
|
| return namespace;
|
| }
|
| @@ -471,7 +674,14 @@ class AnalysisContextImpl implements AnalysisContext {
|
| SourceFactory get sourceFactory => _sourceFactory;
|
| void mergeAnalysisContext(AnalysisContext context) {
|
| {
|
| - _availableSources.addAll(context.availableSources);
|
| + for (MapEntry<Source, SourceInfo> entry in getMapEntrySet(((context as AnalysisContextImpl))._sourceMap)) {
|
| + Source newSource = entry.getKey();
|
| + SourceInfo existingInfo = _sourceMap[newSource];
|
| + if (existingInfo == null) {
|
| + _sourceMap[newSource] = new SourceInfo.con2(entry.getValue());
|
| + } else {
|
| + }
|
| + }
|
| }
|
| }
|
| CompilationUnit parse(Source source) {
|
| @@ -479,27 +689,39 @@ class AnalysisContextImpl implements AnalysisContext {
|
| CompilationUnit unit = _parseCache[source];
|
| if (unit == null) {
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - Token token = scan(source, errorListener);
|
| + AnalysisContextImpl_ScanResult scanResult = internalScan(source, errorListener);
|
| Parser parser = new Parser(source, errorListener);
|
| - unit = parser.parseCompilationUnit(token);
|
| - unit.parsingErrors = errorListener.errors;
|
| + unit = parser.parseCompilationUnit(scanResult._token);
|
| + unit.parsingErrors = errorListener.getErrors2(source);
|
| + unit.lineInfo = new LineInfo(scanResult._lineStarts);
|
| _parseCache[source] = unit;
|
| }
|
| return unit;
|
| }
|
| }
|
| - CompilationUnit parse2(Source source, AnalysisErrorListener errorListener) {
|
| + CompilationUnit parse3(Source source, AnalysisErrorListener errorListener) {
|
| {
|
| CompilationUnit unit = _parseCache[source];
|
| if (unit == null) {
|
| - Token token = scan(source, errorListener);
|
| + AnalysisContextImpl_ScanResult scanResult = internalScan(source, errorListener);
|
| Parser parser = new Parser(source, errorListener);
|
| - unit = parser.parseCompilationUnit(token);
|
| + unit = parser.parseCompilationUnit(scanResult._token);
|
| + unit.lineInfo = new LineInfo(scanResult._lineStarts);
|
| _parseCache[source] = unit;
|
| }
|
| return unit;
|
| }
|
| }
|
| + HtmlParseResult parseHtml(Source source) {
|
| + {
|
| + HtmlParseResult result = _htmlParseCache[source];
|
| + if (result == null) {
|
| + result = new HtmlParser(source).parse(scanHtml(source));
|
| + _htmlParseCache[source] = result;
|
| + }
|
| + return result;
|
| + }
|
| + }
|
| /**
|
| * Given a table mapping the source for the libraries represented by the corresponding elements to
|
| * the elements representing the libraries, record those mappings.
|
| @@ -513,49 +735,30 @@ class AnalysisContextImpl implements AnalysisContext {
|
| }
|
| CompilationUnit resolve(Source source, LibraryElement library) => parse(source);
|
| Token scan(Source source, AnalysisErrorListener errorListener) {
|
| - List<Token> tokens = new List<Token>(1);
|
| - Source_ContentReceiver receiver = new Source_ContentReceiver_1(source, errorListener, tokens);
|
| + AnalysisContextImpl_ScanResult result = internalScan(source, errorListener);
|
| + return result._token;
|
| + }
|
| + HtmlScanResult scanHtml(Source source) {
|
| + HtmlScanner scanner = new HtmlScanner(source);
|
| try {
|
| - source.getContents(receiver);
|
| + source.getContents(scanner);
|
| } on JavaException catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| }
|
| - return tokens[0];
|
| + return scanner.result;
|
| }
|
| void set sourceFactory(SourceFactory sourceFactory2) {
|
| this._sourceFactory = sourceFactory2;
|
| }
|
| - void sourceAvailable(Source source) {
|
| - {
|
| - javaSetAdd(_availableSources, source);
|
| - }
|
| - }
|
| - void sourceChanged(Source source) {
|
| - {
|
| - _parseCache.remove(source);
|
| - _libraryElementCache.remove(source);
|
| - _publicNamespaceCache.remove(source);
|
| - }
|
| - }
|
| - void sourceDeleted(Source source) {
|
| - {
|
| - _availableSources.remove(source);
|
| - sourceChanged(source);
|
| - }
|
| - }
|
| - void sourcesDeleted(SourceContainer container) {
|
| - {
|
| - _parseCache.clear();
|
| - _libraryElementCache.clear();
|
| - _publicNamespaceCache.clear();
|
| - JavaIterator<Source> iter = new JavaIterator(_availableSources);
|
| - while (iter.hasNext) {
|
| - if (container.contains(iter.next())) {
|
| - iter.remove();
|
| - }
|
| + Iterable<Source> sourcesToResolve(List<Source> changedSources) {
|
| + List<Source> librarySources = new List<Source>();
|
| + for (Source source in changedSources) {
|
| + if (identical(getOrComputeKindOf(source), SourceKind.LIBRARY)) {
|
| + librarySources.add(source);
|
| }
|
| }
|
| + return librarySources;
|
| }
|
| - Iterable<Source> sourcesToResolve(List<Source> changedSources) => JavaArrays.asList(changedSources);
|
| /**
|
| * Return {@code true} if the given compilation unit has a part-of directive.
|
| * @param unit the compilation unit being tested
|
| @@ -569,19 +772,97 @@ class AnalysisContextImpl implements AnalysisContext {
|
| }
|
| return false;
|
| }
|
| + AnalysisContextImpl_ScanResult internalScan(Source source, AnalysisErrorListener errorListener) {
|
| + AnalysisContextImpl_ScanResult result = new AnalysisContextImpl_ScanResult();
|
| + Source_ContentReceiver receiver = new Source_ContentReceiver_2(source, errorListener, result);
|
| + try {
|
| + source.getContents(receiver);
|
| + } on JavaException catch (exception) {
|
| + throw new AnalysisException.con3(exception);
|
| + }
|
| + return result;
|
| + }
|
| + /**
|
| + * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
|
| + * @param source the source that has been added
|
| + */
|
| + void sourceAvailable(Source source) {
|
| + SourceInfo existingInfo = _sourceMap[source];
|
| + if (existingInfo == null) {
|
| + _sourceMap[source] = new SourceInfo.con1(source, getOrComputeKindOf(source));
|
| + }
|
| + }
|
| + /**
|
| + * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
|
| + * @param source the source that has been changed
|
| + */
|
| + void sourceChanged(Source source) {
|
| + SourceInfo info = _sourceMap[source];
|
| + if (info == null) {
|
| + return;
|
| + }
|
| + _parseCache.remove(source);
|
| + _htmlParseCache.remove(source);
|
| + _libraryElementCache.remove(source);
|
| + _publicNamespaceCache.remove(source);
|
| + for (Source librarySource in info.librarySources) {
|
| + _libraryElementCache.remove(librarySource);
|
| + _publicNamespaceCache.remove(librarySource);
|
| + }
|
| + }
|
| + /**
|
| + * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
|
| + * @param source the source that has been deleted
|
| + */
|
| + void sourceDeleted(Source source) {
|
| + _sourceMap.remove(source);
|
| + sourceChanged(source);
|
| + }
|
| + /**
|
| + * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
|
| + * @param container the source container specifying the sources that have been deleted
|
| + */
|
| + void sourcesDeleted(SourceContainer container) {
|
| + List<Source> sourcesToRemove = new List<Source>();
|
| + for (Source source in _sourceMap.keys.toSet()) {
|
| + if (container.contains(source)) {
|
| + sourcesToRemove.add(source);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class {@code ScanResult} represent the results of scanning a source.
|
| + */
|
| +class AnalysisContextImpl_ScanResult {
|
| + /**
|
| + * The first token in the token stream.
|
| + */
|
| + Token _token;
|
| + /**
|
| + * The line start information that was produced.
|
| + */
|
| + List<int> _lineStarts;
|
| + /**
|
| + * Initialize a newly created result object to be empty.
|
| + */
|
| + AnalysisContextImpl_ScanResult() : super() {
|
| + }
|
| }
|
| -class Source_ContentReceiver_1 implements Source_ContentReceiver {
|
| +class Source_ContentReceiver_2 implements Source_ContentReceiver {
|
| Source source;
|
| AnalysisErrorListener errorListener;
|
| - List<Token> tokens;
|
| - Source_ContentReceiver_1(this.source, this.errorListener, this.tokens);
|
| + AnalysisContextImpl_ScanResult result;
|
| + Source_ContentReceiver_2(this.source, this.errorListener, this.result);
|
| accept(CharBuffer contents) {
|
| CharBufferScanner scanner = new CharBufferScanner(source, contents, errorListener);
|
| - tokens[0] = scanner.tokenize();
|
| + result._token = scanner.tokenize();
|
| + result._lineStarts = scanner.lineStarts;
|
| }
|
| void accept2(String contents) {
|
| StringScanner scanner = new StringScanner(source, contents, errorListener);
|
| - tokens[0] = scanner.tokenize();
|
| + result._token = scanner.tokenize();
|
| + result._lineStarts = scanner.lineStarts;
|
| }
|
| }
|
| /**
|
| @@ -591,19 +872,121 @@ class Source_ContentReceiver_1 implements Source_ContentReceiver {
|
| */
|
| class RecordingErrorListener implements AnalysisErrorListener {
|
| /**
|
| - * A list containing the errors that were collected.
|
| + * A HashMap of lists containing the errors that were collected, keyed by each {@link Source}.
|
| */
|
| - List<AnalysisError> _errors = null;
|
| + Map<Source, List<AnalysisError>> _errors = new Map<Source, List<AnalysisError>>();
|
| /**
|
| * Answer the errors collected by the listener.
|
| * @return an array of errors (not {@code null}, contains no {@code null}s)
|
| */
|
| - List<AnalysisError> get errors => _errors != null ? new List.from(_errors) : AnalysisError.NO_ERRORS;
|
| + List<AnalysisError> get errors {
|
| + Set<MapEntry<Source, List<AnalysisError>>> entrySet2 = getMapEntrySet(_errors);
|
| + if (entrySet2.length == 0) {
|
| + return AnalysisError.NO_ERRORS;
|
| + }
|
| + List<AnalysisError> resultList = new List<AnalysisError>(entrySet2.length);
|
| + for (MapEntry<Source, List<AnalysisError>> entry in entrySet2) {
|
| + resultList.addAll(entry.getValue());
|
| + }
|
| + return new List.from(resultList);
|
| + }
|
| + /**
|
| + * Answer the errors collected by the listener for some passed {@link Source}.
|
| + * @param source some {@link Source} for which the caller wants the set of {@link AnalysisError}s
|
| + * collected by this listener
|
| + * @return the errors collected by the listener for the passed {@link Source}
|
| + */
|
| + List<AnalysisError> getErrors2(Source source) {
|
| + List<AnalysisError> errorsForSource = _errors[source];
|
| + if (errorsForSource == null) {
|
| + return AnalysisError.NO_ERRORS;
|
| + } else {
|
| + return new List.from(errorsForSource);
|
| + }
|
| + }
|
| void onError(AnalysisError event) {
|
| - if (_errors == null) {
|
| - _errors = new List<AnalysisError>();
|
| + Source source9 = event.source;
|
| + List<AnalysisError> errorsForSource = _errors[source9];
|
| + if (_errors[source9] == null) {
|
| + errorsForSource = new List<AnalysisError>();
|
| + _errors[source9] = errorsForSource;
|
| + }
|
| + errorsForSource.add(event);
|
| + }
|
| +}
|
| +/**
|
| + * Instances of the class {@code SourceInfo} maintain the information known by an analysis context
|
| + * about an individual source.
|
| + */
|
| +class SourceInfo {
|
| + /**
|
| + * The kind of the source.
|
| + */
|
| + SourceKind _kind;
|
| + /**
|
| + * The sources for the defining compilation units for the libraries containing the source, or{@code null} if the libraries containing the source are not yet known.
|
| + */
|
| + List<Source> _librarySources = null;
|
| + SourceInfo.con1(Source source, SourceKind kind3) {
|
| + _jtd_constructor_151_impl(source, kind3);
|
| + }
|
| + _jtd_constructor_151_impl(Source source, SourceKind kind3) {
|
| + this._kind = kind3;
|
| + }
|
| + /**
|
| + * Initialize a newly created information holder to hold the same information as the given holder.
|
| + * @param info the information holder used to initialize this holder
|
| + */
|
| + SourceInfo.con2(SourceInfo info) {
|
| + _jtd_constructor_152_impl(info);
|
| + }
|
| + _jtd_constructor_152_impl(SourceInfo info) {
|
| + _kind = info._kind;
|
| + _librarySources = new List<Source>.from(info._librarySources);
|
| + }
|
| + /**
|
| + * Add the given source to the list of sources for the defining compilation units for the
|
| + * libraries containing this source.
|
| + * @param source the source to be added to the list
|
| + */
|
| + void addLibrarySource(Source source) {
|
| + if (_librarySources == null) {
|
| + _librarySources = new List<Source>();
|
| + }
|
| + _librarySources.add(source);
|
| + }
|
| + /**
|
| + * Return the kind of the source.
|
| + * @return the kind of the source
|
| + */
|
| + SourceKind get kind => _kind;
|
| + /**
|
| + * Return the sources for the defining compilation units for the libraries containing this source.
|
| + * @return the sources for the defining compilation units for the libraries containing this source
|
| + */
|
| + List<Source> get librarySources {
|
| + if (_librarySources == null) {
|
| + return Source.EMPTY_ARRAY;
|
| }
|
| - _errors.add(event);
|
| + return new List.from(_librarySources);
|
| + }
|
| + /**
|
| + * Remove the given source from the list of sources for the defining compilation units for the
|
| + * libraries containing this source.
|
| + * @param source the source to be removed to the list
|
| + */
|
| + void removeLibrarySource(Source source) {
|
| + _librarySources.remove(source);
|
| + if (_librarySources.isEmpty) {
|
| + _librarySources = null;
|
| + }
|
| + }
|
| + /**
|
| + * Set the kind of the source to the given kind.
|
| + * @param kind the kind of the source
|
| + */
|
| + void set kind(SourceKind kind4) {
|
| + this._kind = kind4;
|
| }
|
| }
|
| /**
|
| @@ -657,4 +1040,4 @@ class Logger_NullLogger implements Logger {
|
| }
|
| void logInformation2(String message, Exception exception) {
|
| }
|
| -}
|
| +}
|
|
|