convert lambda to anonymous: correct super qualifiers (IDEA-90854)

This commit is contained in:
Anna Kozlova
2012-09-03 18:27:51 +04:00
parent 01ed7837b9
commit 43ecd38a36
5 changed files with 155 additions and 2 deletions
@@ -28,12 +28,15 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.containers.HashMap;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ReplaceLambdaWithAnonymousIntention extends Intention {
@@ -67,8 +70,26 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention {
PsiCodeBlock blockFromText = psiElementFactory.createCodeBlockFromText(blockText, lambdaExpression);
ChangeContextUtil.encodeContextInfo(blockFromText, true);
PsiNewExpression newExpression = (PsiNewExpression)psiElementFactory.createExpressionFromText("new " + functionalInterfaceType.getCanonicalText() + "(){}", lambdaExpression);
PsiClass thisClass = PsiTreeUtil.getParentOfType(lambdaExpression, PsiClass.class, true);
ChangeContextUtil.decodeContextInfo(blockFromText, thisClass, RefactoringUtil.createThisExpression(lambdaExpression.getManager(), thisClass));
final PsiClass thisClass = PsiTreeUtil.getParentOfType(lambdaExpression, PsiClass.class, true);
final String thisClassName = thisClass.getName();
if (thisClassName != null) {
final PsiThisExpression thisAccessExpr = thisClass instanceof PsiAnonymousClass ? null : RefactoringUtil.createThisExpression(lambdaExpression.getManager(), thisClass);
ChangeContextUtil.decodeContextInfo(blockFromText, thisClass, thisAccessExpr);
final Map<PsiElement, PsiElement> replacements = new HashMap<PsiElement, PsiElement>();
blockFromText.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitSuperExpression(PsiSuperExpression expression) {
super.visitSuperExpression(expression);
if (expression.getQualifier() == null) {
replacements.put(expression, psiElementFactory.createExpressionFromText(thisClassName + "." + expression.getText(), expression));
}
}
});
for (PsiElement psiElement : replacements.keySet()) {
psiElement.replace(replacements.get(psiElement));
}
}
blockFromText = psiElementFactory.createCodeBlockFromText(blockFromText.getText(), null);
newExpression = (PsiNewExpression)lambdaExpression.replace(newExpression);
@@ -132,6 +153,24 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention {
public boolean satisfiedBy(PsiElement element) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
if (lambdaExpression != null && PsiTreeUtil.isAncestor(lambdaExpression.getParameterList(), element, false)) {
final PsiClass thisClass = PsiTreeUtil.getParentOfType(lambdaExpression, PsiClass.class, true);
if (thisClass == null || thisClass instanceof PsiAnonymousClass) {
final PsiElement body = lambdaExpression.getBody();
if (body == null) return false;
final boolean [] disabled = new boolean[1];
body.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitThisExpression(PsiThisExpression expression) {
disabled[0] = true;
}
@Override
public void visitSuperExpression(PsiSuperExpression expression) {
disabled[0] = true;
}
});
if (disabled[0]) return false;
}
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
return functionalInterfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null && LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType);
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Sample extends Super {
public static void main(String[] args) {
new Sample().bar();
}
public void bar() {
new Sample() {
{
new Thread((<caret>) -> {
System.out.println(this.getClass());
super.foo();
}).start();
}
};
}
}
class Super {
public void foo() {
System.out.println("Parent method is called");
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Sample extends Super {
public static void main(String[] args) {
new Sample().bar();
}
public void bar() {
new Thread((<caret>) -> {
System.out.println(this.getClass());
super.foo();
}).start();
}
}
class Super {
public void foo() {
System.out.println("Parent method is called");
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Sample extends Super {
public static void main(String[] args) {
new Sample().bar();
}
public void bar() {
new Thread(new Runnable() {
@Override
public void run() {
<selection>System.out.println(Sample.this.getClass());
Sample.super.foo();</selection>
}
}).start();
}
}
class Super {
public void foo() {
System.out.println("Parent method is called");
}
}
@@ -35,6 +35,10 @@ public class ReplaceLambdaWithAnonymousIntentionTest extends IPPTestCase {
doTest();
}
public void testSuperExpr() {
doTest();
}
public void testInsertFinal() {
doTest();
}
@@ -50,6 +54,10 @@ public class ReplaceLambdaWithAnonymousIntentionTest extends IPPTestCase {
public void testAmbiguity() {
assertIntentionNotAvailable();
}
public void testInsideAnonymous() {
assertIntentionNotAvailable();
}
public void testEffectivelyFinal() {
doTest();