blob: 2829cd95f202a3e14fe7aa7abfdbb840f7fd5d7b [file] [log] [blame]
// 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.ElementKind;
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) {
String name = member.getName();
if (ElementKind.of(member) == ElementKind.LIBRARY) {
name = "__library_" + ((LibraryElement) member).getLibraryUnit().getName();
}
scope.declareElement(name, 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) {
}
}
}