blob: ea3ea09122acfcaf925fccd36c20f1b6b8b042c4 [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.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.dart.compiler.ast.DartUnit;
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.Elements;
import com.google.dart.compiler.resolver.ResolverErrorCode;
import com.google.dart.compiler.resolver.TypeErrorCode;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* An overall context for the Dart compiler providing an adapter and forwarding
* mechanism for to both {@link DartArtifactProvider} and
* {@link DartCompilerListener}. This is an internal compiler construct and as
* such should not be instantiated or subclassed by those outside the compiler
* itself.
*/
final class DartCompilerMainContext implements DartCompilerListener, DartCompilerContext {
private final LibrarySource lib;
private final DartArtifactProvider provider;
private final DartCompilerListener listener;
private final Map<Source, List<DartCompilationError>> errors = Maps.newHashMap();
private final AtomicInteger errorCount = new AtomicInteger(0);
private final AtomicInteger warningCount = new AtomicInteger(0);
private final AtomicInteger typeErrorCount = new AtomicInteger(0);
private final AtomicBoolean filesHaveChanged = new AtomicBoolean();
// declared volatile for thread-safety
private volatile LibraryUnit appLibraryUnit = null;
private final CompilerConfiguration compilerConfiguration;
DartCompilerMainContext(LibrarySource lib, DartArtifactProvider provider,
DartCompilerListener listener,
CompilerConfiguration compilerConfiguration) {
this.lib = lib;
this.provider = provider;
this.listener = listener;
this.compilerConfiguration = compilerConfiguration;
}
@Override
public void onError(DartCompilationError event) {
// problems in dart:core are not interesting
// http://code.google.com/p/dart/issues/detail?id=7128
if (Elements.isCoreLibrarySource(event.getSource())) {
ErrorCode ec = event.getErrorCode();
if (ec == ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_NUMBER
|| ec == TypeErrorCode.ASSERT_BOOL
|| ec == TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE
|| ec == TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE
|| ec == TypeErrorCode.OPERATOR_EQUALS_BOOL_RETURN_TYPE
|| ec == TypeErrorCode.CANNOT_OVERRIDE_TYPED_MEMBER
|| ec == TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE
|| ec == TypeErrorCode.OPERATOR_WRONG_OPERAND_TYPE) {
return;
}
}
// Remember error.
{
Source source = event.getSource();
if (source != null) {
List<DartCompilationError> sourceErrors = errors.get(source);
if (sourceErrors == null) {
sourceErrors = Lists.newArrayList();
errors.put(source, sourceErrors);
}
sourceErrors.add(event);
}
}
// Increment counters.
if (event.getErrorCode().getSubSystem() == SubSystem.STATIC_TYPE) {
incrementTypeErrorCount();
}
if (event.getErrorCode().getErrorSeverity() == ErrorSeverity.ERROR) {
incrementErrorCount();
} else if (event.getErrorCode().getErrorSeverity() == ErrorSeverity.WARNING) {
incrementWarningCount();
}
// Notify listener.
listener.onError(event);
}
@Override
public LibraryUnit getApplicationUnit() {
return getAppLibraryUnit();
}
@Override
public LibraryUnit getAppLibraryUnit() {
// use double-checked looking pattern with use of volatile
if (appLibraryUnit == null) {
synchronized (this) {
if (appLibraryUnit == null) {
try {
appLibraryUnit = new DartParser(lib, DartParser.read(lib), false,
Sets.<String> newHashSet(), DartCompilerListener.EMPTY, null).preProcessLibraryDirectives(lib);
} catch (IOException e) {
onError(new DartCompilationError(lib, DartCompilerErrorCode.IO, e.getMessage()));
return null;
}
}
}
}
return appLibraryUnit;
}
@Override
public Reader getArtifactReader(Source source, String part, String extension)
throws IOException {
return provider.getArtifactReader(source, part, extension);
}
@Override
public URI getArtifactUri(DartSource source, String part, String extension) {
return provider.getArtifactUri(source, part, extension);
}
@Override
public Writer getArtifactWriter(Source source, String part, String extension)
throws IOException {
return provider.getArtifactWriter(source, part, extension);
}
/**
* @return the {@link DartCompilationError}s found in the given {@link Source}.
*/
public List<DartCompilationError> getSourceErrors(Source source) {
List<DartCompilationError> sourceErrors = errors.get(source);
if (sourceErrors != null) {
return sourceErrors;
}
return Collections.emptyList();
}
public int getErrorCount() {
return errorCount.get();
}
public int getWarningCount() {
return warningCount.get();
}
public int getTypeErrorCount() {
return typeErrorCount.get();
}
@Override
public LibraryUnit getLibraryUnit(LibrarySource libSrc) {
if (libSrc == lib) {
return getApplicationUnit();
}
try {
return new DartParser(libSrc, DartParser.read(libSrc), false,
Sets.<String> newHashSet(), listener, null).preProcessLibraryDirectives(libSrc);
} catch (IOException e) {
onError(new DartCompilationError(libSrc, DartCompilerErrorCode.IO, e.getMessage()));
return null;
}
}
@Override
public boolean isOutOfDate(Source source, Source base, String extension) {
return provider.isOutOfDate(source, base, extension);
}
protected void incrementErrorCount() {
errorCount.incrementAndGet();
}
protected void incrementWarningCount() {
warningCount.incrementAndGet();
}
protected void incrementTypeErrorCount() {
typeErrorCount.incrementAndGet();
}
@Override
public CompilerMetrics getCompilerMetrics() {
return compilerConfiguration.getCompilerMetrics();
}
public void setFilesHaveChanged() {
filesHaveChanged.set(true);
}
public boolean getFilesHaveChanged() {
return filesHaveChanged.get();
}
@Override
public CompilerConfiguration getCompilerConfiguration() {
return compilerConfiguration;
}
/**
* Return the system library corresponding to the specified "dart:<libname>" spec.
*/
@Override
public LibrarySource getSystemLibraryFor(String importSpec) {
return compilerConfiguration.getSystemLibraryFor(importSpec);
}
@Override
public void unitAboutToCompile(DartSource source, boolean diet) {
listener.unitAboutToCompile(source, diet);
}
@Override
public void unitCompiled(DartUnit unit) {
listener.unitCompiled(unit);
}
}