private static List<? extends TypeMirror> computeEnhancedForLoop( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { EnhancedForLoopTree efl = (EnhancedForLoopTree) parent.getLeaf(); if (efl.getExpression() != error) { return null; } TypeMirror argument = info.getTrees() .getTypeMirror( new TreePath(new TreePath(parent, efl.getVariable()), efl.getVariable().getType())); if (argument == null) return null; if (argument.getKind().isPrimitive()) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getArrayType(argument)); } TypeElement iterable = info.getElements().getTypeElement("java.lang.Iterable"); // NOI18N if (iterable == null) { return null; } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getDeclaredType(iterable, argument)); }
private static List<? extends TypeMirror> computeUnary( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { UnaryTree tree = (UnaryTree) parent.getLeaf(); if (tree.getExpression() == error) { List<? extends TypeMirror> parentTypes = resolveType(types, info, parent.getParentPath(), tree, offset, null, null); if (parentTypes != null) { // may contain only "void", ignore: if (parentTypes.size() != 1) { return parentTypes; } if (parentTypes.get(0).getKind() != TypeKind.VOID) { return parentTypes; } } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT)); } return null; }
private static List<? extends TypeMirror> computeArrayAccess( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { ArrayAccessTree aat = (ArrayAccessTree) parent.getLeaf(); if (aat.getExpression() == error) { TreePath parentParent = parent.getParentPath(); List<? extends TypeMirror> upperTypes = resolveType(types, info, parentParent, aat, offset, null, null); if (upperTypes == null) { return null; } List<TypeMirror> arrayTypes = new ArrayList<TypeMirror>(); for (TypeMirror tm : upperTypes) { if (tm == null) continue; switch (tm.getKind()) { case VOID: case EXECUTABLE: case WILDCARD: case PACKAGE: continue; } arrayTypes.add(info.getTypes().getArrayType(tm)); } if (arrayTypes.isEmpty()) return null; return arrayTypes; } if (aat.getIndex() == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT)); } return null; }
private static List<? extends TypeMirror> computePrimitiveType( Set<ElementKind> types, CompilationInfo info, Tree expression, Tree error, TypeKind kind) { if (expression == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(kind)); } return null; }
private static List<? extends TypeMirror> computeAssert( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { AssertTree at = (AssertTree) parent.getLeaf(); types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); if (at.getCondition() == error) { return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.BOOLEAN)); } if (at.getDetail() == error) { return Collections.singletonList( info.getElements().getTypeElement("java.lang.Object").asType()); } return null; }
private static List<? extends TypeMirror> computeConditionalExpression( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { ConditionalExpressionTree cet = (ConditionalExpressionTree) parent.getLeaf(); if (cet.getCondition() == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.BOOLEAN)); } if (cet.getTrueExpression() == error || cet.getFalseExpression() == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return resolveType(types, info, parent.getParentPath(), cet, offset, null, null); } return null; }
private static List<? extends TypeMirror> computeNewArray( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { NewArrayTree nat = (NewArrayTree) parent.getLeaf(); if (nat.getType() == error) { types.add(ElementKind.CLASS); types.add(ElementKind.ENUM); types.add(ElementKind.INTERFACE); return null; } for (Tree dimension : nat.getDimensions()) { if (dimension == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getTypes().getPrimitiveType(TypeKind.INT)); } } for (Tree init : nat.getInitializers()) { if (init == error) { TypeMirror whole = info.getTrees().getTypeMirror(parent); if (whole == null || whole.getKind() != TypeKind.ARRAY) return null; types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(((ArrayType) whole).getComponentType()); } } return null; }
public static List<? extends TypeMirror> resolveType( Set<ElementKind> types, CompilationInfo info, TreePath currentPath, Tree unresolved, int offset, TypeMirror[] typeParameterBound, int[] numTypeParameters) { switch (currentPath.getLeaf().getKind()) { case METHOD: return computeMethod(types, info, currentPath, typeParameterBound, unresolved, offset); case MEMBER_SELECT: return computeMemberSelect(types, info, currentPath, unresolved, offset); case ASSIGNMENT: return computeAssignment(types, info, currentPath, unresolved, offset); case ENHANCED_FOR_LOOP: return computeEnhancedForLoop(types, info, currentPath, unresolved, offset); case ARRAY_ACCESS: return computeArrayAccess(types, info, currentPath, unresolved, offset); case VARIABLE: return computeVariableDeclaration(types, info, currentPath, unresolved, offset); case ASSERT: return computeAssert(types, info, currentPath, unresolved, offset); case PARENTHESIZED: return computeParenthesis(types, info, currentPath, unresolved, offset); case DO_WHILE_LOOP: return computePrimitiveType( types, info, ((DoWhileLoopTree) currentPath.getLeaf()).getCondition(), unresolved, TypeKind.BOOLEAN); case FOR_LOOP: return computePrimitiveType( types, info, ((ForLoopTree) currentPath.getLeaf()).getCondition(), unresolved, TypeKind.BOOLEAN); case IF: return computePrimitiveType( types, info, ((IfTree) currentPath.getLeaf()).getCondition(), unresolved, TypeKind.BOOLEAN); case WHILE_LOOP: return computePrimitiveType( types, info, ((WhileLoopTree) currentPath.getLeaf()).getCondition(), unresolved, TypeKind.BOOLEAN); case SYNCHRONIZED: return computeReferenceType( types, info, ((SynchronizedTree) currentPath.getLeaf()).getExpression(), unresolved, "java.lang.Object"); case THROW: return computeReferenceType( types, info, ((ThrowTree) currentPath.getLeaf()).getExpression(), unresolved, "java.lang.Exception"); case INSTANCE_OF: return computeReferenceType( types, info, ((InstanceOfTree) currentPath.getLeaf()).getExpression(), unresolved, "java.lang.Object"); case SWITCH: // TODO: should consider also values in the cases?: return computePrimitiveType( types, info, ((SwitchTree) currentPath.getLeaf()).getExpression(), unresolved, TypeKind.INT); case EXPRESSION_STATEMENT: return Collections.singletonList(info.getTypes().getNoType(TypeKind.VOID)); case RETURN: return computeReturn(types, info, currentPath, unresolved, offset); case TYPE_PARAMETER: return computeTypeParameter(types, info, currentPath, unresolved, offset); case PARAMETERIZED_TYPE: return computeParametrizedType( types, info, currentPath, unresolved, offset, typeParameterBound, numTypeParameters); case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE: return computeClass(types, info, currentPath, unresolved, offset); case CONDITIONAL_EXPRESSION: return computeConditionalExpression(types, info, currentPath, unresolved, offset); case NEW_ARRAY: return computeNewArray(types, info, currentPath, unresolved, offset); case METHOD_INVOCATION: return computeMethodInvocation(types, info, currentPath, unresolved, offset); case NEW_CLASS: return computeNewClass(types, info, currentPath, unresolved, offset); case POSTFIX_INCREMENT: case POSTFIX_DECREMENT: case PREFIX_INCREMENT: case PREFIX_DECREMENT: case UNARY_PLUS: case UNARY_MINUS: case BITWISE_COMPLEMENT: case LOGICAL_COMPLEMENT: return computeUnary(types, info, currentPath, unresolved, offset); case MULTIPLY: case DIVIDE: case REMAINDER: case PLUS: case MINUS: case LEFT_SHIFT: case RIGHT_SHIFT: case UNSIGNED_RIGHT_SHIFT: case LESS_THAN: case GREATER_THAN: case LESS_THAN_EQUAL: case GREATER_THAN_EQUAL: case EQUAL_TO: case NOT_EQUAL_TO: case AND: case XOR: case OR: case CONDITIONAL_AND: case CONDITIONAL_OR: return computeBinaryOperator(types, info, currentPath, unresolved, offset); case MULTIPLY_ASSIGNMENT: case DIVIDE_ASSIGNMENT: case REMAINDER_ASSIGNMENT: case PLUS_ASSIGNMENT: case MINUS_ASSIGNMENT: case LEFT_SHIFT_ASSIGNMENT: case RIGHT_SHIFT_ASSIGNMENT: case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: case AND_ASSIGNMENT: case XOR_ASSIGNMENT: case OR_ASSIGNMENT: // XXX: return computeCompoundAssignment(types, info, currentPath, unresolved, offset); return null; case ARRAY_TYPE: return computeArrayType(types, info, currentPath, unresolved, offset); case IMPORT: return computeImport(types, info, currentPath, unresolved, offset); case BLOCK: case BREAK: case CATCH: case COMPILATION_UNIT: case CONTINUE: case IDENTIFIER: case TYPE_CAST: case TRY: case EMPTY_STATEMENT: case PRIMITIVE_TYPE: case LABELED_STATEMENT: case MODIFIERS: case ERRONEOUS: case OTHER: case INT_LITERAL: case LONG_LITERAL: case FLOAT_LITERAL: case DOUBLE_LITERAL: case BOOLEAN_LITERAL: case CHAR_LITERAL: case STRING_LITERAL: case NULL_LITERAL: // ignored: return null; case CASE: case ANNOTATION: case UNBOUNDED_WILDCARD: case EXTENDS_WILDCARD: case SUPER_WILDCARD: // XXX: currently unhandled return null; default: // should not happen unless set of Tree.Kind changes: return null; } }