@NotNull protected UsageInfo[] findUsages() { final PsiManager manager = myMethod.getManager(); final GlobalSearchScope searchScope = GlobalSearchScope.allScope(manager.getProject()); final List<UsageInfo> usages = new ArrayList<UsageInfo>(); for (PsiReference ref : ReferencesSearch.search(myMethod, searchScope, false)) { final PsiElement element = ref.getElement(); if (element instanceof PsiReferenceExpression) { boolean isInternal = PsiTreeUtil.isAncestor(myMethod, element, true); usages.add(new MethodCallUsageInfo((PsiReferenceExpression) element, isInternal)); } else if (element instanceof PsiDocTagValue) { usages.add(new JavadocUsageInfo(((PsiDocTagValue) element))); } else { throw new UnknownReferenceTypeException(element.getLanguage()); } } if (myTargetClass.isInterface()) { addInheritorUsages(myTargetClass, searchScope, usages); } final PsiCodeBlock body = myMethod.getBody(); if (body != null) { body.accept( new JavaRecursiveElementWalkingVisitor() { @Override public void visitNewExpression(PsiNewExpression expression) { if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) { usages.add(new InternalUsageInfo(expression)); } super.visitNewExpression(expression); } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { if (MoveInstanceMembersUtil.getClassReferencedByThis(expression) != null) { usages.add(new InternalUsageInfo(expression)); } else if (!expression.isQualified()) { final PsiElement resolved = expression.resolve(); if (myTargetVariable.equals(resolved)) { usages.add(new InternalUsageInfo(expression)); } } super.visitReferenceExpression(expression); } }); } return usages.toArray(new UsageInfo[usages.size()]); }
private PsiMethod generateDelegate(final PsiMethod methodToReplaceIn) throws IncorrectOperationException { final PsiMethod delegate = (PsiMethod) methodToReplaceIn.copy(); final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); ChangeSignatureProcessor.makeEmptyBody(elementFactory, delegate); final PsiCallExpression callExpression = ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, delegate.getName()); final PsiExpressionList argumentList = callExpression.getArgumentList(); assert argumentList != null; final PsiParameter[] psiParameters = methodToReplaceIn.getParameterList().getParameters(); final PsiParameter anchorParameter = getAnchorParameter(methodToReplaceIn); if (psiParameters.length == 0) { argumentList.add(myParameterInitializer); } else { if (anchorParameter == null) { argumentList.add(myParameterInitializer); } for (int i = 0; i < psiParameters.length; i++) { PsiParameter psiParameter = psiParameters[i]; if (!myParametersToRemove.contains(i)) { final PsiExpression expression = elementFactory.createExpressionFromText(psiParameter.getName(), delegate); argumentList.add(expression); } if (psiParameter == anchorParameter) { argumentList.add(myParameterInitializer); } } } return (PsiMethod) methodToReplaceIn.getContainingClass().addBefore(delegate, methodToReplaceIn); }
private static PsiExpression createThisExpr(final PsiManager manager) { try { return JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createExpressionFromText("this", null); } catch (IncorrectOperationException e) { LOG.error(e); return null; } }
private void addMethodConflicts(MultiMap<PsiElement, String> conflicts) { String newMethodName = myChangeInfo.getNewName(); if (!(myChangeInfo instanceof JavaChangeInfo)) { return; } try { PsiMethod prototype; final PsiMethod method = myChangeInfo.getMethod(); if (!StdLanguages.JAVA.equals(method.getLanguage())) return; PsiManager manager = method.getManager(); PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); if (returnType != null) { prototype = factory.createMethod(newMethodName, returnType.getType(method, manager)); } else { prototype = factory.createConstructor(); prototype.setName(newMethodName); } JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); for (JavaParameterInfo info : parameters) { PsiType parameterType = info.createType(method, manager); if (parameterType == null) { parameterType = JavaPsiFacade.getElementFactory(method.getProject()) .createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, method); } PsiParameter param = factory.createParameter(info.getName(), parameterType); prototype.getParameterList().add(param); } ConflictsUtil.checkMethodConflicts( method.getContainingClass(), method, prototype, conflicts); } catch (IncorrectOperationException e) { LOG.error(e); } }
/** if expressionToSearch is null, search for localVariable */ public IntroduceParameterProcessor( @NotNull Project project, PsiMethod methodToReplaceIn, @NotNull PsiMethod methodToSearchFor, PsiExpression parameterInitializer, PsiExpression expressionToSearch, PsiLocalVariable localVariable, boolean removeLocalVariable, String parameterName, boolean replaceAllOccurences, int replaceFieldsWithGetters, boolean declareFinal, boolean generateDelegate, PsiType forcedType, @NotNull TIntArrayList parametersToRemove) { super(project); myMethodToReplaceIn = methodToReplaceIn; myMethodToSearchFor = methodToSearchFor; myParameterInitializer = parameterInitializer; myExpressionToSearch = expressionToSearch; myLocalVariable = localVariable; myRemoveLocalVariable = removeLocalVariable; myParameterName = parameterName; myReplaceAllOccurences = replaceAllOccurences; myReplaceFieldsWithGetters = replaceFieldsWithGetters; myDeclareFinal = declareFinal; myGenerateDelegate = generateDelegate; myForcedType = forcedType; myManager = PsiManager.getInstance(project); myParametersToRemove = parametersToRemove; myInitializerWrapper = expressionToSearch == null ? null : new JavaExpressionWrapper(expressionToSearch); }
@NotNull public static UsageInfo[] findUsages( final PsiElement element, final String newName, boolean searchInStringsAndComments, boolean searchForTextOccurrences, Map<? extends PsiElement, String> allRenames) { final List<UsageInfo> result = Collections.synchronizedList(new ArrayList<UsageInfo>()); PsiManager manager = element.getManager(); GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element); Collection<PsiReference> refs = processor.findReferences(element, searchInStringsAndComments); for (final PsiReference ref : refs) { if (ref == null) { LOG.error("null reference from processor " + processor); continue; } PsiElement referenceElement = ref.getElement(); result.add( new MoveRenameUsageInfo( referenceElement, ref, ref.getRangeInElement().getStartOffset(), ref.getRangeInElement().getEndOffset(), element, ref.resolve() == null)); } processor.findCollisions(element, newName, allRenames, result); final PsiElement searchForInComments = processor.getElementToSearchInStringsAndComments(element); if (searchInStringsAndComments && searchForInComments != null) { String stringToSearch = ElementDescriptionUtil.getElementDescription( searchForInComments, NonCodeSearchDescriptionLocation.STRINGS_AND_COMMENTS); if (stringToSearch.length() > 0) { final String stringToReplace = getStringToReplace(element, newName, false, processor); TextOccurrencesUtil.UsageInfoFactory factory = new NonCodeUsageInfoFactory(searchForInComments, stringToReplace); TextOccurrencesUtil.addUsagesInStringsAndComments( searchForInComments, stringToSearch, result, factory); } } if (searchForTextOccurrences && searchForInComments != null) { String stringToSearch = ElementDescriptionUtil.getElementDescription( searchForInComments, NonCodeSearchDescriptionLocation.NON_JAVA); if (stringToSearch.length() > 0) { final String stringToReplace = getStringToReplace(element, newName, true, processor); addTextOccurrence( searchForInComments, result, projectScope, stringToSearch, stringToReplace); } final Pair<String, String> additionalStringToSearch = processor.getTextOccurrenceSearchStrings(searchForInComments, newName); if (additionalStringToSearch != null && additionalStringToSearch.first.length() > 0) { addTextOccurrence( searchForInComments, result, projectScope, additionalStringToSearch.first, additionalStringToSearch.second); } } return result.toArray(new UsageInfo[result.size()]); }
protected void performRefactoring(UsageInfo[] usages) { try { PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); PsiType initializerType = getInitializerType(myForcedType, myParameterInitializer, myLocalVariable); setForcedType(initializerType); // Converting myParameterInitializer if (myParameterInitializer == null) { LOG.assertTrue(myLocalVariable != null); myParameterInitializer = factory.createExpressionFromText(myLocalVariable.getName(), myLocalVariable); } else if (myParameterInitializer instanceof PsiArrayInitializerExpression) { final PsiExpression newExprArrayInitializer = RefactoringUtil.createNewExpressionFromArrayInitializer( (PsiArrayInitializerExpression) myParameterInitializer, initializerType); myParameterInitializer = (PsiExpression) myParameterInitializer.replace(newExprArrayInitializer); } myInitializerWrapper = new JavaExpressionWrapper(myParameterInitializer); // Changing external occurences (the tricky part) IntroduceParameterUtil.processUsages(usages, this); if (myGenerateDelegate) { generateDelegate(myMethodToReplaceIn); if (myMethodToReplaceIn != myMethodToSearchFor) { final PsiMethod method = generateDelegate(myMethodToSearchFor); if (method.getContainingClass().isInterface()) { final PsiCodeBlock block = method.getBody(); if (block != null) { block.delete(); } } } } // Changing signature of initial method // (signature of myMethodToReplaceIn will be either changed now or have already been changed) LOG.assertTrue(initializerType.isValid()); final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(myParameterName, myMethodToReplaceIn.getBody()); IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts( new UsageInfo(myMethodToReplaceIn), usages, this); if (myMethodToSearchFor != myMethodToReplaceIn) { IntroduceParameterUtil.changeMethodSignatureAndResolveFieldConflicts( new UsageInfo(myMethodToSearchFor), usages, this); } ChangeContextUtil.clearContextInfo(myParameterInitializer); // Replacing expression occurrences for (UsageInfo usage : usages) { if (usage instanceof ChangedMethodCallInfo) { PsiElement element = usage.getElement(); processChangedMethodCall(element); } else if (usage instanceof InternalUsageInfo) { PsiElement element = usage.getElement(); if (element instanceof PsiExpression) { element = RefactoringUtil.outermostParenthesizedExpression((PsiExpression) element); } if (element != null) { if (element.getParent() instanceof PsiExpressionStatement) { element.getParent().delete(); } else { PsiExpression newExpr = factory.createExpressionFromText(myParameterName, element); IntroduceVariableBase.replace((PsiExpression) element, newExpr, myProject); } } } } if (myLocalVariable != null && myRemoveLocalVariable) { myLocalVariable.normalizeDeclaration(); myLocalVariable.getParent().delete(); } fieldConflictsResolver.fix(); } catch (IncorrectOperationException ex) { LOG.error(ex); } }
private PsiMethod createMethodToAdd() { ChangeContextUtil.encodeContextInfo(myMethod, true); try { final PsiManager manager = myMethod.getManager(); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); // correct internal references final PsiCodeBlock body = myMethod.getBody(); if (body != null) { final Map<PsiElement, PsiElement> replaceMap = new HashMap<PsiElement, PsiElement>(); body.accept( new JavaRecursiveElementVisitor() { @Override public void visitThisExpression(PsiThisExpression expression) { final PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(expression); if (classReferencedByThis != null && !PsiTreeUtil.isAncestor(myMethod, classReferencedByThis, false)) { final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory(); String paramName = getParameterNameToCreate(classReferencedByThis); try { final PsiExpression refExpression = factory.createExpressionFromText(paramName, null); replaceMap.put(expression, refExpression); } catch (IncorrectOperationException e) { LOG.error(e); } } } @Override public void visitReferenceExpression(PsiReferenceExpression expression) { try { final PsiExpression qualifier = expression.getQualifierExpression(); final PsiElement resolved = expression.resolve(); if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) { if (resolved instanceof PsiField) { for (PsiParameter parameter : myMethod.getParameterList().getParameters()) { if (Comparing.strEqual( parameter.getName(), ((PsiField) resolved).getName())) { qualifier.replace(factory.createExpressionFromText("this", null)); return; } } } // Target is a field, replace target.m -> m qualifier.delete(); return; } if (myTargetVariable.equals(resolved)) { PsiThisExpression thisExpression = RefactoringChangeUtil.createThisExpression( manager, PsiTreeUtil.isAncestor( myMethod, PsiTreeUtil.getParentOfType(expression, PsiClass.class), true) ? myTargetClass : null); replaceMap.put(expression, thisExpression); return; } else if (myMethod.equals(resolved)) { } else { PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(expression); if (classReferencedByThis != null) { final String paramName = getParameterNameToCreate(classReferencedByThis); if (paramName != null) { PsiReferenceExpression newQualifier = (PsiReferenceExpression) factory.createExpressionFromText(paramName, null); expression.setQualifierExpression(newQualifier); return; } } } super.visitReferenceExpression(expression); } catch (IncorrectOperationException e) { LOG.error(e); } } @Override public void visitNewExpression(PsiNewExpression expression) { try { final PsiExpression qualifier = expression.getQualifier(); if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression) qualifier).isReferenceTo(myTargetVariable)) { // Target is a field, replace target.new A() -> new A() qualifier.delete(); } else { final PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(expression); if (classReferencedByThis != null) { if (qualifier != null) qualifier.delete(); final String paramName = getParameterNameToCreate(classReferencedByThis); final PsiExpression newExpression = factory.createExpressionFromText( paramName + "." + expression.getText(), null); replaceMap.put(expression, newExpression); } } super.visitNewExpression(expression); } catch (IncorrectOperationException e) { LOG.error(e); } } @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { correctMethodCall(expression, true); super.visitMethodCallExpression(expression); } }); for (PsiElement element : replaceMap.keySet()) { final PsiElement replacement = replaceMap.get(element); element.replace(replacement); } } final PsiMethod methodCopy = getPatternMethod(); final List<PsiParameter> newParameters = Arrays.asList(methodCopy.getParameterList().getParameters()); RefactoringUtil.fixJavadocsForParams(methodCopy, new HashSet<PsiParameter>(newParameters)); return methodCopy; } catch (IncorrectOperationException e) { LOG.error(e); return myMethod; } }
private void correctMethodCall( final PsiMethodCallExpression expression, final boolean isInternalCall) { try { final PsiManager manager = myMethod.getManager(); PsiReferenceExpression methodExpression = expression.getMethodExpression(); if (!methodExpression.isReferenceTo(myMethod)) return; final PsiExpression oldQualifier = methodExpression.getQualifierExpression(); PsiExpression newQualifier = null; final PsiClass classReferencedByThis = MoveInstanceMembersUtil.getClassReferencedByThis(methodExpression); if (myTargetVariable instanceof PsiParameter) { final int index = myMethod.getParameterList().getParameterIndex((PsiParameter) myTargetVariable); final PsiExpression[] arguments = expression.getArgumentList().getExpressions(); if (index < arguments.length) { newQualifier = (PsiExpression) arguments[index].copy(); arguments[index].delete(); } } else { VisibilityUtil.escalateVisibility((PsiField) myTargetVariable, expression); String newQualifierName = myTargetVariable.getName(); if (myTargetVariable instanceof PsiField && oldQualifier != null) { final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(oldQualifier.getType()); if (aClass == ((PsiField) myTargetVariable).getContainingClass()) { newQualifierName = oldQualifier.getText() + "." + newQualifierName; } } newQualifier = JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createExpressionFromText(newQualifierName, null); } PsiExpression newArgument = null; if (classReferencedByThis != null) { @NonNls String thisArgumentText = null; if (manager.areElementsEquivalent(myMethod.getContainingClass(), classReferencedByThis)) { if (myOldClassParameterNames.containsKey(myMethod.getContainingClass())) { thisArgumentText = "this"; } } else { thisArgumentText = classReferencedByThis.getName() + ".this"; } if (thisArgumentText != null) { newArgument = JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createExpressionFromText(thisArgumentText, null); } } else { if (!isInternalCall && oldQualifier != null) { final PsiType type = oldQualifier.getType(); if (type instanceof PsiClassType) { final PsiClass resolved = ((PsiClassType) type).resolve(); if (resolved != null && getParameterNameToCreate(resolved) != null) { newArgument = replaceRefsToTargetVariable( oldQualifier); // replace is needed in case old qualifier is e.g. the same as // field as target variable } } } } if (newArgument != null) { expression.getArgumentList().add(newArgument); } if (newQualifier != null) { if (newQualifier instanceof PsiThisExpression && ((PsiThisExpression) newQualifier).getQualifier() == null) { // Remove now redundant 'this' qualifier if (oldQualifier != null) oldQualifier.delete(); } else { final PsiReferenceExpression refExpr = (PsiReferenceExpression) JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createExpressionFromText("q." + myMethod.getName(), null); refExpr.getQualifierExpression().replace(newQualifier); methodExpression.replace(refExpr); } } } catch (IncorrectOperationException e) { LOG.error(e); } }