/** * Create a compilation unit that can be serialized from another {@link CompilationUnit}. * * @param unit A unit to copy * @param sourceToken A valid {@DiskCache} token for this unit's source code. * @param astToken A valid {@DiskCache} token for this unit's serialized AST types. */ @SuppressWarnings("deprecation") CachedCompilationUnit(CompilationUnit unit, long sourceToken, long astToken) { assert unit != null; this.compiledClasses = unit.getCompiledClasses(); this.contentId = unit.getContentId(); this.dependencies = unit.getDependencies(); this.resourceLocation = unit.getResourceLocation(); this.resourcePath = unit.getResourcePath(); this.jsniMethods = unit.getJsniMethods(); this.lastModified = unit.getLastModified(); this.methodArgNamesLookup = unit.getMethodArgs(); this.typeName = unit.getTypeName(); this.isError = unit.isError(); this.isGenerated = unit.isGenerated(); this.isSuperSource = unit.isSuperSource(); CategorizedProblem[] problemsIn = unit.getProblems(); if (problemsIn == null) { this.problems = null; } else { this.problems = new CategorizedProblem[problemsIn.length]; for (int i = 0; i < problemsIn.length; i++) { this.problems[i] = new SerializableCategorizedProblem(problemsIn[i]); } } this.astToken = new DiskCacheToken(astToken); this.astVersion = GwtAstBuilder.getSerializationVersion(); this.sourceToken = new DiskCacheToken(sourceToken); }
public void addCompiledUnit(CompilationUnit unit) { addPackages(Shared.getPackageName(unit.getTypeName()).replace('.', '/')); addBinaryTypes(unit.getCompiledClasses()); }
/** * Compiles the source code in each supplied CompilationUnitBuilder into a CompilationUnit and * reports errors. * * <p>A compilation unit is considered invalid if any of its dependencies (recursively) isn't * being compiled and isn't in allValidClasses, or if it has a signature that doesn't match a * dependency. Valid compilation units will be added to cachedUnits and the unit cache, and * their types will be added to allValidClasses. Invalid compilation units will be removed. * * <p>I/O: serializes the AST of each Java type to DiskCache. (This happens even if the * compilation unit is later dropped.) If we're using the persistent unit cache, each valid unit * will also be serialized to the gwt-unitcache file. (As a result, each AST will be copied * there from the DiskCache.) A new persistent unit cache file will be created each time * compile() is called (if there's at least one valid unit) and the entire cache will be * rewritten to disk every {@link PersistentUnitCache#CACHE_FILE_THRESHOLD} files. * * <p>This function won't report errors in invalid source files unless suppressErrors is false. * Instead, a summary giving the number of invalid files will be logged. * * <p>If the JDT compiler aborts, logs an error and throws UnableToCompleteException. (This * doesn't happen for normal compile errors.) */ Collection<CompilationUnit> compile( TreeLogger logger, CompilerContext compilerContext, Collection<CompilationUnitBuilder> builders, Map<CompilationUnitBuilder, CompilationUnit> cachedUnits, EventType eventType) throws UnableToCompleteException { UnitCache unitCache = compilerContext.getUnitCache(); // Initialize the set of valid classes to the initially cached units. for (CompilationUnit unit : cachedUnits.values()) { for (CompiledClass cc : unit.getCompiledClasses()) { // Map by source name. String sourceName = cc.getSourceName(); allValidClasses.put(sourceName, cc); } } ArrayList<CompilationUnit> resultUnits = new ArrayList<CompilationUnit>(); do { final TreeLogger branch = logger.branch(TreeLogger.TRACE, "Compiling..."); // Compile anything that needs to be compiled. buildQueue = new LinkedBlockingQueue<CompilationUnitBuilder>(); final ArrayList<CompilationUnit> newlyBuiltUnits = new ArrayList<CompilationUnit>(); final CompilationUnitBuilder sentinel = CompilationUnitBuilder.create((GeneratedUnit) null); final Throwable[] workerException = new Throwable[1]; final ProgressLogger progressLogger = new ProgressLogger(branch, TreeLogger.TRACE, builders.size(), 10); Thread buildThread = new Thread() { @Override public void run() { int processedCompilationUnitBuilders = 0; try { do { CompilationUnitBuilder builder = buildQueue.take(); if (!progressLogger.isTimerStarted()) { // Set start time here, after first job has arrived, since it can take a // little // while for the first job to arrive, and this helps with the accuracy of the // estimated times. progressLogger.startTimer(); } if (builder == sentinel) { return; } // Expensive, must serialize GWT AST types to bytes. CompilationUnit unit = builder.build(); newlyBuiltUnits.add(unit); processedCompilationUnitBuilders++; progressLogger.updateProgress(processedCompilationUnitBuilders); } while (true); } catch (Throwable e) { workerException[0] = e; } } }; buildThread.setName("CompilationUnitBuilder"); buildThread.start(); Event jdtCompilerEvent = SpeedTracerLogger.start(eventType); long compilationStartNanos = System.nanoTime(); try { compiler.doCompile(branch, builders); } finally { jdtCompilerEvent.end(); } buildQueue.add(sentinel); try { buildThread.join(); long compilationNanos = System.nanoTime() - compilationStartNanos; // Convert nanos to seconds. double compilationSeconds = compilationNanos / (double) TimeUnit.SECONDS.toNanos(1); branch.log( TreeLogger.TRACE, String.format("Compilation completed in %.02f seconds", compilationSeconds)); if (workerException[0] != null) { throw workerException[0]; } } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException("Exception processing units", e); } finally { buildQueue = null; } resultUnits.addAll(newlyBuiltUnits); builders.clear(); // Resolve all newly built unit deps against the global classes. for (CompilationUnit unit : newlyBuiltUnits) { unit.getDependencies().resolve(allValidClasses); } /* * Invalidate any cached units with invalid refs. */ Collection<CompilationUnit> invalidatedUnits = new ArrayList<CompilationUnit>(); for (Iterator<Entry<CompilationUnitBuilder, CompilationUnit>> it = cachedUnits.entrySet().iterator(); it.hasNext(); ) { Entry<CompilationUnitBuilder, CompilationUnit> entry = it.next(); CompilationUnit unit = entry.getValue(); boolean isValid = unit.getDependencies().validate(logger, allValidClasses); if (isValid && unit.isError()) { // See if the unit has classes that can't provide a // NameEnvironmentAnswer for (CompiledClass cc : unit.getCompiledClasses()) { try { cc.getNameEnvironmentAnswer(); } catch (ClassFormatException ex) { isValid = false; break; } } } if (!isValid) { if (logger.isLoggable(TreeLogger.TRACE)) { logger.log(TreeLogger.TRACE, "Invalid Unit: " + unit.getTypeName()); } invalidatedUnits.add(unit); builders.add(entry.getKey()); it.remove(); } } if (invalidatedUnits.size() > 0) { if (logger.isLoggable(TreeLogger.TRACE)) { logger.log(TreeLogger.TRACE, "Invalid units found: " + invalidatedUnits.size()); } } // Any units we invalidated must now be removed from the valid classes. for (CompilationUnit unit : invalidatedUnits) { for (CompiledClass cc : unit.getCompiledClasses()) { allValidClasses.remove(cc.getSourceName()); } } } while (builders.size() > 0); for (CompilationUnit unit : resultUnits) { unitCache.add(unit); } // Any remaining cached units are valid now. resultUnits.addAll(cachedUnits.values()); // Done with a pass of the build - tell the cache its OK to cleanup // stale cache files. unitCache.cleanup(logger); // Sort, then report all errors (re-report for cached units). Collections.sort(resultUnits, CompilationUnit.COMPARATOR); logger = logger.branch(TreeLogger.DEBUG, "Validating units:"); int errorCount = 0; for (CompilationUnit unit : resultUnits) { if (CompilationProblemReporter.reportErrors(logger, unit, suppressErrors)) { errorCount++; } } if (suppressErrors && errorCount > 0 && !logger.isLoggable(TreeLogger.TRACE) && logger.isLoggable(TreeLogger.INFO)) { logger.log( TreeLogger.INFO, "Ignored " + errorCount + " unit" + (errorCount > 1 ? "s" : "") + " with compilation errors in first pass.\n" + "Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors."); } return resultUnits; }
void addValidUnit(CompilationUnit unit) { compiler.addCompiledUnit(unit); for (CompiledClass cc : unit.getCompiledClasses()) { allValidClasses.put(cc.getSourceName(), cc); } }