From: anna Date: Fri, 12 Feb 2010 13:01:21 +0000 (+0300) Subject: inline parameter: conflict if replacement would be inaccessible X-Git-Tag: 94.297~9^2~1 X-Git-Url: https://repo.or.cz/w/fedora-idea.git/commitdiff_plain/8331adb1d7943ea442163b75dff01c5e9a6d26b4 inline parameter: conflict if replacement would be inaccessible --- diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java index 28d8ea1543..a360bedfcb 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java @@ -175,94 +175,18 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor @Override protected boolean preprocessUsages(Ref refUsages) { final MultiMap conflicts = new MultiMap(); - myInitializer.accept(new JavaRecursiveElementWalkingVisitor() { - @Override - public void visitReferenceExpression(final PsiReferenceExpression expression) { - super.visitReferenceExpression(expression); - final PsiElement element = expression.resolve(); - if (element instanceof PsiMember && !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) { - if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { - conflicts.putValue(expression, "Parameter initializer depends on " + RefactoringUIUtil.getDescription(element, false) + " which is not available inside the static method"); - } - } - if (element instanceof PsiMethod || element instanceof PsiField) { - if (!mySameClass && !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) { - conflicts.putValue(expression, "Parameter initializer depend on non static member from some other class"); - } else if (!PsiUtil.isAccessible((PsiMember)element, myMethod, null)) { - conflicts.putValue(expression, "Parameter initializer depends on value which is not available inside method"); - } - } else if (element instanceof PsiParameter) { - conflicts.putValue(expression, "Parameter initializer depends on callers parameter"); - } - } - - @Override - public void visitThisExpression(PsiThisExpression thisExpression) { - super.visitThisExpression(thisExpression); - final PsiJavaCodeReferenceElement qualifier = thisExpression.getQualifier(); - PsiElement containingClass; - if (qualifier != null) { - containingClass = qualifier.resolve(); - } - else { - containingClass = PsiTreeUtil.getParentOfType(myMethodCall, PsiClass.class); - } - final PsiClass methodContainingClass = myMethod.getContainingClass(); - LOG.assertTrue(methodContainingClass != null); - if (!PsiTreeUtil.isAncestor(containingClass, methodContainingClass, false)) { - conflicts.putValue(thisExpression, - "Parameter initializer depends on this which is not available inside the method and cannot be inlined"); - } else if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { - conflicts.putValue(thisExpression, "Parameter initializer depends on this which is not available inside the static method"); - } - } - - @Override - public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { - super.visitReferenceElement(reference); - if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { - final PsiElement resolved = reference.resolve(); - if (resolved instanceof PsiClass && !((PsiClass)resolved).hasModifierProperty(PsiModifier.STATIC)) { - conflicts.putValue(reference, "Parameter initializer depends on non static class which is not available inside static method"); - } - } - } - - @Override - public void visitNewExpression(PsiNewExpression expression) { - super.visitNewExpression(expression); - final PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference(); - if (reference != null) { - final PsiElement resolved = reference.resolve(); - if (resolved instanceof PsiClass) { - final PsiClass refClass = (PsiClass)resolved; - final String classUnavailableMessage = "Parameter initializer depends on " + - RefactoringUIUtil.getDescription(refClass, true) + - " which is not available inside method and cannot be inlined"; - if (!PsiUtil.isAccessible(refClass, myMethod, null)) { - conflicts.putValue(expression, classUnavailableMessage); - } - else { - final PsiClass methodContainingClass = myMethod.getContainingClass(); - LOG.assertTrue(methodContainingClass != null); - if (!PsiTreeUtil.isAncestor(myMethod, refClass, false)) { - PsiElement parent = refClass; - while ((parent = parent.getParent()) instanceof PsiClass) { - if (!PsiUtil.isAccessible((PsiClass)parent, myMethod, null)) { - break; - } - } - if (!(parent instanceof PsiFile)) { - conflicts.putValue(expression, classUnavailableMessage); - } - } - } - } + final UsageInfo[] usages = refUsages.get(); + final InaccessibleExpressionsDetector detector = new InaccessibleExpressionsDetector(conflicts); + myInitializer.accept(detector); + for (UsageInfo usage : usages) { + if (usage instanceof LocalReplacementUsageInfo) { + final PsiElement replacement = ((LocalReplacementUsageInfo)usage).getReplacement(); + if (replacement != null) { + replacement.accept(detector); } } - }); + } - final UsageInfo[] usages = refUsages.get(); final Set vars = new HashSet(); for (UsageInfo usageInfo : usages) { if (usageInfo instanceof LocalReplacementUsageInfo) { @@ -377,4 +301,97 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor return myVariable != null && myVariable.isValid() ? myVariable : null; } } + + private class InaccessibleExpressionsDetector extends JavaRecursiveElementWalkingVisitor { + private final MultiMap myConflicts; + + public InaccessibleExpressionsDetector(MultiMap conflicts) { + myConflicts = conflicts; + } + + @Override + public void visitReferenceExpression(final PsiReferenceExpression expression) { + super.visitReferenceExpression(expression); + final PsiElement element = expression.resolve(); + if (element instanceof PsiMember && !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) { + if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { + myConflicts.putValue(expression, "Parameter initializer depends on " + RefactoringUIUtil.getDescription(element, false) + " which is not available inside the static method"); + } + } + if (element instanceof PsiMethod || element instanceof PsiField) { + if (!mySameClass && !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) { + myConflicts.putValue(expression, "Parameter initializer depend on non static member from some other class"); + } else if (!PsiUtil.isAccessible((PsiMember)element, myMethod, null)) { + myConflicts.putValue(expression, "Parameter initializer depends on value which is not available inside method"); + } + } else if (element instanceof PsiParameter) { + myConflicts.putValue(expression, "Parameter initializer depends on callers parameter"); + } + } + + @Override + public void visitThisExpression(PsiThisExpression thisExpression) { + super.visitThisExpression(thisExpression); + final PsiJavaCodeReferenceElement qualifier = thisExpression.getQualifier(); + PsiElement containingClass; + if (qualifier != null) { + containingClass = qualifier.resolve(); + } + else { + containingClass = PsiTreeUtil.getParentOfType(myMethodCall, PsiClass.class); + } + final PsiClass methodContainingClass = myMethod.getContainingClass(); + LOG.assertTrue(methodContainingClass != null); + if (!PsiTreeUtil.isAncestor(containingClass, methodContainingClass, false)) { + myConflicts.putValue(thisExpression, + "Parameter initializer depends on this which is not available inside the method and cannot be inlined"); + } else if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { + myConflicts.putValue(thisExpression, "Parameter initializer depends on this which is not available inside the static method"); + } + } + + @Override + public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { + super.visitReferenceElement(reference); + if (myMethod.hasModifierProperty(PsiModifier.STATIC)) { + final PsiElement resolved = reference.resolve(); + if (resolved instanceof PsiClass && !((PsiClass)resolved).hasModifierProperty(PsiModifier.STATIC)) { + myConflicts.putValue(reference, "Parameter initializer depends on non static class which is not available inside static method"); + } + } + } + + @Override + public void visitNewExpression(PsiNewExpression expression) { + super.visitNewExpression(expression); + final PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference(); + if (reference != null) { + final PsiElement resolved = reference.resolve(); + if (resolved instanceof PsiClass) { + final PsiClass refClass = (PsiClass)resolved; + final String classUnavailableMessage = "Parameter initializer depends on " + + RefactoringUIUtil.getDescription(refClass, true) + + " which is not available inside method and cannot be inlined"; + if (!PsiUtil.isAccessible(refClass, myMethod, null)) { + myConflicts.putValue(expression, classUnavailableMessage); + } + else { + final PsiClass methodContainingClass = myMethod.getContainingClass(); + LOG.assertTrue(methodContainingClass != null); + if (!PsiTreeUtil.isAncestor(myMethod, refClass, false)) { + PsiElement parent = refClass; + while ((parent = parent.getParent()) instanceof PsiClass) { + if (!PsiUtil.isAccessible((PsiClass)parent, myMethod, null)) { + break; + } + } + if (!(parent instanceof PsiFile)) { + myConflicts.putValue(expression, classUnavailableMessage); + } + } + } + } + } + } + } } \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineParameter/RefCallerParameterInCallChain.java b/java/java-tests/testData/refactoring/inlineParameter/RefCallerParameterInCallChain.java new file mode 100644 index 0000000000..62dc4ced6d --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineParameter/RefCallerParameterInCallChain.java @@ -0,0 +1,21 @@ +class Foo { + void f(boolean b) { + String project = project(b); + if (b) { + barrrr(project.substring(0)); + } else { + if (true) { + barrrr(project.substring(0)); + } + } + + } + + private void barrrr(String pProject) { + System.out.println(pProject); + } + + String project (boolean b) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java index 1e3a7529b2..65a9b51890 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java @@ -237,6 +237,15 @@ public class InlineParameterTest extends LightCodeInsightTestCase { } } + public void testRefCallerParameterInCallChain() throws Exception { + try { + doTest(false); + } + catch (BaseRefactoringProcessor.ConflictsInTestsException e) { + assertEquals("Parameter initializer depends on callers parameter", e.getMessage()); + } + } + private void doTest(final boolean createLocal) throws Exception { getProject().putUserData(InlineParameterExpressionProcessor.CREATE_LOCAL_FOR_TESTS,createLocal);