Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Unified Diff: compiler/java/com/google/dart/compiler/LibraryDeps.java

Issue 9148026: Recompile unit with potential conflict/dependency on some top-level symbol. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix for compiling corelib, so NPE in TreeShaker Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: compiler/java/com/google/dart/compiler/LibraryDeps.java
diff --git a/compiler/java/com/google/dart/compiler/LibraryDeps.java b/compiler/java/com/google/dart/compiler/LibraryDeps.java
index a1ec4a0100a090927911a18d2104c2d28c682903..7d37a3108f545d0c707f5563de89b3a7af04a280 100644
--- a/compiler/java/com/google/dart/compiler/LibraryDeps.java
+++ b/compiler/java/com/google/dart/compiler/LibraryDeps.java
@@ -1,188 +1,276 @@
// Copyright (c) 2011, 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.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import com.google.dart.compiler.ast.DartUnit;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
-import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.List;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map.Entry;
+import java.util.Set;
/**
* Represents a library's dependencies artifact.
*/
public class LibraryDeps {
+ private static final String VERSION = "v00001";
/**
- * Each dependency record contains the library in which it was found, along with a hash of its
- * structure. Any change in the hash of the target dependency will force a recompile of the
- * associated compilation unit.
+ * Each dependency record contains the library in which it was found, name of the unit in this
+ * library and last-modified timestamp. Any change in the timestamp of the target dependency will
+ * force a recompile of the associated compilation unit.
*/
public static class Dependency {
private final URI libUri;
- private final String hash;
+ private final String unitName;
+ private final long lastModified;
- public Dependency(URI libUri, String hash) {
+ public Dependency(URI libUri, String unitName, long lastModified) {
this.libUri = libUri;
- this.hash = hash;
+ this.unitName = unitName;
+ this.lastModified = lastModified;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Dependency) {
+ Dependency dep = (Dependency) obj;
+ return Objects.equal(libUri, dep.libUri) && Objects.equal(unitName, dep.unitName);
+ }
+ return false;
}
- public String getHash() {
- return hash;
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(libUri, unitName);
}
public URI getLibUri() {
return libUri;
}
+
+ public String getUnitName() {
+ return unitName;
+ }
+
+ public long getLastModified() {
+ return lastModified;
+ }
}
- /**
- * Each source is a map from class names to its associated {@link Dependency}.
- *
- * A special dependency entry, called a 'hole', represents a name that, if
- * newly-defined in the library scope, will force a recompile of the unit.
- * This is represented by the static constant {@link Source#HOLE}.
- */
public static class Source {
- private final Map<String, Dependency> deps = new ConcurrentHashMap<String, Dependency>();
- private final static Dependency HOLE = new Dependency(null, null);
+ private final Set<Dependency> deps = Sets.newHashSet();
+ private final Set<String> topSymbols = Sets.newHashSet();
+ private final Set<String> allSymbols = Sets.newHashSet();
+ private boolean shouldRecompileOnAnyTopLevelChange = false;
/**
- * Gets the node names of all dependencies for this source.
+ * @return the {@link Set} of {@link Dependency}s.
*/
- public Iterable<String> getNodeNames() {
- return deps.keySet();
+ public Set<Dependency> getDeps() {
+ return deps;
}
- public void putDependency(String nodeName, Dependency dep) {
- deps.put(nodeName, dep);
+ /**
+ * @return the names of top-level elements, such as methods and classes.
+ */
+ public Set<String> getTopSymbols() {
+ return topSymbols;
}
- public Dependency getDependency(String nodeName) {
- return deps.get(nodeName);
+ /**
+ * @return the names of all elements in unit, such as names of local variables, fields, etc.
+ */
+ public Set<String> getAllSymbols() {
+ return allSymbols;
}
- public void putHole(String nodeName) {
- deps.put(nodeName, HOLE);
+ /**
+ * @return <code>true</code> if this unit should be recompiled on any change in the set of
+ * top-level symbols. Typically unit has compilation errors, which potentially may be
+ * fixed, so we should recompile this unit.
+ */
+ public boolean shouldRecompileOnAnyTopLevelChange() {
+ return shouldRecompileOnAnyTopLevelChange;
}
- public boolean isHole(String nodeName) {
- return deps.containsKey(nodeName) && (deps.get(nodeName) == HOLE);
+ /**
+ * Adds symbol to the {@link Set} of top symbols.
+ */
+ public void addTopSymbol(String symbol) {
+ if (!Strings.isNullOrEmpty(symbol)) {
+ topSymbols.add(symbol);
+ }
+ }
+
+ /**
+ * Adds symbol to the {@link Set} of all symbols.
+ */
+ public void addAllSymbol(String symbol) {
+ allSymbols.add(symbol);
}
}
- public static LibraryDeps fromReader(Reader reader) throws IOException {
+ public static LibraryDeps fromReader(Reader reader) {
+ try {
+ return fromReaderEx(reader);
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ private static LibraryDeps fromReaderEx(Reader reader) throws Exception {
LibraryDeps deps = new LibraryDeps();
BufferedReader buf = new BufferedReader(reader);
- String srcName;
- while (null != (srcName = buf.readLine())) {
- Source src = new Source();
-
- String line;
- while (null != (line = buf.readLine())) {
- // Blank line: next source.
+ // Check version.
+ {
+ String line = buf.readLine();
+ if (!Objects.equal(line, VERSION)) {
+ return deps;
+ }
+ }
+ // Read units dependencies.
+ String relPath;
+ while (null != (relPath = buf.readLine())) {
+ Source source = new Source();
+ // Read flags.
+ source.shouldRecompileOnAnyTopLevelChange = Boolean.parseBoolean(buf.readLine());
+ // Read top symbols.
+ {
+ String line = buf.readLine();
+ Iterable<String> topSymbols = Splitter.on(' ').omitEmptyStrings().split(line);
+ Iterables.addAll(source.topSymbols, topSymbols);
+ }
+ // Read all symbols.
+ {
+ String line = buf.readLine();
+ Iterable<String> allSymbols = Splitter.on(' ').omitEmptyStrings().split(line);
+ Iterables.addAll(source.allSymbols, allSymbols);
+ }
+ // Read dependencies.
+ while (true) {
+ String line = buf.readLine();
+ // Blank line: next unit.
if (line.length() == 0) {
break;
}
-
+ // Parse line.
String[] parts = line.split(" ");
- switch (parts.length) {
- case 3:
- // Full dependency.
- try {
- src.deps.put(parts[0], new Dependency(new URI(parts[1]), parts[2]));
- } catch (URISyntaxException e) {
- return null;
- }
- break;
- case 1:
- // Name only: hole.
- src.deps.put(parts[0], Source.HOLE);
- break;
- default:
- return null;
- }
+ source.deps.add(new Dependency(new URI(parts[0]), parts[1], Long.parseLong(parts[2])));
}
-
- deps.sources.put(srcName, src);
+ // Remember dependencies for current unit.
+ deps.sources.put(relPath, source);
}
-
return deps;
}
- private final Map<String, Source> sources = new ConcurrentHashMap<String, Source>();
+ private final Map<String, Source> sources = Maps.newHashMap();
public LibraryDeps() {
}
- public Source getSource(String sourceName) {
- return sources.get(sourceName);
+ /**
+ * @return the relative paths of all units with remembered dependencies.
+ */
+ public Set<String> getUnitPaths() {
+ return sources.keySet();
}
- public Iterable<String> getSourceNames() {
- return sources.keySet();
+ /**
+ * @return all {@link Source} descriptions for all units in this library.
+ */
+ public Iterable<Source> getSources() {
+ return sources.values();
}
- public void setSource(String sourceName, Source source) {
- sources.put(sourceName, source);
+ /**
+ * @return the {@link Source} description of the unit with given path.
+ */
+ public Source getSource(String relPath) {
+ return sources.get(relPath);
}
- @Override
- public String toString() {
- try {
- StringWriter writer = new StringWriter();
- write(writer);
- return writer.toString();
- } catch (IOException e) {
- throw new AssertionError();
- }
+ /**
+ * Remembers {@link Dependency}s of the unit with given path.
+ */
+ public void putSource(String relPath, Source source) {
+ sources.put(relPath, source);
}
- public void update(DartUnit unit, DartCompilerContext context) {
- // Update the library deps to reflect this unit's classes.
- LibraryDepsVisitor.exec(unit, this);
+ /**
+ * Update the library dependencies to reflect this unit's classes.
+ */
+ public void update(DartCompilerMainContext context, DartUnit unit) {
+ Source source = new Source();
+ String relPath = unit.getSource().getRelativePath();
+ putSource(relPath, source);
+ // Remember dependencies.
+ LibraryDepsVisitor.exec(unit, source);
+ // Fill Source with symbols.
+ for (String name : unit.getDeclarationNames()) {
+ source.addAllSymbol(name);
+ }
+ for (String name : unit.getTopDeclarationNames()) {
+ source.addTopSymbol(name);
+ }
+ // Analyze errors and see if any of them should force recompilation.
+ List<DartCompilationError> sourceErrors = context.getSourceErrors(unit.getSource());
+ for (DartCompilationError error : sourceErrors) {
+ if (error.getErrorCode().needsRecompilation()) {
+ source.shouldRecompileOnAnyTopLevelChange = true;
+ break;
+ }
+ }
}
public void write(Writer writer) throws IOException {
- // For stability from run to run, this output needs to be sorted
- ArrayList<String> sortedSourceNames = new ArrayList<String>(sources.size());
- sortedSourceNames.addAll(sources.keySet());
- Collections.sort(sortedSourceNames);
-
- for (String srcName : sortedSourceNames) {
- writer.write(srcName);
+ // Write version.
+ writer.write(VERSION);
+ writer.write('\n');
+ // Write entries.
+ for (Entry<String, Source> entry : sources.entrySet()) {
+ String relPath = entry.getKey();
+ Source source = entry.getValue();
+ // Unit name.
+ writer.write(relPath);
writer.write('\n');
- Source src = sources.get(srcName);
-
- // sort the types per source name
- ArrayList<String> sortedTypes = new ArrayList<String>(src.deps.size());
- sortedTypes.addAll(src.deps.keySet());
- Collections.sort(sortedTypes);
-
- for (String type : sortedTypes) {
- writer.write(type);
-
- Dependency dep = src.getDependency(type);
- if (dep != Source.HOLE) {
- writer.write(' ');
- writer.write(dep.libUri.toString());
- writer.write(' ');
- writer.write(dep.hash);
- }
-
+ // Flags.
+ writer.write(Boolean.toString(source.shouldRecompileOnAnyTopLevelChange));
+ writer.write('\n');
+ // Write top symbols.
+ for (String symbol : source.topSymbols) {
+ writer.write(symbol);
+ writer.write(' ');
+ }
+ writer.write('\n');
+ // Write all symbols.
+ for (String symbol : source.allSymbols) {
+ writer.write(symbol);
+ writer.write(' ');
+ }
+ writer.write('\n');
+ // Write dependencies.
+ for (Dependency dep : source.deps) {
+ writer.write(dep.libUri.toString());
+ writer.write(' ');
+ writer.write(dep.unitName);
+ writer.write(' ');
+ writer.write(Long.toString(dep.lastModified));
writer.write('\n');
}
-
+ // Empty line after each unit.
writer.write('\n');
}
}

Powered by Google App Engine
This is Rietveld 408576698