public Void visitThrow(ThrowTree node, Set<TypeMirror> p) { super.visitThrow(node, p); TypeMirror tm = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), node.getExpression())); if (tm != null) { if (tm.getKind() == TypeKind.DECLARED) p.add(tm); else if (tm.getKind() == TypeKind.UNION) p.addAll(((UnionType)tm).getAlternatives()); } return null; }
@Override public Void visitUnion(UnionType t, Collection<DeclaredType> p) { for (TypeMirror tm : t.getAlternatives()) { visit(tm, p); } return DEFAULT_VALUE; }
@Override protected void performRewrite(TransformationContext ctx) { WorkingCopy wc = ctx.getWorkingCopy(); TreePath tp = ctx.getPath(); List<Tree> disjointTypes = new LinkedList<Tree>(); TryTree tt = (TryTree) tp.getLeaf(); int first = duplicates.get(0); List<Integer> remainingDuplicates = duplicates.subList(1, duplicates.size()); addDisjointType(disjointTypes, tt.getCatches().get(first).getParameter().getType()); for (Integer d : remainingDuplicates) { addDisjointType(disjointTypes, tt.getCatches().get((int) d).getParameter().getType()); } List<CatchTree> newCatches = new LinkedList<CatchTree>(); int c = 0; for (CatchTree ct : tt.getCatches()) { if (c == first) { wc.rewrite(ct.getParameter().getType(), wc.getTreeMaker().UnionType(disjointTypes)); } if (remainingDuplicates.contains(c++)) continue; newCatches.add(ct); } TryTree nue = wc.getTreeMaker().Try(tt.getResources(), tt.getBlock(), newCatches, tt.getFinallyBlock()); wc.rewrite(tt, nue); }
private static List<? extends TypeMirror> getCaughtExceptions(TypeMirror caught) { if (caught == null) { return Collections.emptyList(); } switch (caught.getKind()) { case UNION: { boolean cloned = false; List<? extends TypeMirror> types = ((UnionType) caught).getAlternatives(); int i = types.size() - 1; for (; i >= 0; i--) { TypeMirror m = types.get(i); TypeKind mk = m.getKind(); if (mk == null || mk != TypeKind.DECLARED) { if (!cloned) { types = new ArrayList<TypeMirror>(types); } types.remove(i); } } return types; } case DECLARED: return Collections.singletonList(caught); default: return Collections.emptyList(); } }
@Override public Boolean visitUnion(UnionType tm, Void p) { for (TypeMirror t : tm.getAlternatives()) { if (stop) { return false; } if (t.accept(this, p)) { return true; } } return false; }
@Override public boolean matches(ExpressionTree tree, VisitorState state) { Type type = ((JCTree) tree).type; if (type.isUnion()) { for (TypeMirror alternative : ((UnionType) type).getAlternatives()) { if (!isKnownCheckedException(state, (Type) alternative)) { return false; } } return true; } else { return isKnownCheckedException(state, type); } }
@Override public AnnotatedUnionType getCopy(boolean copyAnnotations) { AnnotatedUnionType type = new AnnotatedUnionType((UnionType) actualType, atypeFactory); if (copyAnnotations) type.addAnnotations(annotations); type.alternatives = this.alternatives; return type; }
public List<AnnotatedDeclaredType> getAlternatives() { if (alternatives == null) { List<? extends TypeMirror> ualts = ((UnionType)actualType).getAlternatives(); List<AnnotatedDeclaredType> res = new ArrayList<AnnotatedDeclaredType>(ualts.size()); for (TypeMirror alt : ualts) { res.add((AnnotatedDeclaredType) createType(alt, atypeFactory)); } alternatives = Collections.unmodifiableList(res); } return alternatives; }
@Override public <R, P> R accept(TypeVisitor<R, P> v, P p) { switch (kind) { case BOOLEAN: case BYTE: case SHORT: case INT: case LONG: case CHAR: case FLOAT: case DOUBLE: return v.visitPrimitive((PrimitiveType) this, p); case PACKAGE: case VOID: case NONE: return v.visitNoType((NoType) this, p); case NULL: return v.visitNull((NullType) this, p); case ARRAY: return v.visitArray((ArrayType) this, p); case DECLARED: return v.visitDeclared((DeclaredType) this, p); case ERROR: return v.visitError((ErrorType) this, p); case TYPEVAR: return v.visitTypeVariable((TypeVariable) this, p); case WILDCARD: return v.visitWildcard((WildcardType) this, p); case EXECUTABLE: return v.visitExecutable((ExecutableType) this, p); case OTHER: return v.visit(this, p); case UNION: return v.visitUnion((UnionType) this, p); case INTERSECTION: return v.visitIntersection((IntersectionType) this, p); default: throw new AssertionError(String.format("Unknown TypeKind: %s", kind)); } }
@Override public Type visitUnion(UnionType t, Type.Parameters p) { throw new UnsupportedOperationException("UnionType type not supported"); }
private List<? extends TypeMirror> findUncaughtExceptions(CompilationInfo info, TreePath path, List<? extends TypeMirror> exceptions) { List<TypeMirror> result = new ArrayList<TypeMirror>(); result.addAll(exceptions); Tree lastTree = null; while (path != null) { Tree currentTree = path.getLeaf(); if (currentTree.getKind() == Tree.Kind.METHOD) { TypeMirror tm = info.getTrees().getTypeMirror(path); if (tm != null && tm.getKind() == TypeKind.EXECUTABLE) { for (TypeMirror mirr : ((ExecutableType) tm).getThrownTypes()) { for (Iterator<TypeMirror> it = result.iterator(); it.hasNext();) if (info.getTypes().isSameType(it.next(), mirr)) it.remove(); } break; } } if (currentTree.getKind() == Tree.Kind.LAMBDA_EXPRESSION) { // no checked exceptions can be thrown out of Lambda, #243106 break; } if (currentTree.getKind() == Kind.TRY) { TryTree tt = (TryTree) currentTree; if (tt.getBlock() == lastTree) { for (CatchTree c : tt.getCatches()) { TreePath catchPath = new TreePath(new TreePath(path, c), c.getParameter()); VariableElement variable = (VariableElement) info.getTrees().getElement(catchPath); if (variable == null) { continue; } TypeMirror variableType = variable.asType(); if (variableType.getKind() == TypeKind.UNION) { result.removeAll(((UnionType)variableType).getAlternatives()); } else { result.remove(variableType); } } } } lastTree = path.getLeaf(); path = path.getParentPath(); } List<TypeMirror> filtered = new ArrayList<>(); OUTER: for (Iterator<TypeMirror> sourceIt = result.iterator(); sourceIt.hasNext(); ) { TypeMirror sourceType = sourceIt.next(); for (Iterator<TypeMirror> filteredIt = filtered.iterator(); filteredIt.hasNext(); ) { TypeMirror filteredType = filteredIt.next(); if (info.getTypes().isSubtype(sourceType, filteredType)) { sourceIt.remove(); continue OUTER; } if (info.getTypes().isSubtype(filteredType, sourceType)) { filteredIt.remove(); break; } } filtered.add(sourceType); } return filtered; }
/** * Computes possible types for throw expression. Throw can safely throw an exception, which is * either declared by method as a thrown type, or catched within method, by an upper try-catch block. * Unchecked exceptions are permitted (derivatives of RuntimeException or Error). */ @Override public List<? extends TypeMirror> visitThrow(ThrowTree node, Object p) { List<TypeMirror> result = new ArrayList<TypeMirror>(); TreePath parents = getCurrentPath(); Tree prev = null; while (parents != null && parents.getLeaf().getKind() != Tree.Kind.METHOD) { Tree l = parents.getLeaf(); if (l.getKind() == Tree.Kind.TRY) { TryTree tt = (TryTree) l; if (prev == tt.getBlock()) { for (CatchTree ct : tt.getCatches()) { TypeMirror ex = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), ct.getParameter().getType())); if (ex != null) { switch (ex.getKind()) { case DECLARED: if (!result.contains(ex)) { result.add(ex); } break; case UNION: for (TypeMirror t : ((UnionType) ex).getAlternatives()) { if (!result.contains(t)) { result.add(t); } } break; } } } } } prev = l; parents = parents.getParentPath(); } if (parents != null) { MethodTree mt = (MethodTree) parents.getLeaf(); for (ExpressionTree etree : mt.getThrows()) { TypeMirror m = info.getTrees().getTypeMirror(new TreePath(parents, etree)); if (m != null && !result.contains(m)) { result.add(m); } } } TypeMirror jlre = info.getElements().getTypeElement("java.lang.RuntimeException").asType(); // NOI18N TypeMirror jler = info.getElements().getTypeElement("java.lang.Error").asType(); // NOI18N for (TypeMirror em : result) { if (jlre != null && info.getTypes().isAssignable(jlre, em)) { jlre = null; } if (jler != null && info.getTypes().isAssignable(jler, em)) { jler = null; } if (jlre == null && jler == null) { break; } } if (jlre != null) { result.add(jlre); } if (jler != null) { result.add(jler); } return result; }
@Override public Boolean visitUnion(UnionType arg0, Boolean arg1) { return false; }
@Override public String visitUnion(UnionType t, Void p) { return null; }
@Override public final R visitUnion(UnionType type, TypeMirror otherType) { return otherType instanceof UnionType ? visitUnion(type, (UnionType) otherType) : unmatchedAction(type, otherType); }
protected R visitUnion(UnionType type, UnionType otherType) { return defaultMatchAction(type, otherType); }
/** * Creates the appropriate AnnotatedTypeMirror specific wrapper for the * provided type * * @param type * @param atypeFactory * @return [to document] */ public static AnnotatedTypeMirror createType(TypeMirror type, AnnotatedTypeFactory atypeFactory) { if (type == null) { ErrorReporter.errorAbort("AnnotatedTypeMirror.createType: input type must not be null!"); return null; } com.sun.tools.javac.code.Type jctype = ((com.sun.tools.javac.code.Type)type); type = jctype.unannotatedType(); AnnotatedTypeMirror result; switch (type.getKind()) { case ARRAY: result = new AnnotatedArrayType((ArrayType) type, atypeFactory); break; case DECLARED: result = new AnnotatedDeclaredType((DeclaredType) type, atypeFactory); break; case ERROR: ErrorReporter.errorAbort("AnnotatedTypeMirror.createType: input should type-check already! Found error type: " + type); return null; // dead code case EXECUTABLE: result = new AnnotatedExecutableType((ExecutableType) type, atypeFactory); break; case VOID: case PACKAGE: case NONE: result = new AnnotatedNoType((NoType) type, atypeFactory); break; case NULL: result = new AnnotatedNullType((NullType) type, atypeFactory); break; case TYPEVAR: result = new AnnotatedTypeVariable((TypeVariable) type, atypeFactory); break; case WILDCARD: result = new AnnotatedWildcardType((WildcardType) type, atypeFactory); break; case INTERSECTION: result = new AnnotatedIntersectionType((IntersectionType) type, atypeFactory); break; case UNION: result = new AnnotatedUnionType((UnionType) type, atypeFactory); break; default: if (type.getKind().isPrimitive()) { result = new AnnotatedPrimitiveType((PrimitiveType) type, atypeFactory); break; } ErrorReporter.errorAbort("AnnotatedTypeMirror.createType: unidentified type " + type + " (" + type.getKind() + ")"); return null; // dead code } /*if (jctype.isAnnotated()) { result.addAnnotations(jctype.getAnnotationMirrors()); }*/ return result; }
@Override @Nullable public R visitUnion(UnionType t, P p) { throw new UnsupportedOperationException("NYI"); }
@Override public Void visitUnion(UnionType t, Void aVoid) { scans.add(t.toString()); return super.visitUnion(t, aVoid); }
/** * Constructor for this type * * @param type underlying kind of this type * @param atypeFactory TODO */ private AnnotatedUnionType(UnionType type, AnnotatedTypeFactory atypeFactory) { super(type, atypeFactory); }