private void doMoveClass(PsiSubstitutor substitutor, MemberInfo info) { PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject); PsiClass aClass = (PsiClass) info.getMember(); if (Boolean.FALSE.equals(info.getOverrides())) { final PsiReferenceList sourceReferenceList = info.getSourceReferenceList(); LOG.assertTrue(sourceReferenceList != null); PsiJavaCodeReferenceElement ref = mySourceClass.equals(sourceReferenceList.getParent()) ? RefactoringUtil.removeFromReferenceList(sourceReferenceList, aClass) : RefactoringUtil.findReferenceToClass(sourceReferenceList, aClass); if (ref != null && !myTargetSuperClass.isInheritor(aClass, false)) { RefactoringUtil.replaceMovedMemberTypeParameters( ref, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory); final PsiReferenceList referenceList = myIsTargetInterface ? myTargetSuperClass.getExtendsList() : myTargetSuperClass.getImplementsList(); assert referenceList != null; referenceList.add(ref); } } else { RefactoringUtil.replaceMovedMemberTypeParameters( aClass, PsiUtil.typeParametersIterable(mySourceClass), substitutor, elementFactory); fixReferencesToStatic(aClass); final PsiMember movedElement = (PsiMember) myTargetSuperClass.add( convertClassToLanguage(aClass, myTargetSuperClass.getLanguage())); myMembersAfterMove.add(movedElement); aClass.delete(); } }
private static void findClassUsages( final PsiClass psiClass, final PsiElement[] allElementsToDelete, final List<UsageInfo> usages) { final boolean justPrivates = containsOnlyPrivates(psiClass); final String qualifiedName = psiClass.getQualifiedName(); final boolean annotationType = psiClass.isAnnotationType() && qualifiedName != null; ReferencesSearch.search(psiClass) .forEach( reference -> { final PsiElement element = reference.getElement(); if (!isInside(element, allElementsToDelete)) { PsiElement parent = element.getParent(); if (parent instanceof PsiReferenceList) { final PsiElement pparent = parent.getParent(); if (pparent instanceof PsiClass && element instanceof PsiJavaCodeReferenceElement) { final PsiClass inheritor = (PsiClass) pparent; // If psiClass contains only private members, then it is safe to remove it and // change inheritor's extends/implements accordingly if (justPrivates) { if (parent.equals(inheritor.getExtendsList()) || parent.equals(inheritor.getImplementsList())) { usages.add( new SafeDeleteExtendsClassUsageInfo( (PsiJavaCodeReferenceElement) element, psiClass, inheritor)); return true; } } } } LOG.assertTrue(element.getTextRange() != null); final PsiFile containingFile = psiClass.getContainingFile(); boolean sameFileWithSingleClass = false; if (containingFile instanceof PsiClassOwner) { final PsiClass[] classes = ((PsiClassOwner) containingFile).getClasses(); sameFileWithSingleClass = classes.length == 1 && classes[0] == psiClass && element.getContainingFile() == containingFile; } final boolean safeDelete = sameFileWithSingleClass || isInNonStaticImport(element); if (annotationType && parent instanceof PsiAnnotation) { usages.add( new SafeDeleteAnnotation((PsiAnnotation) parent, psiClass, safeDelete)); } else { usages.add( new SafeDeleteReferenceJavaDeleteUsageInfo(element, psiClass, safeDelete)); } } return true; }); }
private boolean isAccessibleFrom(RefElement from, RefJavaElement to, String accessModifier) { if (accessModifier == PsiModifier.PUBLIC) return true; final RefJavaUtil refUtil = RefJavaUtil.getInstance(); if (accessModifier == PsiModifier.PACKAGE_LOCAL) { return RefJavaUtil.getPackage(from) == RefJavaUtil.getPackage(to); } RefClass fromTopLevel = refUtil.getTopLevelClass(from); RefClass toTopLevel = refUtil.getTopLevelClass(to); RefClass fromOwner = refUtil.getOwnerClass(from); RefClass toOwner = refUtil.getOwnerClass(to); if (accessModifier == PsiModifier.PROTECTED) { if (SUGGEST_PRIVATE_FOR_INNERS) { return refUtil.isInheritor(fromTopLevel, toOwner) || fromOwner != null && refUtil.isInheritor(fromOwner, toTopLevel) || toOwner != null && refUtil.getOwnerClass(toOwner) == from; } return refUtil.isInheritor(fromTopLevel, toOwner); } if (accessModifier == PsiModifier.PRIVATE) { if (SUGGEST_PRIVATE_FOR_INNERS) { if (isInExtendsList(to, fromTopLevel.getElement().getExtendsList())) return false; if (isInExtendsList(to, fromTopLevel.getElement().getImplementsList())) return false; if (isInAnnotations(to, fromTopLevel)) return false; return fromTopLevel == toOwner || fromOwner == toTopLevel || toOwner != null && refUtil.getOwnerClass(toOwner) == from; } if (fromOwner != null && fromOwner.isStatic() && !to.isStatic() && refUtil.isInheritor(fromOwner, toOwner)) return false; if (fromTopLevel == toOwner) { if (from instanceof RefClass && to instanceof RefClass) { final PsiClass fromClass = ((RefClass) from).getElement(); LOG.assertTrue(fromClass != null); if (isInExtendsList(to, fromClass.getExtendsList())) return false; if (isInExtendsList(to, fromClass.getImplementsList())) return false; } return true; } } return false; }
@Nullable private PsiType extractListTypeFromContainingClass( PsiElement element) { PsiClass listClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); if (listClass == null) { return null; } final PsiMethod[] getMethods = listClass.findMethodsByName("get", true); if (getMethods.length == 0) { return null; } final PsiType type = getMethods[0].getReturnType(); if (!(type instanceof PsiClassType)) { return null; } final PsiClassType classType = (PsiClassType)type; final PsiClass parameterClass = classType.resolve(); if (parameterClass == null) { return null; } PsiClass subClass = null; while (listClass != null && !listClass.hasTypeParameters()) { subClass = listClass; listClass = listClass.getSuperClass(); } if (listClass == null || subClass == null) { return TypeUtils.getObjectType(element); } final PsiTypeParameter[] typeParameters = listClass.getTypeParameters(); if (!parameterClass.equals(typeParameters[0])) { return TypeUtils.getObjectType(element); } final PsiReferenceList extendsList = subClass.getExtendsList(); if (extendsList == null) { return null; } final PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements(); if (referenceElements.length == 0) { return null; } final PsiType[] types = referenceElements[0].getTypeParameters(); if (types.length == 0) { return TypeUtils.getObjectType(element); } return types[0]; }
public void testReferenceElement() throws Exception { final JavaPsiFacade manager = getJavaFacade(); final PsiClass classA = manager .getElementFactory() .createClassFromText("class A extends List<String>{}", null) .getInnerClasses()[0]; final PsiClass classTestList = manager.findClass( "test.List", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)); assertNotNull(classTestList); classA.getExtendsList().getReferenceElements()[0].bindToElement(classTestList); assertEquals("class A extends test.List<String>{}", classA.getText()); }
private static void addSuperClass(PsiClass targetClass, Project project, String superClassName) throws IncorrectOperationException { if (superClassName == null) return; PsiElementFactory ef = JavaPsiFacade.getInstance(project).getElementFactory(); PsiJavaCodeReferenceElement superClassRef; PsiClass superClass = findClass(project, superClassName); if (superClass != null) { superClassRef = ef.createClassReferenceElement(superClass); } else { superClassRef = ef.createFQClassNameReferenceElement(superClassName, GlobalSearchScope.allScope(project)); } targetClass.getExtendsList().add(superClassRef); }
public void testClassTypeParamsPresentation() throws Exception { PsiClass psiClass = getTestClass(); final PsiReferenceList extendsList = psiClass.getExtendsList(); final PsiJavaCodeReferenceElement referenceElement = extendsList.getReferenceElements()[0]; final PsiClass superClass = extendsList.getReferencedTypes()[0].resolve(); final File htmlPath = new File( JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/" + getTestName(true) + ".html"); String htmlText = FileUtil.loadFile(htmlPath); String docInfo = new JavaDocumentationProvider().getQuickNavigateInfo(superClass, referenceElement); assertNotNull(docInfo); assertEquals( StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(docInfo.trim())); }
static PsiClass extractInterface( PsiDirectory targetDir, PsiClass aClass, String interfaceName, MemberInfo[] selectedMembers, DocCommentPolicy javaDocPolicy) throws IncorrectOperationException { PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName); PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers); final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList(); assert referenceList != null; referenceList.add(ref); PullUpHelper pullUpHelper = new PullUpHelper(aClass, anInterface, selectedMembers, javaDocPolicy); pullUpHelper.moveMembersToBase(); return anInterface; }
@NotNull public static PsiClassType[] getExtendsListTypes(@NotNull PsiClass psiClass) { if (psiClass.isEnum()) { PsiClassType enumSuperType = getEnumSuperType( psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory()); return enumSuperType == null ? PsiClassType.EMPTY_ARRAY : new PsiClassType[] {enumSuperType}; } if (psiClass.isAnnotationType()) { return new PsiClassType[] { getAnnotationSuperType( psiClass, JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory()) }; } final PsiReferenceList extendsList = psiClass.getExtendsList(); if (extendsList != null) { return extendsList.getReferencedTypes(); } return PsiClassType.EMPTY_ARRAY; }
@Nullable private static PsiReferenceParameterList findTypeArgumentsList( final PsiClass superClass, final PsiClass derivedClass) { PsiReferenceParameterList referenceParameterList = null; if (derivedClass instanceof PsiAnonymousClass) { referenceParameterList = ((PsiAnonymousClass) derivedClass).getBaseClassReference().getParameterList(); } else { final PsiReferenceList implementsList = derivedClass.getImplementsList(); if (implementsList != null) { referenceParameterList = extractReferenceParameterList(superClass, implementsList); } if (referenceParameterList == null) { final PsiReferenceList extendsList = derivedClass.getExtendsList(); if (extendsList != null) { referenceParameterList = extractReferenceParameterList(superClass, extendsList); } } } return referenceParameterList; }
private static List<PsiClassType> getSuperTypes(PsiClass clazz) { if (clazz instanceof GrTypeDefinition) { final GrExtendsClause elist = ((GrTypeDefinition) clazz).getExtendsClause(); final GrImplementsClause ilist = ((GrTypeDefinition) clazz).getImplementsClause(); if (elist == null && ilist == null) return ContainerUtil.emptyList(); final ArrayList<PsiClassType> types = new ArrayList<PsiClassType>(); if (elist != null) ContainerUtil.addAll(types, elist.getReferencedTypes()); if (ilist != null) ContainerUtil.addAll(types, ilist.getReferencedTypes()); return types; } else { final PsiReferenceList elist = clazz.getExtendsList(); final PsiReferenceList ilist = clazz.getImplementsList(); if (elist == null && ilist == null) return ContainerUtil.emptyList(); final ArrayList<PsiClassType> types = new ArrayList<PsiClassType>(); if (elist != null) ContainerUtil.addAll(types, elist.getReferencedTypes()); if (ilist != null) ContainerUtil.addAll(types, ilist.getReferencedTypes()); return types; } }
public void replace(final ReplacementInfo info, ReplaceOptions options) { PsiElement elementToReplace = info.getMatch(0); PsiElement elementParent = elementToReplace.getParent(); String replacementToMake = info.getReplacement(); Project project = myContext.getProject(); PsiElement el = findRealSubstitutionElement(elementToReplace); boolean listContext = isListContext(el); if (el instanceof PsiAnnotation && !StringUtil.startsWithChar(replacementToMake, '@')) { replacementToMake = "@" + replacementToMake; } PsiElement[] statements = ReplacerUtil.createTreeForReplacement( replacementToMake, el instanceof PsiMember && !isSymbolReplacement(el) ? PatternTreeContext.Class : PatternTreeContext.Block, myContext); if (listContext) { if (statements.length > 1) { elementParent.addRangeBefore( statements[0], statements[statements.length - 1], elementToReplace); } else if (statements.length == 1) { PsiElement replacement = getMatchExpr(statements[0], elementToReplace); handleModifierList(el, replacement); replacement = handleSymbolReplacement(replacement, el); if (replacement instanceof PsiTryStatement) { final List<PsiCatchSection> unmatchedCatchSections = el.getUserData(JavaMatchingVisitor.UNMATCHED_CATCH_SECTION_CONTENT_VAR_KEY); final PsiCatchSection[] catches = ((PsiTryStatement) replacement).getCatchSections(); if (unmatchedCatchSections != null) { for (int i = unmatchedCatchSections.size() - 1; i >= 0; --i) { final PsiParameter parameter = unmatchedCatchSections.get(i).getParameter(); final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); final PsiCatchSection catchSection = elementFactory.createCatchSection(parameter.getType(), parameter.getName(), null); catchSection.getCatchBlock().replace(unmatchedCatchSections.get(i).getCatchBlock()); replacement.addAfter(catchSection, catches[catches.length - 1]); replacement.addBefore(createWhiteSpace(replacement), replacement.getLastChild()); } } } try { final PsiElement inserted = elementParent.addBefore(replacement, elementToReplace); if (replacement instanceof PsiComment && (elementParent instanceof PsiIfStatement || elementParent instanceof PsiLoopStatement)) { elementParent.addAfter(createSemicolon(replacement), inserted); } } catch (IncorrectOperationException e) { elementToReplace.replace(replacement); } } } else if (statements.length > 0) { PsiElement replacement = ReplacerUtil.copySpacesAndCommentsBefore( elementToReplace, statements, replacementToMake, elementParent); replacement = getMatchExpr(replacement, elementToReplace); if (replacement instanceof PsiStatement && !(replacement.getLastChild() instanceof PsiJavaToken) && !(replacement.getLastChild() instanceof PsiComment)) { // assert w/o ; final PsiElement prevLastChildInParent = replacement.getLastChild().getPrevSibling(); if (prevLastChildInParent != null) { elementParent.addRangeBefore(replacement.getFirstChild(), prevLastChildInParent, el); } else { elementParent.addBefore(replacement.getFirstChild(), el); } el.getNode().getTreeParent().removeChild(el.getNode()); } else { // preserve comments handleModifierList(el, replacement); if (replacement instanceof PsiClass) { // modifier list final PsiStatement[] searchStatements = getCodeBlock().getStatements(); if (searchStatements.length > 0 && searchStatements[0] instanceof PsiDeclarationStatement && ((PsiDeclarationStatement) searchStatements[0]).getDeclaredElements()[0] instanceof PsiClass) { final PsiClass replaceClazz = (PsiClass) replacement; final PsiClass queryClazz = (PsiClass) ((PsiDeclarationStatement) searchStatements[0]).getDeclaredElements()[0]; final PsiClass clazz = (PsiClass) el; if (replaceClazz.getExtendsList().getTextLength() == 0 && queryClazz.getExtendsList().getTextLength() == 0 && clazz.getExtendsList().getTextLength() != 0) { replaceClazz.addBefore( clazz.getExtendsList().getPrevSibling(), replaceClazz.getExtendsList()); // whitespace replaceClazz .getExtendsList() .addRange( clazz.getExtendsList().getFirstChild(), clazz.getExtendsList().getLastChild()); } if (replaceClazz.getImplementsList().getTextLength() == 0 && queryClazz.getImplementsList().getTextLength() == 0 && clazz.getImplementsList().getTextLength() != 0) { replaceClazz.addBefore( clazz.getImplementsList().getPrevSibling(), replaceClazz.getImplementsList()); // whitespace replaceClazz .getImplementsList() .addRange( clazz.getImplementsList().getFirstChild(), clazz.getImplementsList().getLastChild()); } if (replaceClazz.getTypeParameterList().getTextLength() == 0 && queryClazz.getTypeParameterList().getTextLength() == 0 && clazz.getTypeParameterList().getTextLength() != 0) { // skip < and > replaceClazz.getTypeParameterList().replace(clazz.getTypeParameterList()); } } } replacement = handleSymbolReplacement(replacement, el); el.replace(replacement); } } else { final PsiElement nextSibling = el.getNextSibling(); el.delete(); if (nextSibling instanceof PsiWhiteSpace && nextSibling.isValid()) { nextSibling.delete(); } } if (listContext) { final int matchSize = info.getMatchesCount(); for (int i = 0; i < matchSize; ++i) { PsiElement matchElement = info.getMatch(i); PsiElement element = findRealSubstitutionElement(matchElement); if (element == null) continue; PsiElement firstToDelete = element; PsiElement lastToDelete = element; PsiElement prevSibling = element.getPrevSibling(); PsiElement nextSibling = element.getNextSibling(); if (prevSibling instanceof PsiWhiteSpace) { firstToDelete = prevSibling; prevSibling = prevSibling != null ? prevSibling.getPrevSibling() : null; } else if (prevSibling == null && nextSibling instanceof PsiWhiteSpace) { lastToDelete = nextSibling; } if (nextSibling instanceof XmlText && i + 1 < matchSize) { final PsiElement next = info.getMatch(i + 1); if (next != null && next == nextSibling.getNextSibling()) { lastToDelete = nextSibling; } } if (element instanceof PsiExpression) { final PsiElement parent = element.getParent().getParent(); if ((parent instanceof PsiCall || parent instanceof PsiAnonymousClass) && prevSibling instanceof PsiJavaToken && ((PsiJavaToken) prevSibling).getTokenType() == JavaTokenType.COMMA) { firstToDelete = prevSibling; } } else if (element instanceof PsiParameter && prevSibling instanceof PsiJavaToken && ((PsiJavaToken) prevSibling).getTokenType() == JavaTokenType.COMMA) { firstToDelete = prevSibling; } element.getParent().deleteChildRange(firstToDelete, lastToDelete); } } }