lambda: stop at method if it's located inside lambda (IDEA-131087)

(cherry picked from commit 890ffa719208e467b1ba238d248dbbf102c71b76)
This commit is contained in:
Anna Kozlova
2014-10-10 12:36:42 +02:00
parent 74f5498b6b
commit b2a07e2eee
12 changed files with 114 additions and 63 deletions

View File

@@ -375,9 +375,9 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
public void visitReturnStatement(PsiReturnStatement statement) {
super.visitReturnStatement(statement);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(statement, PsiLambdaExpression.class);
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
if (method != null && (lambdaExpression == null || PsiTreeUtil.isAncestor(lambdaExpression, method, true))) {
final PsiElement psiElement = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class);
if (psiElement instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)psiElement;
final PsiType returnType = method.getReturnType();
if (returnType != null && returnType != PsiType.VOID) {
final PsiExpression returnValue = statement.getReturnValue();

View File

@@ -363,22 +363,26 @@ public class ExpectedTypesProvider {
final PsiMethod method;
final PsiType type;
final boolean tailTypeSemicolon;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(statement, PsiLambdaExpression.class);
if (lambdaExpression != null) {
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
final NavigatablePsiElement psiElement = PsiTreeUtil.getParentOfType(statement, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
final PsiType functionalInterfaceType = ((PsiLambdaExpression)psiElement).getFunctionalInterfaceType();
method = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
type = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
tailTypeSemicolon = LambdaHighlightingUtil.insertSemicolonAfter(lambdaExpression);
tailTypeSemicolon = LambdaHighlightingUtil.insertSemicolonAfter((PsiLambdaExpression)psiElement);
}
else {
method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
type = method != null ? method.getReturnType() : null;
else if (psiElement instanceof PsiMethod) {
method = (PsiMethod)psiElement;
type = method.getReturnType();
tailTypeSemicolon = true;
} else {
method = null;
type = null;
tailTypeSemicolon = true;
}
if (method != null) {
visitMethodReturnType(method, type, tailTypeSemicolon);
}
}
private void visitMethodReturnType(final PsiMethod scopeMethod, PsiType type, boolean tailTypeSemicolon) {

View File

@@ -60,14 +60,12 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction {
PsiElement targetElement = null;
PsiMethod targetMethod = null;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(myWrongElement, PsiLambdaExpression.class);
if (lambdaExpression != null) {
targetMethod = LambdaUtil.getFunctionalInterfaceMethod(lambdaExpression);
targetElement = lambdaExpression.getBody();
}
if (targetElement == null && targetMethod == null) {
targetMethod = PsiTreeUtil.getParentOfType(myWrongElement, PsiMethod.class);
final PsiElement psiElement = PsiTreeUtil.getParentOfType(myWrongElement, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
targetMethod = LambdaUtil.getFunctionalInterfaceMethod(psiElement);
targetElement = ((PsiLambdaExpression)psiElement).getBody();
} else if (psiElement instanceof PsiMethod) {
targetMethod = (PsiMethod)psiElement;
targetElement = targetMethod;
}
@@ -85,7 +83,8 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction {
final boolean processSuperMethods;
if (hasSuperMethodsWithoutExceptions && superMethods.length > 0) {
int result = Messages.showYesNoCancelDialog(
int result = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES :
Messages.showYesNoCancelDialog(
QuickFixBundle.message("add.exception.to.throws.inherited.method.warning.text", targetMethod.getName()),
QuickFixBundle.message("method.is.inherited.warning.title"),
Messages.getQuestionIcon());
@@ -184,16 +183,16 @@ public class AddExceptionToThrowsFix extends BaseIntentionAction {
PsiElement targetElement = null;
PsiMethod targetMethod = null;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(myWrongElement, PsiLambdaExpression.class);
if (lambdaExpression != null) {
targetMethod = LambdaUtil.getFunctionalInterfaceMethod(lambdaExpression);
targetElement = lambdaExpression.getBody();
final PsiElement psiElement = PsiTreeUtil.getParentOfType(myWrongElement, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
targetMethod = LambdaUtil.getFunctionalInterfaceMethod(psiElement);
targetElement = ((PsiLambdaExpression)psiElement).getBody();
}
else if (psiElement instanceof PsiMethod) {
targetMethod = (PsiMethod)psiElement;
targetElement = psiElement;
}
if (targetElement == null && targetMethod == null) {
targetMethod = PsiTreeUtil.getParentOfType(myWrongElement, PsiMethod.class);
targetElement = targetMethod;
}
if (targetElement == null || targetMethod == null || !targetMethod.getThrowsList().isPhysical()) return false;
List<PsiClassType> unhandled = getUnhandledExceptions(myWrongElement, targetElement, targetMethod);
if (unhandled == null || unhandled.isEmpty()) return false;

View File

@@ -107,15 +107,12 @@ public class StaticImportMethodFix implements IntentionAction {
}
}
else if (parent instanceof PsiReturnStatement) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
if (lambdaExpression != null) {
return LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression.getFunctionalInterfaceType());
final PsiElement psiElement = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)psiElement).getFunctionalInterfaceType());
}
else {
PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
if (method != null) {
return method.getReturnType();
}
else if (psiElement instanceof PsiMethod) {
return ((PsiMethod)psiElement).getReturnType();
}
}
else if (parent instanceof PsiExpressionList) {

View File

@@ -58,17 +58,14 @@ public class HighlightExitPointsHandler extends HighlightUsagesHandlerBase<PsiEl
if (!(parent instanceof PsiReturnStatement) && !(parent instanceof PsiThrowStatement)) return;
PsiCodeBlock body = null;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(myTarget, PsiLambdaExpression.class);
if (lambdaExpression != null) {
final PsiElement lambdaBody = lambdaExpression.getBody();
final PsiElement psiElement = PsiTreeUtil.getParentOfType(myTarget, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
final PsiElement lambdaBody = ((PsiLambdaExpression)psiElement).getBody();
if (lambdaBody instanceof PsiCodeBlock) {
body = (PsiCodeBlock)lambdaBody;
}
}
if (body == null) {
PsiMethod method = PsiTreeUtil.getParentOfType(myTarget, PsiMethod.class);
body = method != null ? method.getBody() : null;
} else if (psiElement instanceof PsiMethod) {
body = ((PsiMethod)psiElement).getBody();
}
if (body == null) return;

View File

@@ -69,9 +69,9 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler {
PsiElement element = getElement(file, offset);
if (element == null) return null;
final PsiExpression expression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class, PsiMethodReferenceExpression.class);
if (expression != null) {
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(expression);
final PsiElement psiElement = PsiTreeUtil.getParentOfType(element, PsiFunctionalExpression.class, PsiMember.class);
if (psiElement instanceof PsiFunctionalExpression) {
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(psiElement);
if (interfaceMethod != null) {
return ArrayUtil.prepend(interfaceMethod, interfaceMethod.findSuperMethods(false));
}

View File

@@ -60,7 +60,7 @@ public class LambdaUtil {
}
public static PsiMethod getFunctionalInterfaceMethod(@Nullable PsiElement element) {
if (element instanceof PsiLambdaExpression || element instanceof PsiMethodReferenceExpression) {
if (element instanceof PsiFunctionalExpression) {
final PsiType samType = element instanceof PsiLambdaExpression
? ((PsiLambdaExpression)element).getFunctionalInterfaceType()
: ((PsiMethodReferenceExpression)element).getFunctionalInterfaceType();
@@ -355,14 +355,11 @@ public class LambdaUtil {
}
}
else if (parent instanceof PsiReturnStatement) {
final PsiLambdaExpression gParent = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
if (gParent != null) {
return getFunctionalInterfaceTypeByContainingLambda(gParent);
} else {
final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
if (method != null) {
return method.getReturnType();
}
final PsiElement gParent = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, PsiMethod.class);
if (gParent instanceof PsiLambdaExpression) {
return getFunctionalInterfaceTypeByContainingLambda((PsiLambdaExpression)gParent);
} else if (gParent instanceof PsiMethod) {
return ((PsiMethod)gParent).getReturnType();
}
}
else if (parent instanceof PsiLambdaExpression) {

View File

@@ -208,15 +208,12 @@ public class PsiTypesUtil {
}
}
else if (parent instanceof PsiReturnStatement) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
if (lambdaExpression != null) {
final PsiElement psiElement = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, PsiMethod.class);
if (psiElement instanceof PsiLambdaExpression) {
return null;
}
else {
PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
if (method != null) {
return method.getReturnType();
}
else if (psiElement instanceof PsiMethod){
return ((PsiMethod)psiElement).getReturnType();
}
}
else if (PsiUtil.isCondition(methodCall, parent)) {

View File

@@ -0,0 +1,24 @@
import java.util.concurrent.Callable;
import java.util.stream.Stream;
import static java.util.Arrays.stream;
class Test {
public static Callable<Bar> foo(final String[] s) {
return () -> new Bar() {
@Override
public Stream<Number> baz() {
return zip(stream(s));
}
};
}
interface Bar {
Stream<Number> baz();
}
public static <L, O> Stream<O> zip(Stream<L> lefts) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
// "Add Exception to Method Signature" "true"
class C {
interface I {
void a() throws InterruptedException;
}
{
Callable<I> i = () -> {
return new I() {
public void a() throws InterruptedException {
Thread.sleep(2000);
}
};
};
}
}

View File

@@ -0,0 +1,16 @@
// "Add Exception to Method Signature" "true"
class C {
interface I {
void a();
}
{
Callable<I> i = () -> {
return new I() {
public void a() {
Thread.sl<caret>eep(2000);
}
};
};
}
}

View File

@@ -151,6 +151,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testExpectedReturnTypeInAnonymousInsideLambda() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}