001: /*
002: * Copyright 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.jdt;
017:
018: import com.google.gwt.core.ext.TreeLogger;
019: import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider;
020:
021: import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
022: import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
023:
024: import java.io.File;
025: import java.util.ArrayList;
026: import java.util.Arrays;
027: import java.util.Collection;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Map;
033: import java.util.Set;
034:
035: /**
036: * A facade around the JDT compiler to make many repeated compiles as fast as
037: * possible, where the result of each compile is a fully-resolved abstract
038: * syntax tree that can be walked for detailed analysis.
039: */
040: public class AstCompiler extends AbstractCompiler {
041:
042: /**
043: * Manages the caching of <code>CompilationUnitDeclaration</code>.
044: */
045: private class CompilationUnitDeclarationCache {
046:
047: private final Map<String, Long> lastModified = new HashMap<String, Long>();
048:
049: private final Map<String, ArrayList<CompilationUnitDeclaration>> map = new HashMap<String, ArrayList<CompilationUnitDeclaration>>();
050:
051: public void remove(String newLoc) {
052: map.remove(newLoc);
053: }
054:
055: private void add(String location,
056: CompilationUnitDeclaration item) {
057: File file = new File(location);
058: if (file.exists()) {
059: lastModified.put(location,
060: new Long(file.lastModified()));
061: }
062: if (!map.containsKey(location)) {
063: map.put(location,
064: new ArrayList<CompilationUnitDeclaration>());
065: }
066: get(location).add(item);
067: }
068:
069: private boolean containsKey(String location) {
070: return map.containsKey(location);
071: }
072:
073: private List<CompilationUnitDeclaration> get(Object key) {
074: return map.get(key);
075: }
076:
077: private CompilationUnitDeclaration[] getDeclarations() {
078: Set<CompilationUnitDeclaration> outSet = new HashSet<CompilationUnitDeclaration>();
079: for (Iterator<ArrayList<CompilationUnitDeclaration>> iter = map
080: .values().iterator(); iter.hasNext();) {
081: List<CompilationUnitDeclaration> element = iter.next();
082: outSet.addAll(element);
083: }
084: CompilationUnitDeclaration[] out = new CompilationUnitDeclaration[outSet
085: .size()];
086: int i = 0;
087: for (Iterator<CompilationUnitDeclaration> iter = outSet
088: .iterator(); iter.hasNext();) {
089: CompilationUnitDeclaration element = iter.next();
090: out[i] = element;
091: i++;
092: }
093: return out;
094: }
095:
096: private void removeAll(Collection<String> c) {
097: map.keySet().removeAll(c);
098: }
099: }
100:
101: private final CompilationUnitDeclarationCache cachedResults = new CompilationUnitDeclarationCache();
102:
103: public AstCompiler(SourceOracle sourceOracle) {
104: super (sourceOracle, false);
105: }
106:
107: public CompilationUnitDeclaration[] getCompilationUnitDeclarations(
108: TreeLogger logger, ICompilationUnit[] units) {
109: List<ICompilationUnit> allUnits = Arrays.asList(units);
110: List<ICompilationUnitAdapter> newUnits = new ArrayList<ICompilationUnitAdapter>();
111:
112: // Check for newer units that need to be processed.
113: for (Iterator<ICompilationUnit> iter = allUnits.iterator(); iter
114: .hasNext();) {
115: ICompilationUnitAdapter adapter = (ICompilationUnitAdapter) iter
116: .next();
117: CompilationUnitProvider cup = adapter
118: .getCompilationUnitProvider();
119: String location = cup.getLocation();
120: if (!(cachedResults.containsKey(location))) {
121: newUnits.add(adapter);
122: }
123: }
124: ICompilationUnit[] toBeProcessed = new ICompilationUnit[newUnits
125: .size()];
126: newUnits.toArray(toBeProcessed);
127: CompilationUnitDeclaration[] newCuds = compile(logger,
128: toBeProcessed);
129:
130: // Put new cuds into cache.
131: for (int i = 0; i < newCuds.length; i++) {
132: String newLoc = String.valueOf(newCuds[i].getFileName());
133: cachedResults.remove(newLoc);
134: cachedResults.add(newLoc, newCuds[i]);
135: }
136: return cachedResults.getDeclarations();
137: }
138:
139: public void invalidateChangedFiles(Set<String> changedFiles,
140: Set<String> typeNames) {
141: cachedResults.removeAll(changedFiles);
142: invalidateUnitsInFiles(changedFiles, typeNames);
143: }
144: }
|