KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > jdt > StandardSourceOracle


1 /*
2  * Copyright 2006 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.jdt;
17
18 import com.google.gwt.core.ext.TreeLogger;
19 import com.google.gwt.core.ext.UnableToCompleteException;
20 import com.google.gwt.core.ext.typeinfo.CompilationUnitProvider;
21 import com.google.gwt.core.ext.typeinfo.JClassType;
22 import com.google.gwt.core.ext.typeinfo.TypeOracle;
23 import com.google.gwt.dev.util.Util;
24
25 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
26
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31
32 /**
33  * Provides a mutable compilation service host on top of a
34  * {@link com.google.gwt.dev.typeinfo.TypeOracle} as well as providing
35  * subclasses an opportunity to substitute their own source to implement
36  * special-handling, such as rewriting JSNI source.
37  */

38 public class StandardSourceOracle implements SourceOracle {
39
40   private final Map JavaDoc cupsByTypeName = new HashMap JavaDoc();
41
42   private final Set JavaDoc knownPackages = new HashSet JavaDoc();
43
44   private final TypeOracle typeOracle;
45
46   /**
47    * @param typeOracle answers questions about compilation unit locations
48    * @param genDir for compilation units whose location does not correspond to a
49    * URL that can be opened, their source will be written to this
50    * directory to support debugging, or <code>null</code> if the
51    * source need not be written to disk
52    */

53   public StandardSourceOracle(TypeOracle typeOracle) {
54     this.typeOracle = typeOracle;
55   }
56
57   /**
58    * Attempts to find the compilation unit for the requested type. Often
59    * legitimately returns <code>null</code> because the compilation service
60    * does tests to help determine whether a particular symbol refers to a
61    * package or a type.
62    */

63   public final CompilationUnitProvider findCompilationUnit(TreeLogger logger,
64       String JavaDoc typeName) throws UnableToCompleteException {
65
66     // Check the cache first.
67
//
68
CompilationUnitProvider cup = (CompilationUnitProvider) cupsByTypeName.get(typeName);
69
70     if (cup != null) {
71       // Found in cache.
72
//
73
return cup;
74     }
75
76     // See if the type oracle can find it.
77
//
78
JClassType type = typeOracle.findType(typeName);
79     if (type != null) {
80       // All type oracle types are supposed to know their compilation unit.
81
//
82
cup = type.getCompilationUnit();
83       assert (cup != null);
84     }
85
86     // Give the subclass a chance to replace the source. This used for JSNI in
87
// hosted mode at present but could be used for any source rewriting trick.
88
//
89
if (cup != null) {
90       try {
91         CompilationUnitProvider specialCup = doFilterCompilationUnit(logger,
92             typeName, cup);
93
94         if (specialCup != null) {
95           // Use the cup that the subclass returned instead. Note that even
96
// though this file may not exist on disk, it is special so we don't
97
// want users to have to debug into it unless they specifically ask
98
// to.
99
//
100
cup = specialCup;
101         }
102       } catch (UnableToCompleteException e) {
103         String JavaDoc location = cup.getLocation();
104         char[] source = cup.getSource();
105         Util.maybeDumpSource(logger, location, source, typeName);
106         throw e;
107       }
108     }
109
110     if (cup == null) {
111       // Did not find a cup for the type.
112
// This happens commonly and is not a cause for alarm.
113
//
114
return null;
115     }
116
117     // Remember its package and cache it.
118
//
119
cupsByTypeName.put(typeName, cup);
120     return cup;
121   }
122
123   public TypeOracle getTypeOracle() {
124     return typeOracle;
125   }
126
127   /**
128    * Determines whether or not a particular name is a package name.
129    */

130   public final boolean isPackage(String JavaDoc possiblePackageName) {
131     if (knownPackages.contains(possiblePackageName)) {
132       // The quick route -- we've already answered yes to this question.
133
// OPTIMIZE: cache NOs as well
134
return true;
135     }
136
137     if (typeOracle.findPackage(possiblePackageName) != null) {
138       // Was a package know on the source path.
139
//
140
rememberPackage(possiblePackageName);
141       return true;
142     } else {
143       // Not a package.
144
//
145
return false;
146     }
147   }
148
149   /**
150    * Subclasses can override this method if they use a special mechanism to find
151    * the compilation unit for a type. For example, rewriting source code (as
152    * with JSNI) or preempting the source for a given type (as with
153    * <code>GWT.create</code>).
154    * <p>
155    * Note that subclasses should <em>not</em> call
156    * <code>super.{@link #findCompilationUnit(TreeLogger, String)}</code> in
157    * their implementation.
158    *
159    * @return <code>null</code> if you want the superclass to use its normal
160    * mechanism for finding types
161    */

162   protected CompilationUnitProvider doFilterCompilationUnit(TreeLogger logger,
163       String JavaDoc typeName, CompilationUnitProvider existing)
164       throws UnableToCompleteException {
165     return null;
166   }
167
168   /**
169    * Subclasses can override this method if they use additional mechanisms to
170    * find types magically.
171    * <p>
172    * Note that subclasses should <em>not</em> call
173    * <code>super.{@link #findAdditionalTypesUsingMagic(TreeLogger, CompilationUnitDeclaration)}</code>
174    * in their implementation.
175    *
176    * @return <code>null</code> to indicate that no additional types should be
177    * added
178    */

179   protected String JavaDoc[] doFindAdditionalTypesUsingMagic(TreeLogger logger,
180       CompilationUnitDeclaration unit) throws UnableToCompleteException {
181     return null;
182   }
183
184   void invalidateCups(Set JavaDoc typeNames) {
185     cupsByTypeName.keySet().removeAll(typeNames);
186   }
187
188   /**
189    * Remember that this package was added. Used for generated packages.
190    */

191   private void rememberPackage(String JavaDoc packageName) {
192     int i = packageName.lastIndexOf('.');
193     if (i != -1) {
194       // Ensure the parent package is also created.
195
//
196
rememberPackage(packageName.substring(0, i));
197     }
198     knownPackages.add(packageName);
199   }
200 }
201
Popular Tags