mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inline parameter: conflict if replacement would be inaccessible
This commit is contained in:
+104
-87
@@ -175,94 +175,18 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
|
||||
@Override
|
||||
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
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 Set<PsiVariable> vars = new HashSet<PsiVariable>();
|
||||
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<PsiElement, String> myConflicts;
|
||||
|
||||
public InaccessibleExpressionsDetector(MultiMap<PsiElement, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -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 <caret>pProject) {
|
||||
System.out.println(pProject);
|
||||
}
|
||||
|
||||
String project (boolean b) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user