/* * Copyright 2000-2013 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. */ package com.intellij.codeInsight.daemon.lambda; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; public class PsiPolyExpressionUtilTest extends LightCodeInsightFixtureTestCase { public void testPrefixExpression() throws Exception { final PsiExpression psiExpression = findExpression(" int j = i++;"); assertInstanceOf(psiExpression, PsiPostfixExpression.class); assertTrue(PsiPolyExpressionUtil.hasStandaloneForm(psiExpression)); assertFalse(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testNumericConditionExpression() throws Exception { final PsiExpression psiExpression = findExpression(" int j = i == 0 ? i + 1 : i - 1;"); assertInstanceOf(psiExpression, PsiConditionalExpression.class); assertFalse(PsiPolyExpressionUtil.hasStandaloneForm(psiExpression)); assertFalse(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testPolyConditionExpression() throws Exception { myFixture.configureByText("Foo.java", "import java.util.*;" + "class Foo {" + " String foo(int i) {" + " return i == 0 ? bar() : bar();" + " }" + " String bar() {return null;}" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiConditionalExpression.class); assertFalse(PsiPolyExpressionUtil.hasStandaloneForm(psiExpression)); assertTrue(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testNewExpressionDiamond() throws Exception { final PsiExpression psiExpression = findExpression(" List l = new ArrayList<>();"); assertInstanceOf(psiExpression, PsiNewExpression.class); assertFalse(PsiPolyExpressionUtil.hasStandaloneForm(psiExpression)); assertTrue(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testNewExpression() throws Exception { final PsiExpression psiExpression = findExpression(" List l = new ArrayList();"); assertInstanceOf(psiExpression, PsiNewExpression.class); assertFalse(PsiPolyExpressionUtil.hasStandaloneForm(psiExpression)); assertFalse(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testMethodCallInsideArrayCreation() throws Exception { myFixture.configureByText("Foo.java", "import java.util.*;" + "class Foo {" + " T bar() {return null;}" + " void foo() {" + " String[] a = new String[] {bar()};" + " }" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiMethodCallExpression.class); assertInstanceOf(psiExpression, PsiMethodCallExpression.class); assertTrue(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testConditional() throws Exception { myFixture.configureByText("Foo.java", "import java.util.function.Supplier;" + "class Foo {" + " private static void map(Supplier fn) {}\n" + " public static void main(String[] args) {\n" + " Runnable r = null;\n" + " map(() -> (true ? r : r));\n" + " }" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiConditionalExpression.class); assertTrue(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } public void testConditionalInAssignment() throws Exception { myFixture.configureByText("Foo.java", "class Foo {" + " public static void main(String[] args) {\n" + " Object obj = new Object();\n" + " String str = \"\";\n" + " str += args.length == 0 ? obj : args[0];\n" + " }" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiConditionalExpression.class); assertFalse(PsiPolyExpressionUtil.isPolyExpression(psiExpression)); } private PsiExpression findExpression(String textWithExpression) { myFixture.configureByText("Foo.java", "import java.util.*;" + "class Foo {" + " void foo(int i) {" + textWithExpression + " }" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); return PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); } public void testPertinentLambdaExpression() throws Exception { assertFalse(doTestLambdaPertinent(" void bar(List l) {" + " foo(() -> {}, l);" + " }")); } public void testPertinentImplicitLambdaExpression() throws Exception { assertFalse(doTestLambdaPertinent(" void bar(List> l) {" + " foo((String s) -> 1, l);" + " }")); } public void testPertinentNestedLambdaExpression() throws Exception { assertFalse(doTestLambdaPertinent(" interface Fun { O inOut(I i);}\n" + " void bar(List>> l) {" + " foo((sIn, sOut) -> (sInInner, sOutInner) -> sOutInner, l);" + " }")); } public void testPertinentNestedLambdaExpressionWhenTargetIsTypeParameterOfMethod() throws Exception { myFixture.configureByText("Foo.java", "interface Supplier { T get();}" + "class Foo {" + " { Supplier x = foo (() -> () -> {});}\n" + " static Supplier foo(Supplier delegate) {\n" + " return null;\n" + " }\n" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiLambdaExpression.class); final PsiClass aClass = myFixture.findClass("Foo"); assertNotNull(aClass); final PsiMethod[] meths = aClass.findMethodsByName("foo", false); assertTrue(meths.length == 1); assertFalse(InferenceSession.isPertinentToApplicability(psiExpression, meths[0])); } public void testNotExactMethodReferenceOnRawClassType() throws Exception { myFixture.configureByText("Foo.java", "class Foo {" + " class Test{ Test(){}}" + " {Runnable r = Test::new;}" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiMethodReferenceExpression.class); assertFalse(((PsiMethodReferenceExpression)psiExpression).isExact()); } public void testExactMethodReferenceOnGenericClassType() throws Exception { myFixture.configureByText("Foo.java", "class Foo {" + " class Test{ Test(){}}" + " {Runnable r = Test::new;}" + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiMethodReferenceExpression.class); assertTrue(((PsiMethodReferenceExpression)psiExpression).isExact()); } private boolean doTestLambdaPertinent(final String barText) { myFixture.configureByText("Foo.java", "import java.util.*;" + "class Foo {" + " T foo(T t, List lT) {" + " }" + barText + "}"); final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getCaretOffset()); assertNotNull(elementAtCaret); final PsiExpression psiExpression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); assertInstanceOf(psiExpression, PsiLambdaExpression.class); final PsiClass aClass = myFixture.findClass("Foo"); assertNotNull(aClass); final PsiMethod[] meths = aClass.findMethodsByName("foo", false); assertTrue(meths.length == 1); return InferenceSession.isPertinentToApplicability(psiExpression, meths[0]); } }