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

Side by Side 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: Restore "holes". Tests for them. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4
5 package com.google.dart.compiler; 4 package com.google.dart.compiler;
6 5
6 import com.google.common.base.Objects;
7 import com.google.common.base.Splitter;
8 import com.google.common.base.Strings;
9 import com.google.common.collect.Iterables;
10 import com.google.common.collect.Maps;
11 import com.google.common.collect.Sets;
7 import com.google.dart.compiler.ast.DartUnit; 12 import com.google.dart.compiler.ast.DartUnit;
8 13
9 import java.io.BufferedReader; 14 import java.io.BufferedReader;
10 import java.io.IOException; 15 import java.io.IOException;
11 import java.io.Reader; 16 import java.io.Reader;
12 import java.io.StringWriter;
13 import java.io.Writer; 17 import java.io.Writer;
14 import java.net.URI; 18 import java.net.URI;
15 import java.net.URISyntaxException; 19 import java.util.List;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Map; 20 import java.util.Map;
19 import java.util.concurrent.ConcurrentHashMap; 21 import java.util.Map.Entry;
22 import java.util.Set;
20 23
21 /** 24 /**
22 * Represents a library's dependencies artifact. 25 * Represents a library's dependencies artifact.
23 */ 26 */
24 public class LibraryDeps { 27 public class LibraryDeps {
25 28 private static final String VERSION = "v00001";
26 /** 29
27 * Each dependency record contains the library in which it was found, along wi th a hash of its 30 /**
28 * structure. Any change in the hash of the target dependency will force a rec ompile of the 31 * Each dependency record contains the library in which it was found, name of the unit in this
29 * associated compilation unit. 32 * library and last-modified timestamp. Any change in the timestamp of the tar get dependency will
33 * force a recompile of the associated compilation unit.
30 */ 34 */
31 public static class Dependency { 35 public static class Dependency {
32 private final URI libUri; 36 private final URI libUri;
33 private final String hash; 37 private final String unitName;
34 38 private final long lastModified;
35 public Dependency(URI libUri, String hash) { 39
40 public Dependency(URI libUri, String unitName, long lastModified) {
36 this.libUri = libUri; 41 this.libUri = libUri;
37 this.hash = hash; 42 this.unitName = unitName;
38 } 43 this.lastModified = lastModified;
39 44 }
40 public String getHash() { 45
41 return hash; 46 @Override
47 public boolean equals(Object obj) {
48 if (obj instanceof Dependency) {
49 Dependency dep = (Dependency) obj;
50 return Objects.equal(libUri, dep.libUri) && Objects.equal(unitName, dep. unitName);
51 }
52 return false;
53 }
54
55 @Override
56 public int hashCode() {
57 return Objects.hashCode(libUri, unitName);
42 } 58 }
43 59
44 public URI getLibUri() { 60 public URI getLibUri() {
45 return libUri; 61 return libUri;
46 } 62 }
47 } 63
48 64 public String getUnitName() {
49 /** 65 return unitName;
50 * Each source is a map from class names to its associated {@link Dependency}. 66 }
51 * 67
52 * A special dependency entry, called a 'hole', represents a name that, if 68 public long getLastModified() {
53 * newly-defined in the library scope, will force a recompile of the unit. 69 return lastModified;
54 * This is represented by the static constant {@link Source#HOLE}. 70 }
55 */ 71 }
72
56 public static class Source { 73 public static class Source {
57 private final Map<String, Dependency> deps = new ConcurrentHashMap<String, D ependency>(); 74 private final Set<Dependency> deps = Sets.newHashSet();
58 private final static Dependency HOLE = new Dependency(null, null); 75 private final Set<String> topSymbols = Sets.newHashSet();
59 76 private final Set<String> allSymbols = Sets.newHashSet();
60 /** 77 private final Set<String> holes = Sets.newHashSet();
61 * Gets the node names of all dependencies for this source. 78 private boolean shouldRecompileOnAnyTopLevelChange = false;
62 */ 79
63 public Iterable<String> getNodeNames() { 80 /**
64 return deps.keySet(); 81 * @return the {@link Set} of {@link Dependency}s.
65 } 82 */
66 83 public Set<Dependency> getDeps() {
67 public void putDependency(String nodeName, Dependency dep) { 84 return deps;
68 deps.put(nodeName, dep); 85 }
69 } 86
70 87 /**
71 public Dependency getDependency(String nodeName) { 88 * @return the names of top-level elements, such as methods and classes.
72 return deps.get(nodeName); 89 */
73 } 90 public Set<String> getTopSymbols() {
74 91 return topSymbols;
75 public void putHole(String nodeName) { 92 }
76 deps.put(nodeName, HOLE); 93
77 } 94 /**
78 95 * @return the names of all elements in unit, such as names of local variabl es, fields, etc.
79 public boolean isHole(String nodeName) { 96 */
80 return deps.containsKey(nodeName) && (deps.get(nodeName) == HOLE); 97 public Set<String> getAllSymbols() {
81 } 98 return allSymbols;
82 } 99 }
83 100
84 public static LibraryDeps fromReader(Reader reader) throws IOException { 101 /**
102 * @return the names of functions, which are invoked without qualifier. So, declaration or
103 * removing function with such name on top-level should cause recomp iling.
104 */
105 public Set<String> getHoles() {
106 return holes;
107 }
108
109 /**
110 * @return <code>true</code> if this unit should be recompiled on any change in the set of
111 * top-level symbols. Typically unit has compilation errors, which p otentially may be
112 * fixed, so we should recompile this unit.
113 */
114 public boolean shouldRecompileOnAnyTopLevelChange() {
115 return shouldRecompileOnAnyTopLevelChange;
116 }
117
118 /**
119 * Adds new {@link Dependency}.
120 */
121 public void addDep(Dependency dep) {
122 deps.add(dep);
123 }
124
125 /**
126 * Adds symbol to the {@link Set} of top symbols.
127 */
128 public void addTopSymbol(String symbol) {
129 if (!Strings.isNullOrEmpty(symbol)) {
130 topSymbols.add(symbol);
131 }
132 }
133
134 /**
135 * Adds symbol to the {@link Set} of all symbols.
136 */
137 public void addAllSymbol(String symbol) {
138 allSymbols.add(symbol);
139 }
140
141 /**
142 * Adds new hole for {@link #getHoles()}.
143 */
144 public void addHole(String hole) {
145 holes.add(hole);
146 }
147 }
148
149 public static LibraryDeps fromReader(Reader reader) {
150 try {
151 return fromReaderEx(reader);
152 } catch (Throwable e) {
153 return null;
154 }
155 }
156
157 private static LibraryDeps fromReaderEx(Reader reader) throws Exception {
85 LibraryDeps deps = new LibraryDeps(); 158 LibraryDeps deps = new LibraryDeps();
86 BufferedReader buf = new BufferedReader(reader); 159 BufferedReader buf = new BufferedReader(reader);
87 String srcName; 160 // Check version.
88 while (null != (srcName = buf.readLine())) { 161 {
89 Source src = new Source(); 162 String line = buf.readLine();
90 163 if (!Objects.equal(line, VERSION)) {
91 String line; 164 return deps;
92 while (null != (line = buf.readLine())) { 165 }
93 // Blank line: next source. 166 }
167 // Read units dependencies.
168 String relPath;
169 while (null != (relPath = buf.readLine())) {
170 Source source = new Source();
171 // Read flags.
172 source.shouldRecompileOnAnyTopLevelChange = Boolean.parseBoolean(buf.readL ine());
173 // Read top symbols.
174 {
175 String line = buf.readLine();
176 Iterable<String> topSymbols = Splitter.on(' ').omitEmptyStrings().split( line);
177 Iterables.addAll(source.topSymbols, topSymbols);
178 }
179 // Read all symbols.
180 {
181 String line = buf.readLine();
182 Iterable<String> allSymbols = Splitter.on(' ').omitEmptyStrings().split( line);
183 Iterables.addAll(source.allSymbols, allSymbols);
184 }
185 // Read holes.
186 {
187 String line = buf.readLine();
188 Iterable<String> holes = Splitter.on(' ').omitEmptyStrings().split(line) ;
189 Iterables.addAll(source.holes, holes);
190 }
191 // Read dependencies.
192 while (true) {
193 String line = buf.readLine();
194 // Blank line: next unit.
94 if (line.length() == 0) { 195 if (line.length() == 0) {
95 break; 196 break;
96 } 197 }
97 198 // Parse line.
98 String[] parts = line.split(" "); 199 String[] parts = line.split(" ");
99 switch (parts.length) { 200 source.deps.add(new Dependency(new URI(parts[0]), parts[1], Long.parseLo ng(parts[2])));
100 case 3: 201 }
101 // Full dependency. 202 // Remember dependencies for current unit.
102 try { 203 deps.sources.put(relPath, source);
103 src.deps.put(parts[0], new Dependency(new URI(parts[1]), parts[2]) ); 204 }
104 } catch (URISyntaxException e) {
105 return null;
106 }
107 break;
108 case 1:
109 // Name only: hole.
110 src.deps.put(parts[0], Source.HOLE);
111 break;
112 default:
113 return null;
114 }
115 }
116
117 deps.sources.put(srcName, src);
118 }
119
120 return deps; 205 return deps;
121 } 206 }
122 207
123 private final Map<String, Source> sources = new ConcurrentHashMap<String, Sour ce>(); 208 private final Map<String, Source> sources = Maps.newHashMap();
124 209
125 public LibraryDeps() { 210 public LibraryDeps() {
126 } 211 }
127 212
128 public Source getSource(String sourceName) { 213 /**
129 return sources.get(sourceName); 214 * @return the relative paths of all units with remembered dependencies.
130 } 215 */
131 216 public Set<String> getUnitPaths() {
132 public Iterable<String> getSourceNames() {
133 return sources.keySet(); 217 return sources.keySet();
134 } 218 }
135 219
136 public void setSource(String sourceName, Source source) { 220 /**
137 sources.put(sourceName, source); 221 * @return all {@link Source} descriptions for all units in this library.
138 } 222 */
139 223 public Iterable<Source> getSources() {
140 @Override 224 return sources.values();
141 public String toString() { 225 }
142 try { 226
143 StringWriter writer = new StringWriter(); 227 /**
144 write(writer); 228 * @return the {@link Source} description of the unit with given path.
145 return writer.toString(); 229 */
146 } catch (IOException e) { 230 public Source getSource(String relPath) {
147 throw new AssertionError(); 231 return sources.get(relPath);
148 } 232 }
149 } 233
150 234 /**
151 public void update(DartUnit unit, DartCompilerContext context) { 235 * Remembers {@link Dependency}s of the unit with given path.
152 // Update the library deps to reflect this unit's classes. 236 */
153 LibraryDepsVisitor.exec(unit, this); 237 public void putSource(String relPath, Source source) {
238 sources.put(relPath, source);
239 }
240
241 /**
242 * Update the library dependencies to reflect this unit's classes.
243 */
244 public void update(DartCompilerMainContext context, DartUnit unit) {
245 Source source = new Source();
246 String relPath = unit.getSource().getRelativePath();
247 putSource(relPath, source);
248 // Remember dependencies.
249 LibraryDepsVisitor.exec(unit, source);
250 // Fill Source with symbols.
251 for (String name : unit.getDeclarationNames()) {
252 source.addAllSymbol(name);
253 }
254 for (String name : unit.getTopDeclarationNames()) {
255 source.addTopSymbol(name);
256 }
257 // Analyze errors and see if any of them should force recompilation.
258 List<DartCompilationError> sourceErrors = context.getSourceErrors(unit.getSo urce());
259 for (DartCompilationError error : sourceErrors) {
260 if (error.getErrorCode().needsRecompilation()) {
261 source.shouldRecompileOnAnyTopLevelChange = true;
262 break;
263 }
264 }
154 } 265 }
155 266
156 public void write(Writer writer) throws IOException { 267 public void write(Writer writer) throws IOException {
157 // For stability from run to run, this output needs to be sorted 268 // Write version.
158 ArrayList<String> sortedSourceNames = new ArrayList<String>(sources.size()); 269 writer.write(VERSION);
159 sortedSourceNames.addAll(sources.keySet()); 270 writer.write('\n');
160 Collections.sort(sortedSourceNames); 271 // Write entries.
161 272 for (Entry<String, Source> entry : sources.entrySet()) {
162 for (String srcName : sortedSourceNames) { 273 String relPath = entry.getKey();
163 writer.write(srcName); 274 Source source = entry.getValue();
164 writer.write('\n'); 275 // Unit name.
165 Source src = sources.get(srcName); 276 writer.write(relPath);
166 277 writer.write('\n');
167 // sort the types per source name 278 // Flags.
168 ArrayList<String> sortedTypes = new ArrayList<String>(src.deps.size()); 279 writer.write(Boolean.toString(source.shouldRecompileOnAnyTopLevelChange));
169 sortedTypes.addAll(src.deps.keySet()); 280 writer.write('\n');
170 Collections.sort(sortedTypes); 281 // Write top symbols.
171 282 for (String symbol : source.topSymbols) {
172 for (String type : sortedTypes) { 283 writer.write(symbol);
173 writer.write(type); 284 writer.write(' ');
174 285 }
175 Dependency dep = src.getDependency(type); 286 writer.write('\n');
176 if (dep != Source.HOLE) { 287 // Write all symbols.
177 writer.write(' '); 288 for (String symbol : source.allSymbols) {
178 writer.write(dep.libUri.toString()); 289 writer.write(symbol);
179 writer.write(' '); 290 writer.write(' ');
180 writer.write(dep.hash); 291 }
181 } 292 writer.write('\n');
182 293 // Write holes.
294 for (String hole : source.holes) {
295 writer.write(hole);
296 writer.write(' ');
297 }
298 writer.write('\n');
299 // Write dependencies.
300 for (Dependency dep : source.deps) {
301 writer.write(dep.libUri.toString());
302 writer.write(' ');
303 writer.write(dep.unitName);
304 writer.write(' ');
305 writer.write(Long.toString(dep.lastModified));
183 writer.write('\n'); 306 writer.write('\n');
184 } 307 }
185 308 // Empty line after each unit.
186 writer.write('\n'); 309 writer.write('\n');
187 } 310 }
188 } 311 }
189 } 312 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698