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)); }
@Override public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) { Tree t = treePath.getLeaf(); JTextComponent editor = EditorRegistry.lastFocusedComponent(); Document doc = editor.getDocument(); SourcePositions sp = info.getTrees().getSourcePositions(); int start = (int) sp.getStartPosition(info.getCompilationUnit(), t); int end = (int) sp.getEndPosition(info.getCompilationUnit(), t); int endLine = info.getText().indexOf("\n", start); String line = info.getText().substring(start, endLine).trim(); if (!Suppression.isSuppressed(line)) { return Collections.<ErrorDescription>singletonList( ErrorDescriptionFactory.createErrorDescription( Severity.HINT, ERROR_DESCRIPTION, createFixes(doc, start, endLine), info.getFileObject(), start, end)); } else { return null; } }
private void analyzePatternsImpl(CompilationInfo javac) { checkState(1); String clsname = javaFile.getName(); TypeElement clselm = null; for (TypeElement top : javac.getTopLevelElements()) { if (clsname.contentEquals(top.getSimpleName())) { clselm = top; } } if (clselm == null) { isCancelled = true; error = new NotifyDescriptor.Message( NbBundle.getMessage( GenerateBeanInfoAction.class, "MSG_FileWitoutTopLevelClass", clsname, FileUtil.getFileDisplayName(javaFile)), NotifyDescriptor.ERROR_MESSAGE); return; } PatternAnalyser pa = new PatternAnalyser(javaFile, null, true); pa.analyzeAll(javac, clselm); // XXX analyze also superclasses here try { bia = new BiAnalyser(pa, javac); } catch (Exception ex) { isCancelled = true; Exceptions.printStackTrace(ex); } }
private static List<? extends TypeMirror> computeReturn( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { ReturnTree rt = (ReturnTree) parent.getLeaf(); if (rt.getExpression() == error) { TreePath method = findMethod(parent); if (method == null) { return null; } Element el = info.getTrees().getElement(method); if (el == null || el.getKind() != ElementKind.METHOD) { return null; } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(((ExecutableElement) el).getReturnType()); } return null; }
private static List<? extends TypeMirror> computeArrayType( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { types.add(ElementKind.CLASS); return Collections.singletonList( info.getElements().getTypeElement("java.lang.Object").asType()); }
private static List<? extends TypeMirror> computeVariableDeclaration( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { VariableTree vt = (VariableTree) parent.getLeaf(); if (vt.getInitializer() == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList( info.getTrees().getTypeMirror(new TreePath(parent, vt.getType()))); } TreePath context = parent.getParentPath(); if (vt.getType() != error || context == null) { return null; } switch (context.getLeaf().getKind()) { case ENHANCED_FOR_LOOP: ExpressionTree iterableTree = ((EnhancedForLoopTree) context.getLeaf()).getExpression(); TreePath iterablePath = new TreePath(context, iterableTree); TypeMirror type = getIterableGenericType(info, iterablePath); types.add(ElementKind.LOCAL_VARIABLE); return Collections.singletonList(type); default: types.add(ElementKind.CLASS); return Collections.<TypeMirror>emptyList(); } }
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> computeParametrizedType( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset, TypeMirror[] typeParameterBound, int[] numTypeParameters) { ParameterizedTypeTree ptt = (ParameterizedTypeTree) parent.getLeaf(); if (ptt.getType() == error) { Tree gpt = parent.getParentPath().getLeaf(); if (TreeUtilities.CLASS_TREE_KINDS.contains(gpt.getKind()) && ((ClassTree) gpt).getExtendsClause() == ptt) { types.add(ElementKind.CLASS); } else if (TreeUtilities.CLASS_TREE_KINDS.contains(gpt.getKind()) && ((ClassTree) gpt).getImplementsClause().contains(ptt)) { types.add(ElementKind.INTERFACE); } else { types.add(ElementKind.CLASS); types.add(ElementKind.INTERFACE); } if (numTypeParameters != null) { numTypeParameters[0] = ptt.getTypeArguments().size(); } return null; } TypeMirror resolved = info.getTrees().getTypeMirror(parent); DeclaredType resolvedDT = null; if (resolved != null && resolved.getKind() == TypeKind.DECLARED) { resolvedDT = (DeclaredType) resolved; } int index = 0; for (Tree t : ptt.getTypeArguments()) { if (t == error) { if (resolvedDT != null && typeParameterBound != null) { List<? extends TypeMirror> typeArguments = ((DeclaredType) resolvedDT.asElement().asType()).getTypeArguments(); if (typeArguments.size() > index) { typeParameterBound[0] = ((TypeVariable) typeArguments.get(index)).getUpperBound(); } } types.add(ElementKind.CLASS); // XXX: class/interface/enum/annotation? return null; } index++; } 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> 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; }
/* (non-Javadoc) * @see com.sun.source.util.TreeScanner#visitClass(com.sun.source.tree.ClassTree, java.lang.Object) */ @Override public Void visitClass(ClassTree t, Void v) { Element el = info.getTrees().getElement(getCurrentPath()); if (el == null) { StatusDisplayer.getDefault().setStatusText("Cannot resolve class!"); } else { typeElement = (TypeElement) el; } return null; }
private static List<? extends TypeMirror> computeAssignment( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { AssignmentTree at = (AssignmentTree) parent.getLeaf(); TypeMirror type = null; if (at.getVariable() == error) { type = info.getTrees().getTypeMirror(new TreePath(parent, at.getExpression())); if (type != null) { // anonymous class? type = org.netbeans.modules.java.hints.errors.Utilities.convertIfAnonymous(type); if (type.getKind() == TypeKind.EXECUTABLE) { // TODO: does not actualy work, attempt to solve situations like: // t = Collections.emptyList() // t = Collections.<String>emptyList(); // see also testCreateFieldMethod1 and testCreateFieldMethod2 tests: type = ((ExecutableType) type).getReturnType(); } } } if (at.getExpression() == error) { type = info.getTrees().getTypeMirror(new TreePath(parent, at.getVariable())); } // class or field: if (type == null) { if (ErrorHintsProvider.ERR.isLoggable(ErrorManager.INFORMATIONAL)) { ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "offset=" + offset); ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "errorTree=" + error); ErrorHintsProvider.ERR.log(ErrorManager.INFORMATIONAL, "type=null"); } return null; } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(type); }
private static List<? extends TypeMirror> computeReferenceType( Set<ElementKind> types, CompilationInfo info, Tree expression, Tree error, String type) { if (expression == error) { types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(info.getElements().getTypeElement(type).asType()); } 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> 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; }
private static List<? extends TypeMirror> computeImport( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { ImportTree tree = (ImportTree) parent.getLeaf(); if (tree.getQualifiedIdentifier() == error) { types.add(ElementKind.ANNOTATION_TYPE); types.add(ElementKind.CLASS); types.add(ElementKind.ENUM); types.add(ElementKind.INTERFACE); return Collections.singletonList( info.getElements().getTypeElement("java.lang.Object").asType()); } return null; }
private static List<? extends TypeMirror> computeMemberSelect( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { // class or field: MemberSelectTree ms = (MemberSelectTree) parent.getLeaf(); final TypeElement jlObject = info.getElements().getTypeElement("java.lang.Object"); if (jlObject != null // may happen if the platform is broken && !"class" .equals( ms.getIdentifier() .toString())) { // we obviously should not propose "Create Field" for // unknown.class: types.add(ElementKind.FIELD); types.add(ElementKind.CLASS); return Collections.singletonList(jlObject.asType()); } return null; }
private static List<? extends TypeMirror> computeBinaryOperator( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { BinaryTree bt = (BinaryTree) parent.getLeaf(); TreePath typeToResolve = null; if (bt.getLeftOperand() == error) { typeToResolve = new TreePath(parent, bt.getRightOperand()); } if (bt.getRightOperand() == error) { typeToResolve = new TreePath(parent, bt.getLeftOperand()); } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return typeToResolve != null ? Collections.singletonList(info.getTrees().getTypeMirror(typeToResolve)) : 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> computeMethod( Set<ElementKind> types, CompilationInfo info, TreePath parent, TypeMirror[] typeParameterBound, Tree error, int offset) { // class or field: // check the error is in the body: // #92419: check for abstract method/method without body: MethodTree mt = (MethodTree) parent.getLeaf(); if (mt.getReturnType() == error) { types.add(ElementKind.CLASS); types.add(ElementKind.INTERFACE); types.add(ElementKind.ENUM); } List<? extends ExpressionTree> throwList = mt.getThrows(); if (throwList != null && !throwList.isEmpty()) { for (ExpressionTree t : throwList) { if (t == error) { types.add(ElementKind.CLASS); typeParameterBound[0] = info.getElements().getTypeElement("java.lang.Exception").asType(); break; } } } if (mt.getBody() == null) { return null; } try { Document doc = info.getDocument(); if (doc != null) { // XXX int bodyStart = Utilities.findBodyStart( parent.getLeaf(), info.getCompilationUnit(), info.getTrees().getSourcePositions(), doc); int bodyEnd = (int) info.getTrees() .getSourcePositions() .getEndPosition(info.getCompilationUnit(), parent.getLeaf()); types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); if (bodyStart <= offset && offset <= bodyEnd) return Collections.singletonList( info.getElements().getTypeElement("java.lang.Object").asType()); } } catch (IOException ex) { Logger.getLogger("global").log(Level.INFO, ex.getMessage(), ex); } return null; }
@Override public void run(final CompilationInfo parameter) { TypeElement clazz = parameter.getElements().getTypeElement(annotation.getClassName()); if (clazz == null) { // XXX: log return; } Element resolved = null; if (annotation instanceof FieldAnnotation) { FieldAnnotation fa = (FieldAnnotation) annotation; for (VariableElement var : ElementFilter.fieldsIn(clazz.getEnclosedElements())) { if (var.getSimpleName().contentEquals(fa.getFieldName())) { resolved = var; break; } } } else if (annotation instanceof MethodAnnotation) { MethodAnnotation ma = (MethodAnnotation) annotation; for (ExecutableElement method : ElementFilter.methodsIn(clazz.getEnclosedElements())) { if (method.getSimpleName().contentEquals(ma.getMethodName())) { if (ma.getMethodSignature() .equals(SourceUtils.getJVMSignature(ElementHandle.create(method))[2])) { resolved = method; break; } } } } else if (annotation instanceof ClassAnnotation) { resolved = clazz; } if (resolved == null) { // XXX: log return; } final Element resolvedFin = resolved; new CancellableTreePathScanner<Void, Void>() { @Override public Void visitVariable(VariableTree node, Void p) { if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) { int[] span = parameter.getTreeUtilities().findNameSpan(node); if (span != null) { result[0] = span[0]; result[1] = span[1]; } } return super.visitVariable(node, p); } @Override public Void visitMethod(MethodTree node, Void p) { if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) { int[] span = parameter.getTreeUtilities().findNameSpan(node); if (span != null) { result[0] = span[0]; result[1] = span[1]; } } return super.visitMethod(node, p); } @Override public Void visitClass(ClassTree node, Void p) { if (resolvedFin.equals(parameter.getTrees().getElement(getCurrentPath()))) { int[] span = parameter.getTreeUtilities().findNameSpan(node); if (span != null) { result[0] = span[0]; result[1] = span[1]; } } return super.visitClass(node, p); } }.scan(parameter.getCompilationUnit(), 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; } }