private static boolean hasCorrectType( @Nullable PsiAnnotationMemberValue value, PsiType expectedType) { if (value == null) return false; if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS) && !(value instanceof PsiClassObjectAccessExpression)) { return false; } if (value instanceof PsiAnnotation) { final PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation) value).getNameReferenceElement(); if (nameRef == null) return true; if (expectedType instanceof PsiClassType) { final PsiClass aClass = ((PsiClassType) expectedType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return true; } if (expectedType instanceof PsiArrayType) { final PsiType componentType = ((PsiArrayType) expectedType).getComponentType(); if (componentType instanceof PsiClassType) { final PsiClass aClass = ((PsiClassType) componentType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return true; } } return false; } if (value instanceof PsiArrayInitializerMemberValue) { return expectedType instanceof PsiArrayType; } if (value instanceof PsiExpression) { final PsiExpression expression = (PsiExpression) value; return expression.getType() != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expression) || expectedType instanceof PsiArrayType && TypeConversionUtil.areTypesAssignmentCompatible( ((PsiArrayType) expectedType).getComponentType(), expression); } return true; }
@Override public void visitThisExpression(PsiThisExpression expression) { super.visitThisExpression(expression); final PsiJavaCodeReferenceElement qualifier = expression.getQualifier(); if (qualifier != null && qualifier.isReferenceTo(mySourceClass)) { try { qualifier.bindToElement(myTargetSuperClass); } catch (IncorrectOperationException e) { LOG.error(e); } } }
@Override public void visitSuperExpression(PsiSuperExpression expression) { super.visitSuperExpression(expression); final PsiJavaCodeReferenceElement qualifier = expression.getQualifier(); if (qualifier != null && qualifier.isReferenceTo(mySourceClass)) { try { expression.replace( JavaPsiFacade.getElementFactory(myProject) .createExpressionFromText(myTargetSuperClass.getName() + ".this", null)); } catch (IncorrectOperationException e) { LOG.error(e); } } }
public void handleInsert( final InsertionContext context, final JavaPsiClassReferenceElement item) { final char c = context.getCompletionChar(); int offset = context.getTailOffset() - 1; final PsiFile file = context.getFile(); if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatementBase.class, false) != null) { final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, offset, PsiJavaCodeReferenceElement.class, false); final String qname = item.getQualifiedName(); if (qname != null && (ref == null || !qname.equals(ref.getCanonicalText()))) { AllClassesGetter.INSERT_FQN.handleInsert(context, item); } return; } PsiElement position = file.findElementAt(offset); PsiClass psiClass = item.getObject(); final Project project = context.getProject(); final boolean annotation = insertingAnnotation(context, item); final Editor editor = context.getEditor(); if (c == '#') { context.setLaterRunnable( new Runnable() { public void run() { new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(project, editor); } }); } else if (c == '.' && PsiTreeUtil.getParentOfType(position, PsiParameterList.class) == null) { AutoPopupController.getInstance(context.getProject()) .autoPopupMemberLookup(context.getEditor(), null); } if (position != null) { PsiElement parent = position.getParent(); if (parent instanceof PsiJavaCodeReferenceElement) { final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent; if (PsiTreeUtil.getParentOfType(position, PsiDocTag.class) != null && ref.isReferenceTo(psiClass)) { return; } } } OffsetKey refEnd = context.trackOffset(context.getTailOffset(), false); boolean fillTypeArgs = context.getCompletionChar() == '<'; if (fillTypeArgs) { context.setAddCompletionChar(false); } if (shouldInsertParentheses(psiClass, position)) { if (ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) { fillTypeArgs |= psiClass.hasTypeParameters() && PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_5); } } else if (insertingAnnotationWithParameters(context, item)) { JavaCompletionUtil.insertParentheses(context, item, false, true); AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null); } LOG.assertTrue(context.getTailOffset() >= 0); String docText = context.getDocument().getText(); DefaultInsertHandler.addImportForItem(context, item); if (context.getTailOffset() < 0) { LOG.error( LogMessageEx.createEvent( "Tail offset degraded after insertion", "start=" + context.getStartOffset(), new Attachment( context.getFile().getViewProvider().getVirtualFile().getPath(), docText))); } if (annotation) { // Check if someone inserts annotation class that require @ PsiElement elementAt = file.findElementAt(context.getStartOffset()); final PsiElement parentElement = elementAt != null ? elementAt.getParent() : null; if (elementAt instanceof PsiIdentifier && (PsiTreeUtil.getParentOfType(elementAt, PsiAnnotationParameterList.class) != null || parentElement instanceof PsiErrorElement && parentElement.getParent() instanceof PsiJavaFile // top level annotation without @ ) && isAtTokenNeeded(context)) { int expectedOffsetForAtToken = elementAt.getTextRange().getStartOffset(); context.getDocument().insertString(expectedOffsetForAtToken, "@"); } } if (fillTypeArgs) { PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); int typeArgs = context.getOffset(refEnd); if (typeArgs >= 0) { context.getDocument().insertString(typeArgs, "<>"); context.getEditor().getCaretModel().moveToOffset(typeArgs + 1); } } }
@Nullable public static HighlightInfo checkMemberValueType( @Nullable PsiAnnotationMemberValue value, PsiType expectedType) { if (value == null) return null; if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)) { if (!(value instanceof PsiClassObjectAccessExpression)) { String description = JavaErrorMessages.message("annotation.non.class.literal.attribute.value"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } } if (value instanceof PsiAnnotation) { PsiJavaCodeReferenceElement nameRef = ((PsiAnnotation) value).getNameReferenceElement(); if (nameRef == null) return null; if (expectedType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType) expectedType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } if (expectedType instanceof PsiArrayType) { PsiType componentType = ((PsiArrayType) expectedType).getComponentType(); if (componentType instanceof PsiClassType) { PsiClass aClass = ((PsiClassType) componentType).resolve(); if (aClass != null && nameRef.isReferenceTo(aClass)) return null; } } String description = JavaErrorMessages.message( "annotation.incompatible.types", formatReference(nameRef), JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } if (value instanceof PsiArrayInitializerMemberValue) { if (expectedType instanceof PsiArrayType) return null; String description = JavaErrorMessages.message( "annotation.illegal.array.initializer", JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } if (value instanceof PsiExpression) { PsiExpression expr = (PsiExpression) value; PsiType type = expr.getType(); if (type != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expr) || expectedType instanceof PsiArrayType && TypeConversionUtil.areTypesAssignmentCompatible( ((PsiArrayType) expectedType).getComponentType(), expr)) { return null; } String description = JavaErrorMessages.message( "annotation.incompatible.types", JavaHighlightUtil.formatType(type), JavaHighlightUtil.formatType(expectedType)); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(value) .descriptionAndTooltip(description) .create(); } LOG.error("Unknown annotation member value: " + value); return null; }