001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.api.java.source;
042:
043: import com.sun.tools.javac.code.Symtab;
044: import com.sun.tools.javac.util.Context;
045: import com.sun.tools.javac.util.Name;
046: import java.util.ArrayList;
047: import java.util.Collections;
048: import java.util.Iterator;
049: import java.util.List;
050: import javax.lang.model.element.Element;
051: import javax.lang.model.element.Modifier;
052: import javax.lang.model.element.TypeElement;
053: import javax.lang.model.element.TypeParameterElement;
054: import javax.lang.model.type.ArrayType;
055: import javax.lang.model.type.DeclaredType;
056: import javax.lang.model.type.ErrorType;
057: import javax.lang.model.type.TypeKind;
058: import javax.lang.model.type.TypeMirror;
059: import javax.lang.model.type.TypeVariable;
060: import javax.lang.model.type.WildcardType;
061:
062: /**
063: * Represents a handle for {@link TypeMirror} which can be kept and later resolved
064: * by another javac. The Javac {@link TypeMirror}s are valid only in the single
065: * {@link javax.tools.CompilationTask} or single run of the
066: * {@link org.netbeans.api.java.source.CancellableTask}. If the client needs to
067: * keep a reference to the {@link TypeMirror} and use it in the other CancellableTask
068: * he has to serialize it into the {@link TypeMirrorHandle}.
069: * <div class="nonnormative">
070: * <p>
071: ** Typical usage of TypeMirrorHandle is:
072: * </p>
073: * <pre>
074: * final TypeMirrorHandle[] typeMirrorHandle = new TypeMirrorHandle[1];
075: * javaSource.runCompileControlTask(new CancellableTask<CompilationController>() {
076: * public void run(CompilationController compilationController) {
077: * parameter.toPhase(Phase.RESOLVED);
078: * CompilationUnitTree cu = compilationController.getTree ();
079: * TypeMirror type = getInterestingType(cu);
080: * typeMirrorHandle[0] = TypeMirrorHandle.create (type);
081: * }
082: * },priority);
083: *
084: * otherJavaSource.runCompileControlTask(new CancellableTask<CompilationController>() {
085: * public void run(CompilationController compilationController) {
086: * parameter.toPhase(Phase.RESOLVED);
087: * TypeMirror type = typeMirrorHandle[0].resolve (compilationController);
088: * ....
089: * }
090: * },priority);
091: * </pre>
092: * </div>
093: * Currently, not all the {@link TypeMirror} {@link TypeKind kinds} are supported by handle.
094: * The unsupported {@link TykeKind kinds} are: {@link TypeKind#EXECUTABLE}, {@link TypeKind#OTHER},
095: * and {@link TypeKind#PACKAGE}.
096: *
097: * @author Jan Lahoda, Dusan Balek
098: */
099: public final class TypeMirrorHandle<T extends TypeMirror> {
100:
101: private TypeKind kind;
102: private ElementHandle<? extends Element> element;
103: private List<TypeMirrorHandle<? extends TypeMirror>> typeMirrors;
104:
105: private TypeMirrorHandle(TypeKind kind,
106: ElementHandle<? extends Element> element,
107: List<TypeMirrorHandle<? extends TypeMirror>> typeArguments) {
108: this .kind = kind;
109: this .element = element;
110: this .typeMirrors = typeArguments;
111: }
112:
113: /**
114: * Factory method for creating {@link TypeMirrorHandle}.
115: * @param {@link TypeMirror} for which the {@link TypeMirrorHandle} should be created.
116: * Not all the {@link TypeMirror} {@link TypeKind kinds} are currently supported.
117: * The unsupported {@link TykeKind kinds} are: {@link TypeKind#EXECUTABLE}, {@link TypeKind#OTHER},
118: * and {@link TypeKind#PACKAGE}.
119: * @return a new {@link TypeMirrorHandle}
120: * @throws {@link IllegalArgumentException} if the {@link TypeMirror} is of an unsupported
121: * {@link TypeKind}.
122: */
123: public static <T extends TypeMirror> TypeMirrorHandle<T> create(T tm) {
124: TypeKind kind = tm.getKind();
125: ElementHandle<? extends Element> element = null;
126: List<TypeMirrorHandle<? extends TypeMirror>> typeMirrors = null;
127: switch (kind) {
128: case BOOLEAN:
129: case BYTE:
130: case CHAR:
131: case DOUBLE:
132: case FLOAT:
133: case INT:
134: case LONG:
135: case NONE:
136: case NULL:
137: case SHORT:
138: case VOID:
139: break;
140: case DECLARED:
141: DeclaredType dt = (DeclaredType) tm;
142: TypeElement te = (TypeElement) dt.asElement();
143: element = ElementHandle.create(te);
144: Element encl = te.getEnclosingElement();
145: boolean genericOuter = (encl.getKind().isClass() || encl
146: .getKind().isInterface())
147: && !((TypeElement) encl).getTypeParameters()
148: .isEmpty()
149: && !te.getModifiers().contains(Modifier.STATIC);
150: if (te.getTypeParameters().isEmpty() && !genericOuter)
151: break;
152: List<? extends TypeMirror> targs = dt.getTypeArguments();
153: if (!targs.isEmpty()) {
154: TypeMirror targ = targs.get(0);
155: if (targ.getKind() == TypeKind.TYPEVAR) {
156: TypeParameterElement tpe = (TypeParameterElement) ((TypeVariable) targ)
157: .asElement();
158: if (tpe.getGenericElement() == dt.asElement())
159: break;
160: }
161: }
162: if (genericOuter) {
163: typeMirrors = new ArrayList<TypeMirrorHandle<? extends TypeMirror>>(
164: targs.size() + 1);
165: typeMirrors.add(create(dt.getEnclosingType()));
166: } else {
167: typeMirrors = new ArrayList<TypeMirrorHandle<? extends TypeMirror>>(
168: targs.size());
169: }
170: for (TypeMirror ta : targs)
171: typeMirrors.add(create(ta));
172: break;
173: case ARRAY:
174: typeMirrors = Collections
175: .<TypeMirrorHandle<? extends TypeMirror>> singletonList(TypeMirrorHandle
176: .create(((ArrayType) tm).getComponentType()));
177: break;
178: case TYPEVAR:
179: TypeVariable tv = (TypeVariable) tm;
180: element = ElementHandle.create(tv.asElement());
181: typeMirrors = new ArrayList<TypeMirrorHandle<? extends TypeMirror>>();
182: typeMirrors
183: .add(tv.getLowerBound() != null ? TypeMirrorHandle
184: .create(tv.getLowerBound()) : null);
185: typeMirrors
186: .add(tv.getUpperBound() != null ? TypeMirrorHandle
187: .create(tv.getUpperBound()) : null);
188: break;
189: case WILDCARD:
190: WildcardType wt = (WildcardType) tm;
191: typeMirrors = new ArrayList<TypeMirrorHandle<? extends TypeMirror>>();
192: typeMirrors
193: .add(wt.getExtendsBound() != null ? TypeMirrorHandle
194: .create(wt.getExtendsBound())
195: : null);
196: typeMirrors
197: .add(wt.getSuperBound() != null ? TypeMirrorHandle
198: .create(wt.getSuperBound()) : null);
199: break;
200: case ERROR:
201: ErrorType et = (ErrorType) tm;
202: element = ElementHandle.create(et.asElement());
203: break;
204: default:
205: throw new IllegalArgumentException(
206: "Currently unsupported TypeKind: " + tm.getKind());
207: }
208: return new TypeMirrorHandle(kind, element, typeMirrors);
209: }
210:
211: /**
212: * Resolves an {@link TypeMirror} from the {@link TypeMirrorHandle}.
213: * @param {@link CompilationInfo} representing the {@link javax.tools.CompilationTask}
214: * in which the {@link TypeMirror} should be resolved.
215: * @return resolved subclass of {@link TypeMirror} or null if the type cannot be
216: * resolved in this {@link javax.tools.CompilationTask}.
217: */
218: public T resolve(CompilationInfo info) {
219: switch (kind) {
220: case BOOLEAN:
221: case BYTE:
222: case CHAR:
223: case DOUBLE:
224: case FLOAT:
225: case INT:
226: case LONG:
227: case SHORT:
228: return (T) info.getTypes().getPrimitiveType(kind);
229: case NONE:
230: case VOID:
231: return (T) info.getTypes().getNoType(kind);
232: case NULL:
233: return (T) info.getTypes().getNullType();
234: case DECLARED:
235: TypeElement te = (TypeElement) element.resolve(info);
236: if (te == null)
237: return null;
238: if (typeMirrors == null)
239: return (T) te.asType();
240: Iterator<TypeMirrorHandle<? extends TypeMirror>> it = typeMirrors
241: .iterator();
242: Element encl = te.getEnclosingElement();
243: boolean genericOuter = (encl.getKind().isClass() || encl
244: .getKind().isInterface())
245: && !((TypeElement) encl).getTypeParameters()
246: .isEmpty()
247: && !te.getModifiers().contains(Modifier.STATIC);
248: TypeMirror outer = null;
249: if (genericOuter) {
250: outer = it.hasNext() ? it.next().resolve(info) : null;
251: if (outer == null
252: || outer.getKind() != TypeKind.DECLARED)
253: return null;
254: }
255: List<TypeMirror> resolvedTypeArguments = new ArrayList<TypeMirror>();
256: while (it.hasNext()) {
257: TypeMirror resolved = it.next().resolve(info);
258: if (resolved == null)
259: return null;
260: resolvedTypeArguments.add(resolved);
261: }
262: return outer != null ? (T) info
263: .getTypes()
264: .getDeclaredType(
265: (DeclaredType) outer,
266: te,
267: resolvedTypeArguments
268: .toArray(new TypeMirror[resolvedTypeArguments
269: .size()]))
270: : (T) info
271: .getTypes()
272: .getDeclaredType(
273: te,
274: resolvedTypeArguments
275: .toArray(new TypeMirror[resolvedTypeArguments
276: .size()]));
277: case ARRAY:
278: TypeMirror resolved = typeMirrors.get(0).resolve(info);
279: if (resolved == null)
280: return null;
281: return (T) info.getTypes().getArrayType(resolved);
282: case TYPEVAR:
283: Element e = element.resolve(info);
284: if (!(e instanceof com.sun.tools.javac.code.Symbol.TypeSymbol))
285: return null;
286: TypeMirrorHandle<? extends TypeMirror> lBound = typeMirrors
287: .get(0);
288: TypeMirror lowerBound = lBound != null ? lBound
289: .resolve(info) : null;
290: TypeMirrorHandle<? extends TypeMirror> uBound = typeMirrors
291: .get(1);
292: TypeMirror upperBound = uBound != null ? uBound
293: .resolve(info) : null;
294: return (T) new com.sun.tools.javac.code.Type.TypeVar(
295: (com.sun.tools.javac.code.Symbol.TypeSymbol) e,
296: (com.sun.tools.javac.code.Type) lowerBound,
297: (com.sun.tools.javac.code.Type) upperBound);
298: case WILDCARD:
299: TypeMirrorHandle<? extends TypeMirror> eBound = typeMirrors
300: .get(0);
301: TypeMirror extendsBound = eBound != null ? eBound
302: .resolve(info) : null;
303: TypeMirrorHandle<? extends TypeMirror> sBound = typeMirrors
304: .get(1);
305: TypeMirror super Bound = sBound != null ? sBound
306: .resolve(info) : null;
307: return (T) info.getTypes().getWildcardType(extendsBound,
308: super Bound);
309: case ERROR:
310: e = element.resolve(info);
311: if (e == null) {
312: String[] signatures = element.getSignature();
313: assert signatures.length == 1;
314: Context context = info.impl.getJavacTask().getContext();
315: return (T) new com.sun.tools.javac.code.Type.ErrorType(
316: Name.Table.instance(context).fromString(
317: signatures[0]), Symtab
318: .instance(context).rootPackage);
319: }
320: if (!(e instanceof com.sun.tools.javac.code.Symbol.ClassSymbol))
321: return null;
322: return (T) new com.sun.tools.javac.code.Type.ErrorType(
323: (com.sun.tools.javac.code.Symbol.ClassSymbol) e);
324: default:
325: throw new IllegalStateException(
326: "Internal error: unknown TypeHandle kind: " + kind);
327: }
328: }
329:
330: /**
331: * Returns the {@link TypeKind} of this handle,
332: * it is the kind of the {@link TypeMirror} from which the handle
333: * was created.
334: * @return {@link TypeKind}
335: */
336: public TypeKind getKind() {
337: return this .kind;
338: }
339:
340: ElementHandle<? extends Element> getElementHandle() {
341: return element;
342: }
343: }
|