/** * Allows to check if static import may be performed for the given element. * * @param element element to check * @return target class that may be statically imported if any; <code>null</code> otherwise */ @Nullable public static PsiClass getClassToPerformStaticImport(@NotNull PsiElement element) { if (!PsiUtil.isLanguageLevel5OrHigher(element)) return null; if (!(element instanceof PsiIdentifier) || !(element.getParent() instanceof PsiJavaCodeReferenceElement)) { return null; } PsiJavaCodeReferenceElement refExpr = (PsiJavaCodeReferenceElement) element.getParent(); if (refExpr instanceof PsiMethodReferenceExpression) return null; final PsiElement gParent = refExpr.getParent(); if (gParent instanceof PsiMethodReferenceExpression) return null; if (!(gParent instanceof PsiJavaCodeReferenceElement) || isParameterizedReference((PsiJavaCodeReferenceElement) gParent)) return null; PsiElement resolved = refExpr.resolve(); if (!(resolved instanceof PsiClass)) { return null; } PsiClass psiClass = (PsiClass) resolved; if (PsiUtil.isFromDefaultPackage(psiClass) || psiClass.hasModifierProperty(PsiModifier.PRIVATE) || psiClass.getQualifiedName() == null) return null; final PsiElement ggParent = gParent.getParent(); if (ggParent instanceof PsiMethodCallExpression) { final PsiMethodCallExpression call = (PsiMethodCallExpression) ggParent.copy(); final PsiElement qualifier = call.getMethodExpression().getQualifier(); if (qualifier == null) return null; qualifier.delete(); final PsiMethod method = call.resolveMethod(); if (method != null && method.getContainingClass() != psiClass) return null; } else { final PsiJavaCodeReferenceElement copy = (PsiJavaCodeReferenceElement) gParent.copy(); final PsiElement qualifier = copy.getQualifier(); if (qualifier == null) return null; qualifier.delete(); final PsiElement target = copy.resolve(); if (target != null && PsiTreeUtil.getParentOfType(target, PsiClass.class) != psiClass) return null; } PsiFile file = refExpr.getContainingFile(); if (!(file instanceof PsiJavaFile)) return null; PsiImportList importList = ((PsiJavaFile) file).getImportList(); if (importList == null) return null; return psiClass; }
@Override public ASTNode process( @NotNull ASTNode element, boolean addImports, boolean incompleteCode, boolean useFqInJavadoc, boolean useFqInCode) { IElementType elementType = element.getElementType(); if ((elementType == JavaElementType.JAVA_CODE_REFERENCE || elementType == JavaElementType.REFERENCE_EXPRESSION) && !isAnnotated(element)) { IElementType parentType = element.getTreeParent().getElementType(); if (elementType == JavaElementType.JAVA_CODE_REFERENCE || incompleteCode || parentType == JavaElementType.REFERENCE_EXPRESSION || parentType == JavaElementType.METHOD_REF_EXPRESSION) { PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) element.getPsi(); PsiReferenceParameterList parameterList = ref.getParameterList(); if (parameterList != null) { PsiTypeElement[] typeParameters = parameterList.getTypeParameterElements(); for (PsiTypeElement typeParameter : typeParameters) { process( typeParameter.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } } boolean rightKind = true; if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { PsiJavaCodeReferenceElementImpl impl = (PsiJavaCodeReferenceElementImpl) element; int kind = impl.getKind(impl.getContainingFile()); rightKind = kind == PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND || kind == PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND; } if (rightKind) { // annotations may jump out of reference (see PsiJavaCodeReferenceImpl#setAnnotations()) // so they should be processed first List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(ref, PsiAnnotation.class); for (PsiAnnotation annotation : annotations) { process(annotation.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } boolean isInsideDocComment = TreeUtil.findParent(element, JavaDocElementType.DOC_COMMENT) != null; boolean isShort = !ref.isQualified(); if (isInsideDocComment ? !useFqInJavadoc : !useFqInCode) { if (isShort) return element; // short name already, no need to change } PsiElement refElement; if (!incompleteCode) { refElement = ref.resolve(); } else { PsiResolveHelper helper = JavaPsiFacade.getInstance(ref.getManager().getProject()).getResolveHelper(); final SourceJavaCodeReference reference = (SourceJavaCodeReference) element; refElement = helper.resolveReferencedClass(reference.getClassNameText(), ref); } if (refElement instanceof PsiClass) { PsiClass psiClass = (PsiClass) refElement; if (isInsideDocComment ? useFqInJavadoc : useFqInCode) { String qName = psiClass.getQualifiedName(); if (qName == null) return element; PsiFile file = ref.getContainingFile(); if (file instanceof PsiJavaFile) { if (ImportHelper.isImplicitlyImported(qName, (PsiJavaFile) file)) { if (isShort) return element; return makeShortReference((CompositeElement) element, psiClass, addImports); } String thisPackageName = ((PsiJavaFile) file).getPackageName(); if (ImportHelper.hasPackage(qName, thisPackageName)) { if (!isShort) { return makeShortReference((CompositeElement) element, psiClass, addImports); } } } return replaceReferenceWithFQ(element, psiClass); } else { int oldLength = element.getTextLength(); ASTNode treeElement = makeShortReference((CompositeElement) element, psiClass, addImports); if (treeElement.getTextLength() == oldLength && psiClass.getContainingClass() != null) { PsiElement qualifier = ref.getQualifier(); if (qualifier instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement) qualifier).resolve() instanceof PsiClass) { process( qualifier.getNode(), addImports, incompleteCode, useFqInJavadoc, useFqInCode); } } return treeElement; } } } } } for (ASTNode child = element.getFirstChildNode(); child != null; child = child.getTreeNext()) { //noinspection AssignmentToForLoopParameter child = process(child, addImports, incompleteCode, useFqInJavadoc, useFqInCode); } return element; }