| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| package com.google.dart.compiler; |
| |
| import com.google.common.collect.Sets; |
| import com.google.common.io.CharStreams; |
| import com.google.common.io.Closeables; |
| import com.google.dart.compiler.ast.DartNode; |
| import com.google.dart.compiler.ast.DartUnit; |
| import com.google.dart.compiler.ast.LibraryNode; |
| import com.google.dart.compiler.ast.LibraryUnit; |
| import com.google.dart.compiler.metrics.CompilerMetrics; |
| import com.google.dart.compiler.parser.DartParser; |
| import com.google.dart.compiler.resolver.CoreTypeProvider; |
| import com.google.dart.compiler.resolver.CoreTypeProviderImplementation; |
| import com.google.dart.compiler.resolver.Element; |
| import com.google.dart.compiler.resolver.LibraryElement; |
| import com.google.dart.compiler.resolver.MemberBuilder; |
| import com.google.dart.compiler.resolver.Resolver; |
| import com.google.dart.compiler.resolver.Scope; |
| import com.google.dart.compiler.resolver.SupertypeResolver; |
| import com.google.dart.compiler.resolver.TopLevelElementBuilder; |
| import com.google.dart.compiler.type.TypeAnalyzer; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.Writer; |
| import java.net.URI; |
| |
| class DeltaAnalyzer { |
| private final SourceDelta delta; |
| private final LibraryElement enclosingLibrary; |
| private final CompilerConfiguration config; |
| private final DartCompilerListener listener; |
| private final CoreTypeProvider typeProvider; |
| private final DartCompilerContext context; |
| |
| public DeltaAnalyzer(SourceDelta delta, |
| LibraryElement enclosingLibrary, |
| LibraryElement coreLibrary, |
| DartNode interestNode, |
| int interestStart, |
| int interestLength, |
| CompilerConfiguration config, |
| DartCompilerListener listener) { |
| this.delta = delta; |
| this.enclosingLibrary = enclosingLibrary; |
| this.config = config; |
| this.listener = listener; |
| typeProvider = new CoreTypeProviderImplementation(coreLibrary.getScope(), listener); |
| this.context = new Context(); |
| } |
| |
| public DartNode analyze() throws IOException { |
| Source originalSource = delta.getSourceBefore(); |
| DartUnit unit = delta.getUnitAfter(); |
| if (unit == null) { |
| DartSource source = delta.getSourceAfter(); |
| unit = getParser(source).parseUnit(); |
| } |
| Scope scope = deltaLibraryScope(originalSource, unit); |
| // We have to create supertypes and member elements for the entire unit. For example, if you're |
| // doing code-completion, you are only interested in the current expression, but you may be |
| // code-completing on a type that is defined outside the current class. |
| new SupertypeResolver().exec(unit, context, typeProvider); |
| new MemberBuilder().exec(unit, context, typeProvider); |
| |
| // The following two phases can be narrowed down to the interest area. We currently ignore the |
| // interest area, but long term, we will need to narrow down to the interest area to handle |
| // very large files. |
| new Resolver(context, scope, typeProvider).exec(unit); |
| new TypeAnalyzer().exec(unit, context, typeProvider); |
| return unit; |
| } |
| |
| private Scope deltaLibraryScope(Source originalSource, DartUnit unit) { |
| // Create a library unit which holds the new unit. |
| LibraryUnit libraryUnit = new LibraryUnit(makeLibrarySource("delta")); |
| // Copy all the imports |
| for (LibraryNode path : enclosingLibrary.getLibraryUnit().getImportPaths()) { |
| libraryUnit.addImportPath(path); |
| } |
| for (LibraryUnit importUnit : enclosingLibrary.getLibraryUnit().getImportedLibraries()) { |
| libraryUnit.addImport(importUnit, importUnit.getEntryNode()); |
| } |
| libraryUnit.putUnit(unit); |
| |
| // Create top-level elements for the new unit. |
| new TopLevelElementBuilder().exec(libraryUnit, context); |
| new TopLevelElementBuilder().fillInLibraryScope(libraryUnit, listener); |
| |
| // Copy all the elements from the old library, except the ones declared in the original source. |
| Scope scope = libraryUnit.getElement().getScope(); |
| for (Element member : enclosingLibrary.getMembers()) { |
| if (member.getSourceInfo().getSource() != originalSource) { |
| scope.declareElement(member.getName(), member); |
| } |
| } |
| return scope; |
| } |
| |
| private LibrarySource makeLibrarySource(final String name) { |
| final URI uri = URI.create(name); |
| return new LibrarySource() { |
| @Override |
| public String getUniqueIdentifier() { |
| return uri.toString(); |
| } |
| |
| @Override |
| public URI getUri() { |
| return uri; |
| } |
| |
| @Override |
| public Reader getSourceReader() { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| @Override |
| public long getLastModified() { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public boolean exists() { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public DartSource getSourceFor(String relPath) { |
| return null; |
| } |
| |
| @Override |
| public LibrarySource getImportFor(String relPath) { |
| return null; |
| } |
| }; |
| } |
| |
| private DartParser getParser(Source source) throws IOException { |
| Reader r = source.getSourceReader(); |
| String sourceString = CharStreams.toString(r); |
| Closeables.close(r, false); |
| return new DartParser(source, sourceString, false, Sets.<String>newHashSet(), listener, null); |
| } |
| |
| private class Context implements DartCompilerListener, DartCompilerContext { |
| @Override |
| public LibraryUnit getApplicationUnit() { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public LibraryUnit getAppLibraryUnit() { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public LibraryUnit getLibraryUnit(LibrarySource lib) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public Reader getArtifactReader(Source source, String part, String extension) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public URI getArtifactUri(DartSource source, String part, String extension) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public Writer getArtifactWriter(Source source, String part, String extension) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public boolean isOutOfDate(Source source, Source base, String extension) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public CompilerMetrics getCompilerMetrics() { |
| return null; |
| } |
| |
| @Override |
| public CompilerConfiguration getCompilerConfiguration() { |
| return config; |
| } |
| |
| @Override |
| public LibrarySource getSystemLibraryFor(String importSpec) { |
| throw new AssertionError(); |
| } |
| |
| @Override |
| public void onError(DartCompilationError event) { |
| listener.onError(event); |
| } |
| |
| @Override |
| public void unitAboutToCompile(DartSource source, boolean diet) { |
| } |
| |
| @Override |
| public void unitCompiled(DartUnit unit) { |
| } |
| } |
| } |