diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java index 161f4d8e6e6c..61e77ded09d2 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java @@ -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 replacements = new HashMap(); + 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); } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/InsideAnonymous.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/InsideAnonymous.java new file mode 100644 index 000000000000..988fb0adbd35 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/InsideAnonymous.java @@ -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(() -> { + System.out.println(this.getClass()); + super.foo(); + }).start(); + } + }; + } +} + +class Super { + public void foo() { + System.out.println("Parent method is called"); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr.java new file mode 100644 index 000000000000..44f56af1fac7 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr.java @@ -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(() -> { + System.out.println(this.getClass()); + super.foo(); + }).start(); + } +} + +class Super { + public void foo() { + System.out.println("Parent method is called"); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr_after.java new file mode 100644 index 000000000000..337e7ac8aa7f --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/SuperExpr_after.java @@ -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() { + System.out.println(Sample.this.getClass()); + Sample.super.foo(); + } + }).start(); + } +} + +class Super { + public void foo() { + System.out.println("Parent method is called"); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java index 1196dec5ec95..09f7f4464be9 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java @@ -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();