Index: dart/compiler/java/com/google/dart/compiler/DartCompiler.java |
diff --git a/dart/compiler/java/com/google/dart/compiler/DartCompiler.java b/dart/compiler/java/com/google/dart/compiler/DartCompiler.java |
deleted file mode 100644 |
index b939d6a34fc96b1b5867bcc023bd4263d2db8a72..0000000000000000000000000000000000000000 |
--- a/dart/compiler/java/com/google/dart/compiler/DartCompiler.java |
+++ /dev/null |
@@ -1,1463 +0,0 @@ |
-// 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.base.Objects; |
-import com.google.common.collect.Maps; |
-import com.google.common.collect.Sets; |
-import com.google.common.collect.Sets.SetView; |
-import com.google.common.io.CharStreams; |
-import com.google.common.io.Closeables; |
-import com.google.dart.compiler.CommandLineOptions.CompilerOptions; |
-import com.google.dart.compiler.LibraryDeps.Dependency; |
-import com.google.dart.compiler.UnitTestBatchRunner.Invocation; |
-import com.google.dart.compiler.ast.DartDirective; |
-import com.google.dart.compiler.ast.DartLibraryDirective; |
-import com.google.dart.compiler.ast.DartNode; |
-import com.google.dart.compiler.ast.DartPartOfDirective; |
-import com.google.dart.compiler.ast.DartToSourceVisitor; |
-import com.google.dart.compiler.ast.DartUnit; |
-import com.google.dart.compiler.ast.LibraryExport; |
-import com.google.dart.compiler.ast.LibraryNode; |
-import com.google.dart.compiler.ast.LibraryUnit; |
-import com.google.dart.compiler.ast.Modifiers; |
-import com.google.dart.compiler.common.SourceInfo; |
-import com.google.dart.compiler.metrics.CompilerMetrics; |
-import com.google.dart.compiler.metrics.DartEventType; |
-import com.google.dart.compiler.metrics.JvmMetrics; |
-import com.google.dart.compiler.metrics.Tracer; |
-import com.google.dart.compiler.metrics.Tracer.TraceEvent; |
-import com.google.dart.compiler.parser.DartParser; |
-import com.google.dart.compiler.resolver.CompileTimeConstantAnalyzer; |
-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.Elements; |
-import com.google.dart.compiler.resolver.LibraryElement; |
-import com.google.dart.compiler.resolver.MemberBuilder; |
-import com.google.dart.compiler.resolver.MethodElement; |
-import com.google.dart.compiler.resolver.Resolver; |
-import com.google.dart.compiler.resolver.ResolverErrorCode; |
-import com.google.dart.compiler.resolver.SupertypeResolver; |
-import com.google.dart.compiler.resolver.TopLevelElementBuilder; |
-import com.google.dart.compiler.type.TypeAnalyzer; |
-import com.google.dart.compiler.util.DefaultTextOutput; |
-import com.google.dart.compiler.util.apache.StringUtils; |
- |
-import org.kohsuke.args4j.CmdLineException; |
-import org.kohsuke.args4j.CmdLineParser; |
- |
-import java.io.BufferedReader; |
-import java.io.File; |
-import java.io.FileReader; |
-import java.io.IOException; |
-import java.io.PrintStream; |
-import java.io.Reader; |
-import java.io.Writer; |
-import java.net.URI; |
-import java.util.ArrayList; |
-import java.util.Arrays; |
-import java.util.Collection; |
-import java.util.Collections; |
-import java.util.HashMap; |
-import java.util.HashSet; |
-import java.util.LinkedHashMap; |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Map.Entry; |
-import java.util.Set; |
- |
-/** |
- * Entry point for the Dart compiler. |
- */ |
-public class DartCompiler { |
- |
- static final int RESULT_OK = 0; |
- static final int RESULT_WARNINGS = 1; |
- static final int RESULT_ERRORS = 2; |
- static final int RESULT_OTHER = 127; |
- |
- static class Result { |
- final int code; |
- final String message; |
- public Result(int code, String message) { |
- this.code = code; |
- this.message = message; |
- } |
- Result merge(Result other) { |
- if (other.code > code) { |
- return other; |
- } |
- return this; |
- } |
- } |
- |
- public static final String EXTENSION_DEPS = "deps"; |
- public static final String EXTENSION_LOG = "log"; |
- public static final String EXTENSION_TIMESTAMP = "timestamp"; |
- |
- public static final String CORELIB_URL_SPEC = "dart:core"; |
- public static final String MAIN_ENTRY_POINT_NAME = "main"; |
- |
- private static class Compiler { |
- private final LibrarySource app; |
- private final List<LibrarySource> embeddedLibraries = new ArrayList<LibrarySource>(); |
- private final DartCompilerMainContext context; |
- private final CompilerConfiguration config; |
- private final Map<URI, LibraryUnit> libraries = new LinkedHashMap<URI, LibraryUnit>(); |
- private CoreTypeProvider typeProvider; |
- private final boolean incremental; |
- private final List<DartCompilationPhase> phases; |
- private final LibrarySource coreLibrarySource; |
- |
- private Compiler(LibrarySource app, List<LibrarySource> embedded, CompilerConfiguration config, |
- DartCompilerMainContext context) { |
- this.app = app; |
- this.config = config; |
- this.phases = config.getPhases(); |
- this.context = context; |
- for (LibrarySource library : embedded) { |
- if (PackageLibraryManager.isDartSpec(library.getName())) { |
- LibrarySource foundLibrary = context.getSystemLibraryFor(library.getName()); |
- assert(foundLibrary != null); |
- embeddedLibraries.add(foundLibrary); |
- } else { |
- embeddedLibraries.add(library); |
- } |
- } |
- coreLibrarySource = context.getSystemLibraryFor(CORELIB_URL_SPEC); |
- assert(coreLibrarySource != null); |
- embeddedLibraries.add(coreLibrarySource); |
- |
- incremental = config.incremental(); |
- } |
- |
- void addResolvedLibraries(Map<URI, LibraryUnit> resolvedLibraries) { |
- libraries.putAll(resolvedLibraries); |
- } |
- |
- Map<URI, LibraryUnit> getLibraries() { |
- return libraries; |
- } |
- |
- private void compile() { |
- TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE) : null; |
- try { |
- updateAndResolve(); |
- if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) { |
- return; |
- } |
- compileLibraries(); |
- } catch (IOException e) { |
- context.onError(new DartCompilationError(app, DartCompilerErrorCode.IO, e.getMessage())); |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * Update the current application and any referenced libraries and resolve |
- * them. |
- * |
- * @return a {@link LibraryUnit}, maybe <code>null</code> |
- * @throws IOException on IO errors - the caller must log this if it cares |
- */ |
- private LibraryUnit updateAndResolve() throws IOException { |
- TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.UPDATE_RESOLVE) : null; |
- |
- CompilerMetrics compilerMetrics = context.getCompilerMetrics(); |
- if (compilerMetrics != null) { |
- compilerMetrics.startUpdateAndResolveTime(); |
- } |
- |
- try { |
- LibraryUnit library = updateLibraries(app); |
- importEmbeddedLibraries(); |
- parseOutOfDateFiles(); |
- if (incremental) { |
- addOutOfDateDeps(); |
- } |
- if (!config.resolveDespiteParseErrors() && (context.getErrorCount() > 0)) { |
- return library; |
- } |
- buildLibraryScopes(); |
- LibraryUnit corelibUnit = updateLibraries(coreLibrarySource); |
- typeProvider = new CoreTypeProviderImplementation(corelibUnit.getElement().getScope(), |
- context); |
- resolveLibraries(); |
- validateLibraryDirectives(); |
- return library; |
- } finally { |
- if(compilerMetrics != null) { |
- compilerMetrics.endUpdateAndResolveTime(); |
- } |
- |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * This method reads all libraries. They will be populated from some combination of fully-parsed |
- * and diet-parser compilation units. |
- */ |
- private void parseOutOfDateFiles() throws IOException { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.PARSE_OUTOFDATE) : null; |
- CompilerMetrics compilerMetrics = context.getCompilerMetrics(); |
- long parseStart = compilerMetrics != null ? CompilerMetrics.getCPUTime() : 0; |
- |
- try { |
- final Set<String> topLevelSymbolsDiff = Sets.newHashSet(); |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- LibrarySource libSrc = lib.getSource(); |
- LibraryNode selfSourcePath = lib.getSelfSourcePath(); |
- |
- // Load the existing DEPS, or create an empty one. |
- LibraryDeps deps = lib.getDeps(context); |
- Set<String> newUnitPaths = Sets.newHashSet(); |
- |
- // Parse each compilation unit. |
- for (LibraryNode sourcePathNode : lib.getSourcePaths()) { |
- String relPath = sourcePathNode.getText(); |
- newUnitPaths.add(relPath); |
- |
- // Prepare DartSource for "#source" unit. |
- final DartSource dartSrc = libSrc.getSourceFor(relPath); |
- if (dartSrc == null || !dartSrc.exists()) { |
- continue; |
- } |
- |
- if (!incremental |
- || PackageLibraryManager.isDartUri(libSrc.getUri()) |
- || isSourceOutOfDate(dartSrc)) { |
- DartUnit unit = parse(dartSrc, lib.getPrefixes(), false); |
- // If we just parsed unit of library, report problems. |
- if (sourcePathNode == selfSourcePath) { |
- // report "#import" problems |
- for (LibraryNode importPathNode : lib.getImportPaths()) { |
- LibrarySource dep = getImportSource(libSrc, importPathNode); |
- if (dep == null) { |
- reportMissingSource(context, libSrc, importPathNode); |
- } |
- } |
- // report "#source" problems |
- for (LibraryNode checkSourcePathNode : lib.getSourcePaths()) { |
- String checkRelPath = checkSourcePathNode.getText(); |
- final DartSource checkSource = libSrc.getSourceFor(checkRelPath); |
- if (checkSource == null || !checkSource.exists()) { |
- reportMissingSource(context, libSrc, checkSourcePathNode); |
- } |
- } |
- } |
- |
- // Process unit, if exists. |
- if (unit != null) { |
- if (sourcePathNode == selfSourcePath) { |
- lib.setSelfDartUnit(unit); |
- } |
- // Replace unit within the library. |
- lib.putUnit(unit); |
- context.setFilesHaveChanged(); |
- // Include into top-level symbols diff from current units, already existed or new. |
- { |
- LibraryDeps.Source source = deps.getSource(relPath); |
- Set<String> newTopSymbols = unit.getTopDeclarationNames(); |
- if (source != null) { |
- Set<String> oldTopSymbols = source.getTopSymbols(); |
- SetView<String> diff0 = Sets.symmetricDifference(oldTopSymbols, newTopSymbols); |
- topLevelSymbolsDiff.addAll(diff0); |
- } else { |
- topLevelSymbolsDiff.addAll(newTopSymbols); |
- } |
- } |
- } |
- } else { |
- DartUnit dietUnit = parse(dartSrc, lib.getPrefixes(), true); |
- if (dietUnit != null) { |
- if (sourcePathNode == selfSourcePath) { |
- lib.setSelfDartUnit(dietUnit); |
- } |
- lib.putUnit(dietUnit); |
- } |
- } |
- } |
- |
- // Include into top-level symbols diff from units which disappeared since last compiling. |
- { |
- Set<String> oldUnitPaths = deps.getUnitPaths(); |
- Set<String> disappearedUnitPaths = Sets.difference(oldUnitPaths, newUnitPaths); |
- for (String relPath : disappearedUnitPaths) { |
- LibraryDeps.Source source = deps.getSource(relPath); |
- if (source != null) { |
- Set<String> oldTopSymbols = source.getTopSymbols(); |
- topLevelSymbolsDiff.addAll(oldTopSymbols); |
- } |
- } |
- } |
- } |
- |
- // Parse units, which potentially depend on the difference in top-level symbols. |
- if (!topLevelSymbolsDiff.isEmpty()) { |
- context.setFilesHaveChanged(); |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- LibrarySource libSrc = lib.getSource(); |
- LibraryNode selfSourcePath = lib.getSelfSourcePath(); |
- LibraryDeps deps = lib.getDeps(context); |
- for (LibraryNode libNode : lib.getSourcePaths()) { |
- String relPath = libNode.getText(); |
- // Prepare source dependency. |
- LibraryDeps.Source source = deps.getSource(relPath); |
- if (source == null) { |
- continue; |
- } |
- // Check re-compilation conditions. |
- if (source.shouldRecompileOnAnyTopLevelChange() |
- || !Sets.intersection(source.getAllSymbols(), topLevelSymbolsDiff).isEmpty() |
- || !Sets.intersection(source.getHoles(), topLevelSymbolsDiff).isEmpty()) { |
- DartSource dartSrc = libSrc.getSourceFor(relPath); |
- if (dartSrc == null || !dartSrc.exists()) { |
- continue; |
- } |
- DartUnit unit = parse(dartSrc, lib.getPrefixes(), false); |
- if (unit != null) { |
- if (libNode == selfSourcePath) { |
- lib.setSelfDartUnit(unit); |
- } else { |
- lib.putUnit(unit); |
- } |
- } |
- } |
- } |
- } |
- } |
- } finally { |
- if (compilerMetrics != null) { |
- compilerMetrics.addParseWallTimeNano(CompilerMetrics.getCPUTime() - parseStart); |
- } |
- Tracer.end(logEvent); |
- } |
- } |
- |
- Collection<LibraryUnit> getLibrariesToProcess() { |
- return libraries.values(); |
- } |
- |
- /** |
- * This method reads the embedded library sources, making sure they are added |
- * to the list of libraries to compile. It then adds the libraries as imports |
- * of all libraries. The import is without prefix. |
- */ |
- private void importEmbeddedLibraries() throws IOException { |
- TraceEvent importEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.IMPORT_EMBEDDED_LIBRARIES) : null; |
- try { |
- for (LibrarySource embedded : embeddedLibraries) { |
- updateLibraries(embedded); |
- } |
- |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- for (LibrarySource embedded : embeddedLibraries) { |
- LibraryUnit imp = libraries.get(embedded.getUri()); |
- // Check that the current library is not the embedded library, and |
- // that the current library does not already import the embedded |
- // library. |
- if (lib != imp && !lib.hasImport(imp)) { |
- lib.addImport(imp, null); |
- } |
- } |
- } |
- } finally { |
- Tracer.end(importEvent); |
- } |
- } |
- |
- /** |
- * This method reads a library source and sets it up with its imports. When it |
- * completes, it is guaranteed that {@link Compiler#libraries} will be completely populated. |
- */ |
- private LibraryUnit updateLibraries(LibrarySource libSrc) throws IOException { |
- TraceEvent updateEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.UPDATE_LIBRARIES, "name", |
- libSrc.getName()) : null; |
- try { |
- // Avoid cycles. |
- LibraryUnit lib = libraries.get(libSrc.getUri()); |
- if (lib != null) { |
- return lib; |
- } |
- |
- lib = context.getLibraryUnit(libSrc); |
- // If we could not find the library, continue. The context will report |
- // the error at the end. |
- if (lib == null) { |
- return null; |
- } |
- |
- libraries.put(libSrc.getUri(), lib); |
- |
- // Update dependencies. |
- for (LibraryNode libNode : lib.getImportPaths()) { |
- LibrarySource dep = getImportSource(libSrc, libNode); |
- if (dep != null) { |
- LibraryUnit importedLib = updateLibraries(dep); |
- lib.addImport(importedLib, libNode); |
- if (libNode.isExported()) { |
- lib.addExport(importedLib, libNode); |
- } |
- } |
- } |
- for (LibraryNode libNode : lib.getExportPaths()) { |
- LibrarySource dep = getImportSource(libSrc, libNode); |
- if (dep != null) { |
- lib.addExport(updateLibraries(dep), libNode); |
- } |
- } |
- return lib; |
- } finally { |
- Tracer.end(updateEvent); |
- } |
- } |
- |
- /** |
- * @return the {@link LibrarySource} referenced in the "#import" from "libSrc". May be |
- * <code>null</code> if invalid URI or not existing library. |
- */ |
- private LibrarySource getImportSource(LibrarySource libSrc, LibraryNode libNode) |
- throws IOException { |
- String libSpec = libNode.getText(); |
- LibrarySource dep; |
- try { |
- if (PackageLibraryManager.isDartSpec(libSpec)) { |
- dep = context.getSystemLibraryFor(libSpec); |
- } else { |
- dep = libSrc.getImportFor(libSpec); |
- } |
- } catch (Throwable e) { |
- return null; |
- } |
- if (dep == null || !dep.exists()) { |
- return null; |
- } |
- return dep; |
- } |
- |
- /** |
- * Determines whether the given source is out-of-date with respect to its artifacts. |
- */ |
- private boolean isSourceOutOfDate(DartSource dartSrc) { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.IS_SOURCE_OUTOFDATE, "src", |
- dartSrc.getName()) : null; |
- |
- try { |
- // If incremental compilation is disabled, just return true to force all |
- // units to be recompiled. |
- if (!incremental) { |
- return true; |
- } |
- |
- TraceEvent timestampEvent = |
- Tracer.canTrace() ? Tracer.start( |
- DartEventType.TIMESTAMP_OUTOFDATE, |
- "src", |
- dartSrc.getName()) : null; |
- try { |
- return context.isOutOfDate(dartSrc, dartSrc, EXTENSION_TIMESTAMP); |
- } finally { |
- Tracer.end(timestampEvent); |
- } |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * Build scopes for the given libraries. |
- */ |
- private void buildLibraryScopes() { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.BUILD_LIB_SCOPES) : null; |
- try { |
- Collection<LibraryUnit> libs = getLibrariesToProcess(); |
- |
- // Build the class elements declared in the sources of a library. |
- // Loop can be parallelized. |
- for (LibraryUnit lib : libs) { |
- new TopLevelElementBuilder().exec(lib, context); |
- } |
- |
- // The library scope can then be constructed, containing types declared |
- // in the library, and types declared in the imports. Loop can be parallelized. |
- for (LibraryUnit lib : libs) { |
- new TopLevelElementBuilder().fillInLibraryScope(lib, context); |
- } |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * Parses compilation units that are out-of-date with respect to their dependencies. |
- */ |
- private void addOutOfDateDeps() throws IOException { |
- TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.ADD_OUTOFDATE) : null; |
- try { |
- boolean filesHaveChanged = false; |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- |
- // Load the existing DEPS, or create an empty one. |
- LibraryDeps deps = lib.getDeps(context); |
- |
- // Prepare all top-level symbols. |
- Set<String> oldTopLevelSymbols = Sets.newHashSet(); |
- for (LibraryDeps.Source source : deps.getSources()) { |
- oldTopLevelSymbols.addAll(source.getTopSymbols()); |
- } |
- |
- // Parse units that are out-of-date with respect to their dependencies. |
- for (DartUnit unit : lib.getUnits()) { |
- if (unit.isDiet()) { |
- String relPath = ((DartSource) unit.getSourceInfo().getSource()).getRelativePath(); |
- LibraryDeps.Source source = deps.getSource(relPath); |
- if (isUnitOutOfDate(lib, source)) { |
- filesHaveChanged = true; |
- DartSource dartSrc = lib.getSource().getSourceFor(relPath); |
- if (dartSrc != null && dartSrc.exists()) { |
- unit = parse(dartSrc, lib.getPrefixes(), false); |
- if (unit != null) { |
- lib.putUnit(unit); |
- } |
- } |
- } |
- } |
- } |
- } |
- |
- if (filesHaveChanged) { |
- context.setFilesHaveChanged(); |
- } |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * Determines whether the given dependencies are out-of-date. |
- */ |
- private boolean isUnitOutOfDate(LibraryUnit lib, LibraryDeps.Source source) { |
- // If we don't have dependency information, then we can not be sure that nothing changed. |
- if (source == null) { |
- return true; |
- } |
- // Check all dependencies. |
- for (Dependency dep : source.getDeps()) { |
- LibraryUnit depLib = libraries.get(dep.getLibUri()); |
- if (depLib == null) { |
- return true; |
- } |
- // Prepare unit. |
- DartUnit depUnit = depLib.getUnit(dep.getUnitName()); |
- if (depUnit == null) { |
- return true; |
- } |
- // May be unit modified. |
- if (depUnit.getSourceInfo().getSource().getLastModified() != dep.getLastModified()) { |
- return true; |
- } |
- } |
- // No changed dependencies. |
- return false; |
- } |
- |
- /** |
- * Resolve all libraries. Assume that all library scopes are already built. |
- */ |
- private void resolveLibraries() { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.RESOLVE_LIBRARIES) : null; |
- try { |
- // TODO(jgw): Optimization: Skip work for libraries that have nothing to |
- // compile. |
- |
- // Resolve super class chain, and build the member elements. Both passes |
- // need the library scope to be setup. Each for loop can be |
- // parallelized. |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- for (DartUnit unit : lib.getUnits()) { |
- // These two method calls can be parallelized. |
- new SupertypeResolver().exec(unit, context, getTypeProvider()); |
- new MemberBuilder().exec(unit, context, getTypeProvider()); |
- } |
- } |
- |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- private void validateLibraryDirectives() { |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- // don't need to validate system libraries |
- if (PackageLibraryManager.isDartUri(lib.getSource().getUri())) { |
- continue; |
- } |
- |
- // check for #source uniqueness |
- { |
- Set<URI> includedSourceUris = Sets.newHashSet(); |
- for (LibraryNode sourceNode : lib.getSourcePaths()) { |
- String path = sourceNode.getText(); |
- DartSource source = lib.getSource().getSourceFor(path); |
- if (source != null) { |
- URI uri = source.getUri(); |
- if (includedSourceUris.contains(uri)) { |
- context.onError(new DartCompilationError(sourceNode.getSourceInfo(), |
- DartCompilerErrorCode.UNIT_WAS_ALREADY_INCLUDED, uri)); |
- } |
- includedSourceUris.add(uri); |
- } |
- } |
- } |
- |
- // Validate imports. |
- boolean hasIO = false; |
- boolean hasHTML = false; |
- for (LibraryNode importNode : lib.getImportPaths()) { |
- String libSpec = importNode.getText(); |
- hasIO |= "dart:io".equals(libSpec); |
- hasHTML |= "dart:html".equals(libSpec); |
- // "dart:mirrors" are not done yet |
- if ("dart:mirrors".equals(libSpec)) { |
- context.onError(new DartCompilationError(importNode, |
- DartCompilerErrorCode.MIRRORS_NOT_FULLY_IMPLEMENTED)); |
- } |
- // validate console/web mix |
- if (hasIO && hasHTML) { |
- context.onError(new DartCompilationError(importNode.getSourceInfo(), |
- DartCompilerErrorCode.CONSOLE_WEB_MIX)); |
- } |
- } |
- |
- // check that each exported library has a library directive |
- for (LibraryExport libraryExport : lib.getExports()) { |
- LibraryUnit exportedLibrary = libraryExport.getLibrary(); |
- String exportedLibraryName = getLibraryName(exportedLibrary); |
- // no => error |
- if (exportedLibraryName == null) { |
- SourceInfo info = findExportDirective(lib, exportedLibrary); |
- if (info != null) { |
- Source expSource = exportedLibrary.getSelfDartUnit().getSourceInfo().getSource(); |
- context.onError(new DartCompilationError(info, |
- DartCompilerErrorCode.MISSING_LIBRARY_DIRECTIVE_EXPORT, |
- ((DartSource) expSource).getRelativePath())); |
- } |
- } |
- } |
- |
- // check that each imported library has a library directive |
- Map<String, LibraryUnit> nameToImportedLibrary = Maps.newHashMap(); |
- for (LibraryUnit importedLib : lib.getImportedLibraries()) { |
- |
- if (PackageLibraryManager.isDartUri(importedLib.getSource().getUri())) { |
- // system libraries are always valid |
- continue; |
- } |
- |
- // get the dart unit corresponding to this library |
- DartUnit unit = importedLib.getSelfDartUnit(); |
- if (unit == null || unit.isDiet()) { |
- // don't need to check a unit that hasn't changed |
- continue; |
- } |
- |
- // find imported library name |
- String importedLibraryName = getLibraryName(importedLib); |
- |
- // no name => error |
- if (importedLibraryName == null) { |
- SourceInfo info = findImportDirective(lib, importedLib); |
- if (info != null) { |
- context.onError(new DartCompilationError(info, |
- DartCompilerErrorCode.MISSING_LIBRARY_DIRECTIVE_IMPORT, |
- ((DartSource) unit.getSourceInfo().getSource()).getRelativePath())); |
- } |
- } |
- |
- // has already library with such name => error |
- if (importedLibraryName != null) { |
- LibraryUnit prevLibraryWithSameName = nameToImportedLibrary.get(importedLibraryName); |
- if (prevLibraryWithSameName != null) { |
- SourceInfo info = findImportDirective(lib, importedLib); |
- if (info != null) { |
- Source prevSource = prevLibraryWithSameName.getSelfDartUnit().getSourceInfo().getSource(); |
- context.onError(new DartCompilationError(info, |
- DartCompilerErrorCode.DUPLICATE_IMPORTED_LIBRARY_NAME, |
- importedLibraryName, |
- ((DartSource) prevSource).getRelativePath())); |
- } |
- } else { |
- nameToImportedLibrary.put(importedLibraryName, importedLib); |
- } |
- } |
- } |
- |
- // check that all sourced units have no directives |
- for (DartUnit unit : lib.getUnits()) { |
- // don't need to check a unit that hasn't changed |
- if (unit.isDiet()) { |
- continue; |
- } |
- // ignore library unit |
- DartSource unitSource = (DartSource) unit.getSourceInfo().getSource(); |
- if (isLibrarySelfUnit(lib, unitSource)) { |
- continue; |
- } |
- // analyze directives |
- List<DartDirective> directives = unit.getDirectives(); |
- if (directives.isEmpty()) { |
- context.onError(new DartCompilationError(unitSource, |
- DartCompilerErrorCode.MISSING_PART_OF_DIRECTIVE, lib.getName())); |
- } else if (directives.size() == 1 && directives.get(0) instanceof DartPartOfDirective) { |
- DartPartOfDirective directive = (DartPartOfDirective) directives.get(0); |
- String dirName = directive.getLibraryName(); |
- if (!Objects.equal(dirName, lib.getName())) { |
- context.onError(new DartCompilationError(directive, |
- DartCompilerErrorCode.WRONG_PART_OF_NAME, lib.getName(), dirName)); |
- } |
- } else { |
- context.onError(new DartCompilationError(directives.get(0), |
- DartCompilerErrorCode.ILLEGAL_DIRECTIVES_IN_SOURCED_UNIT, |
- Elements.getRelativeSourcePath(unitSource, lib.getSource()))); |
- } |
- } |
- } |
- } |
- |
- /** |
- * @return the name of the given {@link LibraryUnit} specified in {@link DartLibraryDirective}. |
- */ |
- private static String getLibraryName(LibraryUnit libraryUnit) { |
- DartUnit unit = libraryUnit.getSelfDartUnit(); |
- for (DartDirective directive : unit.getDirectives()) { |
- if (directive instanceof DartLibraryDirective) { |
- return ((DartLibraryDirective) directive).getLibraryName(); |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * @return the {@link SourceInfo} of the import directive in "lib" for "importedLib". |
- */ |
- private static SourceInfo findImportDirective(LibraryUnit lib, LibraryUnit importedLib) { |
- for (LibraryNode importPath : lib.getImportPaths()) { |
- if (importPath.getText().equals(importedLib.getSelfSourcePath().getText())) { |
- return importPath.getSourceInfo(); |
- } |
- } |
- return null; |
- } |
- |
- /** |
- * @return the {@link SourceInfo} of the export directive in "lib" for "importedLib". |
- */ |
- private static SourceInfo findExportDirective(LibraryUnit lib, LibraryUnit importedLib) { |
- for (LibraryNode exportPath : lib.getExportPaths()) { |
- if (exportPath.getText().equals(importedLib.getSelfSourcePath().getText())) { |
- return exportPath.getSourceInfo(); |
- } |
- } |
- return null; |
- } |
- |
- private static boolean isLibrarySelfUnit(LibraryUnit lib, DartSource unitSource) { |
- String unitRelativePath = unitSource.getRelativePath(); |
- for (LibraryNode sourceNode : lib.getSourcePaths()) { |
- if (unitRelativePath.equals(sourceNode.getText())) { |
- if (sourceNode == lib.getSelfSourcePath()) { |
- return true; |
- } |
- return false; |
- } |
- } |
- return false; |
- } |
- |
- private void setEntryPoint() { |
- LibraryUnit lib = context.getAppLibraryUnit(); |
- lib.setEntryNode(new LibraryNode(MAIN_ENTRY_POINT_NAME)); |
- // this ensures that if we find it, it's a top-level static element |
- Element element = lib.getElement().lookupLocalElement(MAIN_ENTRY_POINT_NAME); |
- switch (ElementKind.of(element)) { |
- case NONE: |
- // this is ok, it might just be a library |
- break; |
- |
- case METHOD: |
- MethodElement methodElement = (MethodElement) element; |
- Modifiers modifiers = methodElement.getModifiers(); |
- if (modifiers.isGetter()) { |
- context.onError(new DartCompilationError(element, |
- DartCompilerErrorCode.ENTRY_POINT_METHOD_MAY_NOT_BE_GETTER, MAIN_ENTRY_POINT_NAME)); |
- } else if (modifiers.isSetter()) { |
- context.onError(new DartCompilationError(element, |
- DartCompilerErrorCode.ENTRY_POINT_METHOD_MAY_NOT_BE_SETTER, MAIN_ENTRY_POINT_NAME)); |
- } else if (methodElement.getParameters().size() > 0) { |
- context.onError(new DartCompilationError(element, |
- DartCompilerErrorCode.ENTRY_POINT_METHOD_CANNOT_HAVE_PARAMETERS, |
- MAIN_ENTRY_POINT_NAME)); |
- } else { |
- lib.getElement().setEntryPoint(methodElement); |
- } |
- break; |
- |
- default: |
- context.onError(new DartCompilationError(element, |
- ResolverErrorCode.NOT_A_STATIC_METHOD, MAIN_ENTRY_POINT_NAME)); |
- break; |
- } |
- } |
- |
- private void compileLibraries() throws IOException { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE_LIBRARIES) : null; |
- |
- CompilerMetrics compilerMetrics = context.getCompilerMetrics(); |
- if (compilerMetrics != null) { |
- compilerMetrics.startCompileLibrariesTime(); |
- } |
- |
- try { |
- // Set entry point |
- setEntryPoint(); |
- |
- // The two following for loops can be parallelized. |
- for (LibraryUnit lib : getLibrariesToProcess()) { |
- boolean persist = false; |
- |
- // Compile all the units in this library. |
- for (DartCompilationPhase phase : phases) { |
- |
- // Run all compiler phases including AST simplification and symbol |
- // resolution. This must run in serial. |
- for (DartUnit unit : lib.getUnits()) { |
- |
- // Don't compile diet units. |
- if (unit.isDiet()) { |
- continue; |
- } |
- |
- unit = phase.exec(unit, context, getTypeProvider()); |
- if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) { |
- return; |
- } |
- } |
- |
- } |
- |
- for (DartUnit unit : lib.getUnits()) { |
- if (unit.isDiet()) { |
- continue; |
- } |
- updateAnalysisTimestamp(unit); |
- // To help support the IDE, notify the listener that this unit is compiled. |
- context.unitCompiled(unit); |
- // Update deps. |
- lib.getDeps(context).update(context, unit); |
- // We analyzed something, so we need to persist the deps. |
- persist = true; |
- } |
- |
- // Persist the DEPS file. |
- if (persist) { |
- lib.writeDeps(context); |
- } |
- } |
- } finally { |
- if (compilerMetrics != null) { |
- compilerMetrics.endCompileLibrariesTime(); |
- } |
- Tracer.end(logEvent); |
- } |
- } |
- |
- private void updateAnalysisTimestamp(DartUnit unit) throws IOException { |
- // Update timestamp. |
- Writer writer = |
- context.getArtifactWriter(unit.getSourceInfo().getSource(), "", EXTENSION_TIMESTAMP); |
- String timestampData = String.format("%d\n", System.currentTimeMillis()); |
- writer.write(timestampData); |
- writer.close(); |
- } |
- |
- DartUnit parse(DartSource dartSrc, Set<String> libraryPrefixes, boolean diet) throws IOException { |
- TraceEvent parseEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.PARSE, "src", dartSrc.getName()) : null; |
- CompilerMetrics compilerMetrics = context.getCompilerMetrics(); |
- long parseStart = compilerMetrics != null ? CompilerMetrics.getThreadTime() : 0; |
- Reader r = dartSrc.getSourceReader(); |
- String srcCode; |
- boolean failed = true; |
- try { |
- try { |
- srcCode = CharStreams.toString(r); |
- failed = false; |
- } finally { |
- Closeables.close(r, failed); |
- } |
- |
- DartParser parser = new DartParser(dartSrc, srcCode, diet, libraryPrefixes, context, |
- context.getCompilerMetrics()); |
- DartUnit unit = parser.parseUnit(); |
- if (compilerMetrics != null) { |
- compilerMetrics.addParseTimeNano(CompilerMetrics.getThreadTime() - parseStart); |
- } |
- |
- if (!config.resolveDespiteParseErrors() && context.getErrorCount() > 0) { |
- // We don't return this unit, so no more processing expected for it. |
- context.unitCompiled(unit); |
- return null; |
- } |
- return unit; |
- } finally { |
- Tracer.end(parseEvent); |
- } |
- } |
- |
- private void reportMissingSource(DartCompilerContext context, |
- LibrarySource libSrc, |
- LibraryNode libNode) { |
- if (libNode != null && StringUtils.startsWith(libNode.getText(), "dart-ext:")) { |
- return; |
- } |
- DartCompilationError event = new DartCompilationError(libNode, |
- DartCompilerErrorCode.MISSING_SOURCE, |
- libNode.getText()); |
- event.setSource(libSrc); |
- context.onError(event); |
- } |
- CoreTypeProvider getTypeProvider() { |
- typeProvider.getClass(); // Quick null check. |
- return typeProvider; |
- } |
- } |
- |
- /** |
- * Provides cached parse and resolution results during selective compilation |
- */ |
- public abstract static class SelectiveCache { |
- |
- /** |
- * Answer the cached resolved libraries |
- * |
- * @return a mapping (not <code>null</code>) of library source URI to cached {@link LibraryUnit} |
- */ |
- public abstract Map<URI, LibraryUnit> getResolvedLibraries(); |
- |
- /** |
- * Answer the cached unresolved {@link DartUnit} for the specified source |
- * |
- * @param dartSrc the source (not <code>null</code>) |
- * @return the cached unit or <code>null</code> if it is not cached |
- */ |
- public abstract DartUnit getUnresolvedDartUnit(DartSource dartSrc); |
- } |
- |
- /** |
- * Selectively compile a library. Use supplied libraries and ASTs when available. |
- * This allows programming tools to provide customized ASTs for code that is currently being |
- * edited, and may not compile correctly. |
- */ |
- static class SelectiveCompiler extends Compiler { |
- private final SelectiveCache selectiveCache; |
- private Collection<LibraryUnit> librariesToProcess; |
- |
- private SelectiveCompiler(LibrarySource app, SelectiveCache selectiveCache, |
- CompilerConfiguration config, DartCompilerMainContext context) { |
- super(app, Collections.<LibrarySource>emptyList(), config, context); |
- this.selectiveCache = selectiveCache; |
- addResolvedLibraries(selectiveCache.getResolvedLibraries()); |
- } |
- |
- @Override |
- Collection<LibraryUnit> getLibrariesToProcess() { |
- if (librariesToProcess == null) { |
- librariesToProcess = new ArrayList<LibraryUnit>(); |
- librariesToProcess.addAll(super.getLibrariesToProcess()); |
- librariesToProcess.removeAll(selectiveCache.getResolvedLibraries().values()); |
- } |
- return librariesToProcess; |
- } |
- |
- @Override |
- DartUnit parse(DartSource dartSrc, Set<String> prefixes, boolean diet) throws IOException { |
- DartUnit parsedUnit = selectiveCache.getUnresolvedDartUnit(dartSrc); |
- if (parsedUnit != null) { |
- return parsedUnit; |
- } |
- return super.parse(dartSrc, prefixes, diet); |
- } |
- } |
- |
- private static CompilerOptions processCommandLineOptions(String[] args) { |
- CmdLineParser cmdLineParser = null; |
- CompilerOptions compilerOptions = null; |
- try { |
- compilerOptions = new CompilerOptions(); |
- cmdLineParser = CommandLineOptions.parse(args, compilerOptions); |
- if (args.length == 0 || compilerOptions.showHelp()) { |
- showUsage(cmdLineParser, System.err); |
- System.exit(1); |
- } |
- } catch (CmdLineException e) { |
- System.err.println(e.getLocalizedMessage()); |
- showUsage(cmdLineParser, System.err); |
- System.exit(1); |
- } |
- |
- assert compilerOptions != null; |
- return compilerOptions; |
- } |
- |
- public static void main(final String[] topArgs) { |
- Tracer.init(); |
- |
- CompilerOptions topCompilerOptions = processCommandLineOptions(topArgs); |
- Result result = null; |
- try { |
- // configure UTF-8 output |
- System.setOut(new PrintStream(System.out, true, "UTF-8")); |
- System.setErr(new PrintStream(System.err, true, "UTF-8")); |
- |
- if (topCompilerOptions.showVersion()) { |
- showVersion(topCompilerOptions); |
- System.exit(RESULT_OK); |
- } |
- if (topCompilerOptions.shouldBatch()) { |
- if (topArgs.length > 1) { |
- System.err.println("(Extra arguments specified with -batch ignored.)"); |
- } |
- result = UnitTestBatchRunner.runAsBatch(topArgs, new Invocation() { |
- @Override |
- public Result invoke(String[] lineArgs) throws Throwable { |
- List<String> allArgs = new ArrayList<String>(); |
- for (String arg: topArgs) { |
- if (!arg.equals("-batch")) { |
- allArgs.add(arg); |
- } |
- } |
- for (String arg: lineArgs) { |
- allArgs.add(arg); |
- } |
- |
- CompilerOptions compilerOptions = processCommandLineOptions( |
- allArgs.toArray(new String[allArgs.size()])); |
- if (compilerOptions.shouldBatch()) { |
- System.err.println("-batch ignored: Already in batch mode."); |
- } |
- return compilerMain(compilerOptions); |
- } |
- }); |
- } else { |
- System.out.println("WARNING: This command is now deprecated, please use dartanalyzer instead."); |
- System.out.println("For more info, see www.dartlang.org/tools/analyzer."); |
- System.out.println(); |
- |
- result = compilerMain(topCompilerOptions); |
- } |
- } catch (Throwable t) { |
- t.printStackTrace(); |
- crash(); |
- } |
- // exit |
- { |
- int exitCode = result.code; |
- if (!topCompilerOptions.extendedExitCode()) { |
- if (exitCode == RESULT_ERRORS) { |
- exitCode = 1; |
- } else { |
- exitCode = 0; |
- } |
- } |
- System.exit(exitCode); |
- } |
- } |
- |
- /** |
- * Invoke the compiler to build single application. |
- * |
- * @param compilerOptions parsed command line arguments |
- * @return the result as integer when <code>0</code> means clean; <code>1</code> there were |
- * warnings; <code>2</code> there were errors; <code>127</code> other problems or |
- * exceptions. |
- */ |
- public static Result compilerMain(CompilerOptions compilerOptions) throws IOException { |
- List<String> sourceFiles = compilerOptions.getSourceFiles(); |
- if (sourceFiles.size() == 0) { |
- System.err.println("dart_analyzer: no source files were specified."); |
- showUsage(null, System.err); |
- return new Result(RESULT_OTHER, null); |
- } |
- |
- File sourceFile = new File(sourceFiles.get(0)); |
- if (!sourceFile.exists()) { |
- System.err.println("dart_analyzer: file not found: " + sourceFile); |
- showUsage(null, System.err); |
- return new Result(RESULT_OTHER, null); |
- } |
- |
- CompilerConfiguration config = new DefaultCompilerConfiguration(compilerOptions); |
- config.getPackageLibraryManager().setPackageRoots(Arrays.asList(new File[]{compilerOptions.getPackageRoot()})); |
- return compilerMain(sourceFile, config); |
- } |
- |
- /** |
- * Invoke the compiler to build single application. |
- * |
- * @param sourceFile file passed on the command line to build |
- * @param config compiler configuration built from parsed command line options |
- */ |
- public static Result compilerMain(File sourceFile, CompilerConfiguration config) |
- throws IOException { |
- Result result = compileApp(sourceFile, config); |
- String errorMessage = result.message; |
- if (errorMessage != null) { |
- System.err.println(errorMessage); |
- return result; |
- } |
- |
- TraceEvent logEvent = Tracer.canTrace() ? Tracer.start(DartEventType.WRITE_METRICS) : null; |
- try { |
- maybeShowMetrics(config); |
- } finally { |
- Tracer.end(logEvent); |
- } |
- return result; |
- } |
- |
- public static void crash() { |
- // Our test scripts look for 253 to signal a "crash". |
- System.exit(253); |
- } |
- |
- private static void showUsage(CmdLineParser cmdLineParser, PrintStream out) { |
- out.println("Usage: dart_analyzer [<options>] <dart-script> [script-arguments]"); |
- out.println("Available options:"); |
- if (cmdLineParser == null) { |
- cmdLineParser = new CmdLineParser(new CompilerOptions()); |
- } |
- cmdLineParser.printUsage(out); |
- } |
- |
- private static void maybeShowMetrics(CompilerConfiguration config) { |
- CompilerMetrics compilerMetrics = config.getCompilerMetrics(); |
- if (compilerMetrics != null) { |
- compilerMetrics.write(System.out); |
- } |
- |
- JvmMetrics.maybeWriteJvmMetrics(System.out, config.getJvmMetricOptions()); |
- } |
- |
- /** |
- * Treats the <code>sourceFile</code> as the top level library and generates compiled output by |
- * linking the dart source in this file with all libraries referenced with <code>#import</code> |
- * statements. |
- * |
- * @return the result as integer when <code>0</code> means clean; <code>1</code> there were |
- * warnings; <code>2</code> there were errors; <code>127</code> other problems or |
- * exceptions. |
- */ |
- public static Result compileApp(File sourceFile, CompilerConfiguration config) throws IOException { |
- TraceEvent logEvent = |
- Tracer.canTrace() ? Tracer.start(DartEventType.COMPILE_APP, "src", sourceFile.toString()) |
- : null; |
- try { |
- File outputDirectory = config.getOutputDirectory(); |
- DefaultDartArtifactProvider provider = new DefaultDartArtifactProvider(outputDirectory); |
- // Compile the Dart application and its dependencies. |
- PackageLibraryManager libraryManager = config.getPackageLibraryManager(); |
- final LibrarySource lib = new UrlLibrarySource(sourceFile.toURI(),libraryManager); |
- DefaultDartCompilerListener listener; |
- if (config.getCompilerOptions().showSourceFromAst()) { |
- listener = new DefaultDartCompilerListener(config.printErrorFormat()) { |
- @Override |
- public void unitCompiled(DartUnit unit) { |
- if (unit.getLibrary() != null) { |
- if (unit.getLibrary().getSource() == lib) { |
- DefaultTextOutput output = new DefaultTextOutput(false); |
- unit.accept(new DartToSourceVisitor(output)); |
- System.out.println(output.toString()); |
- } |
- } |
- } |
- }; |
- } else { |
- listener = new DefaultDartCompilerListener(config.printErrorFormat()); |
- } |
- return compileLib(lib, config, provider, listener); |
- } finally { |
- Tracer.end(logEvent); |
- } |
- } |
- |
- /** |
- * Compiles the given library, translating all its source files, and those |
- * of its imported libraries, transitively. |
- * |
- * @param lib The library to be compiled (not <code>null</code>) |
- * @param config The compiler configuration specifying the compilation phases |
- * @param provider A mechanism for specifying where code should be generated |
- * @param listener An object notified when compilation errors occur |
- */ |
- public static Result compileLib(LibrarySource lib, CompilerConfiguration config, |
- DartArtifactProvider provider, DartCompilerListener listener) throws IOException { |
- return compileLib(lib, Collections.<LibrarySource>emptyList(), config, provider, listener); |
- } |
- |
- /** |
- * Same method as above, but also takes a list of libraries that should be |
- * implicitly imported by all libraries. These libraries are provided by the embedder. |
- */ |
- public static Result compileLib(LibrarySource lib, |
- List<LibrarySource> embeddedLibraries, |
- CompilerConfiguration config, |
- DartArtifactProvider provider, |
- DartCompilerListener listener) throws IOException { |
- DartCompilerMainContext context = new DartCompilerMainContext(lib, provider, listener, |
- config); |
- new Compiler(lib, embeddedLibraries, config, context).compile(); |
- int errorCount = context.getErrorCount(); |
- if (config.typeErrorsAreFatal()) { |
- errorCount += context.getTypeErrorCount(); |
- } |
- if (config.warningsAreFatal()) { |
- errorCount += context.getWarningCount(); |
- } |
- if (errorCount > 0) { |
- return new Result(RESULT_ERRORS, "Compilation failed with " + errorCount |
- + (errorCount == 1 ? " problem." : " problems.")); |
- } |
- if (!context.getFilesHaveChanged()) { |
- return null; |
- } |
- // Write checking log. |
- { |
- Writer writer = provider.getArtifactWriter(lib, "", EXTENSION_LOG); |
- boolean threw = true; |
- try { |
- writer.write(String.format("Checked %s and found:%n", lib.getName())); |
- writer.write(String.format(" no load/resolution errors%n")); |
- writer.write(String.format(" %s type errors%n", context.getTypeErrorCount())); |
- threw = false; |
- } finally { |
- Closeables.close(writer, threw); |
- } |
- } |
- { |
- int resultCode = RESULT_OK; |
- if (context.getWarningCount() != 0) { |
- resultCode = RESULT_WARNINGS; |
- } |
- return new Result(resultCode, null); |
- } |
- } |
- |
- /** |
- * Analyzes the given library and all its transitive dependencies. |
- * |
- * @param lib The library to be analyzed |
- * @param parsedUnits A collection of unresolved ASTs that should be used |
- * instead of parsing the associated source from storage. Intended for |
- * IDE use when modified buffers must be analyzed. AST nodes in the map may be |
- * ignored if not referenced by {@code lib}. (May be null.) |
- * @param config The compiler configuration (phases will not be used), but resolution and |
- * type-analysis will be invoked |
- * @param provider A mechanism for specifying where code should be generated |
- * @param listener An object notified when compilation errors occur |
- * @throws NullPointerException if any of the arguments except {@code parsedUnits} |
- * are {@code null} |
- * @throws IOException on IO errors, which are not logged |
- */ |
- public static LibraryUnit analyzeLibrary(LibrarySource lib, final Map<URI, DartUnit> parsedUnits, |
- CompilerConfiguration config, DartArtifactProvider provider, DartCompilerListener listener) |
- throws IOException { |
- final PackageLibraryManager manager = config.getPackageLibraryManager(); |
- final HashMap<URI, LibraryUnit> resolvedLibs = new HashMap<URI, LibraryUnit>(); |
- SelectiveCache selectiveCache = new SelectiveCache() { |
- @Override |
- public Map<URI, LibraryUnit> getResolvedLibraries() { |
- return resolvedLibs; |
- } |
- @Override |
- public DartUnit getUnresolvedDartUnit(DartSource dartSrc) { |
- if (parsedUnits == null) { |
- return null; |
- } |
- URI srcUri = dartSrc.getUri(); |
- DartUnit parsedUnit = parsedUnits.remove(srcUri); |
- if (parsedUnit != null) { |
- return parsedUnit; |
- } |
- URI fileUri = manager.resolveDartUri(srcUri); |
- return parsedUnits.remove(fileUri); |
- } |
- }; |
- Map<URI, LibraryUnit> libraryUnit = analyzeLibraries(lib, selectiveCache, config, |
- provider, listener, false); |
- return libraryUnit != null ? libraryUnit.get(lib.getUri()) : null; |
- } |
- |
- /** |
- * Analyzes the given library and all its transitive dependencies. |
- * |
- * @param lib The library to be analyzed |
- * @param selectiveCache Provides cached parse and resolution results |
- * during selective compilation (not <code>null</code>) |
- * @param config The compiler configuration (phases and backends |
- * will not be used), but resolution and type-analysis will be invoked |
- * @param provider A mechanism for specifying where code should be generated |
- * @param listener An object notified when compilation errors occur |
- * @param resolveAllNewLibs <code>true</code> if all new libraries should be resolved |
- * or false if only the library specified by the "lib" parameter should be resolved |
- * @throws NullPointerException if any of the arguments except {@code parsedUnits} |
- * are {@code null} |
- * @throws IOException on IO errors, which are not logged |
- */ |
- public static Map<URI, LibraryUnit> analyzeLibraries(LibrarySource lib, |
- SelectiveCache selectiveCache, CompilerConfiguration config, |
- DartArtifactProvider provider, DartCompilerListener listener, |
- boolean resolveAllNewLibs) throws IOException { |
- lib.getClass(); // Quick null check. |
- provider.getClass(); // Quick null check. |
- listener.getClass(); // Quick null check. |
- Map<URI, LibraryUnit> resolvedLibs = selectiveCache.getResolvedLibraries(); |
- DartCompilerMainContext context = new DartCompilerMainContext(lib, provider, listener, config); |
- Compiler compiler = new SelectiveCompiler(lib, selectiveCache, config, context); |
- |
- LibraryUnit topLibUnit = compiler.updateAndResolve(); |
- if (topLibUnit == null) { |
- return null; |
- } |
- |
- Map<URI, LibraryUnit> librariesToResolve; |
- librariesToResolve = new HashMap<URI, LibraryUnit>(); |
- if (resolveAllNewLibs) { |
- librariesToResolve.putAll(compiler.getLibraries()); |
- } |
- librariesToResolve.put(topLibUnit.getSource().getUri(), topLibUnit); |
- |
- DartCompilationPhase[] phases = { |
- new Resolver.Phase(), |
- new CompileTimeConstantAnalyzer.Phase(), |
- new TypeAnalyzer()}; |
- Map<URI, LibraryUnit> newLibraries = Maps.newHashMap(); |
- for (Entry<URI, LibraryUnit> entry : librariesToResolve.entrySet()) { |
- URI libUri = entry.getKey(); |
- LibraryUnit libUnit = entry.getValue(); |
- if (!resolvedLibs.containsKey(libUri) && libUnit != null) { |
- newLibraries.put(libUri, libUnit); |
- for (DartCompilationPhase phase : phases) { |
- // Run phase on all units, because "const" phase expects to have fully resolved library. |
- for (DartUnit unit : libUnit.getUnits()) { |
- if (unit.isDiet()) { |
- continue; |
- } |
- unit = phase.exec(unit, context, compiler.getTypeProvider()); |
- } |
- } |
- // To help support the IDE, notify the listener that these unit were compiled. |
- for (DartUnit unit : libUnit.getUnits()) { |
- context.unitCompiled(unit); |
- } |
- } |
- } |
- |
- return newLibraries; |
- } |
- |
- /** |
- * Re-analyzes source code after a modification. The modification is described by a SourceDelta. |
- * |
- * @param delta what has changed |
- * @param enclosingLibrary the library in which the change occurred |
- * @param interestStart beginning of interest area (as character offset from the beginning of the |
- * source file after the change. |
- * @param interestLength length of interest area |
- * @return a node which covers the entire interest area. |
- */ |
- public static DartNode analyzeDelta(SourceDelta delta, |
- LibraryElement enclosingLibrary, |
- LibraryElement coreLibrary, |
- DartNode interestNode, |
- int interestStart, |
- int interestLength, |
- CompilerConfiguration config, |
- DartCompilerListener listener) throws IOException { |
- DeltaAnalyzer analyzer = new DeltaAnalyzer(delta, enclosingLibrary, coreLibrary, |
- interestNode, interestStart, interestLength, |
- config, listener); |
- return analyzer.analyze(); |
- } |
- |
- public static LibraryUnit findLibrary(LibraryUnit libraryUnit, String uri, |
- Set<LibraryElement> seen) { |
- if (seen.contains(libraryUnit.getElement())) { |
- return null; |
- } |
- seen.add(libraryUnit.getElement()); |
- if (uri.equals(libraryUnit.getName())) { |
- return libraryUnit; |
- } |
- for (LibraryNode src : libraryUnit.getSourcePaths()) { |
- if (src.getText().equals(uri)) { |
- return libraryUnit; |
- } |
- } |
- for (LibraryUnit importedLibrary : libraryUnit.getImportedLibraries()) { |
- LibraryUnit unit = findLibrary(importedLibrary, uri, seen); |
- if (unit != null) { |
- return unit; |
- } |
- } |
- return null; |
- } |
- |
- public static LibraryUnit getCoreLib(LibraryUnit libraryUnit) { |
- LibraryUnit coreLib = findLibrary(libraryUnit, "dart.core", new HashSet<LibraryElement>()); |
- if (coreLib == null) { |
- coreLib = findLibrary(libraryUnit, "dart:core", new HashSet<LibraryElement>()); |
- } |
- return coreLib; |
- } |
- |
- private static void showVersion(CompilerOptions options) { |
- String version = getSdkVersion(options); |
- if (version == null) { |
- version = "<unkown>"; |
- } |
- System.out.println("dart_analyzer version " + version); |
- } |
- |
- /** |
- * @return the numeric revision of SDK, may be <code>null</code> if cannot find. |
- */ |
- private static String getSdkVersion(CompilerOptions options) { |
- try { |
- File sdkPath = options.getDartSdkPath(); |
- File revisionFile = new File(sdkPath, "version"); |
- if (revisionFile.exists() && revisionFile.isFile()) { |
- BufferedReader br = new BufferedReader(new FileReader(revisionFile)); |
- try { |
- return br.readLine(); |
- } finally { |
- br.close(); |
- } |
- } |
- } catch (Throwable e) { |
- } |
- return null; |
- } |
-} |