mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-158821 - added an edge between refFrom and lambda/method ref parameters where it's needed
GitOrigin-RevId: 946c0073473e6a5f68da422518cdc137f9224601
This commit is contained in:
committed by
intellij-monorepo-bot
parent
064b127d6b
commit
1b4c297f74
+38
-9
@@ -157,18 +157,20 @@ public class RefJavaUtilImpl extends RefJavaUtil {
|
||||
@Override
|
||||
public boolean visitCallableReferenceExpression(@NotNull UCallableReferenceExpression node) {
|
||||
visitReferenceExpression(node);
|
||||
processFunctionalExpression(node, getFunctionalInterfaceType(node));
|
||||
markParametersReferenced(node);
|
||||
// todo doesn't work for kotlin
|
||||
PsiType interfaceType = getFunctionalInterfaceType(node);
|
||||
processFunctionalExpression(node, interfaceType);
|
||||
markParametersReferenced(node, interfaceType);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void markParametersReferenced(@NotNull UCallableReferenceExpression node) {
|
||||
PsiElement resolved = node.resolve();
|
||||
if (resolved == null) return;
|
||||
RefElement refElement = refFrom.getRefManager().getReference(resolved);
|
||||
if (refElement instanceof RefMethod) {
|
||||
for (RefParameter parameter : ((RefMethod)refElement).getParameters()) {
|
||||
refFrom.addReference(parameter, parameter.getPsiElement(), decl, false, true, node);
|
||||
private void markParametersReferenced(@NotNull UCallableReferenceExpression node, @Nullable PsiType type) {
|
||||
PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(type);
|
||||
if (method == null) return;
|
||||
for (PsiParameter param : method.getParameterList().getParameters()) {
|
||||
RefElement paramRef = refFrom.getRefManager().getReference(param);
|
||||
if (paramRef != null) {
|
||||
refFrom.addReference(paramRef, param, decl, false, true, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,6 +247,13 @@ public class RefJavaUtilImpl extends RefJavaUtil {
|
||||
//TODO support kotlin
|
||||
addClassReferenceForStaticImport(node, (PsiMember)psiResolved, refFrom, decl);
|
||||
}
|
||||
else {
|
||||
// todo currently if psiResolved is KtParameter, it doesn't convert to UParameter, that seems wrong
|
||||
UParameter uParam = UastContextKt.toUElement(psiResolved, UParameter.class);
|
||||
if (uParam != null) {
|
||||
addReferenceToLambdaParameter(uParam, psiResolved, decl, refFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -367,6 +376,26 @@ public class RefJavaUtilImpl extends RefJavaUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addReferenceToLambdaParameter(@NotNull UParameter uParam, @NotNull PsiElement param, @NotNull UDeclaration decl,
|
||||
@NotNull RefJavaElementImpl refFrom) {
|
||||
ULambdaExpression lambda = UastUtils.getParentOfType(uParam, ULambdaExpression.class);
|
||||
if (lambda == null) return;
|
||||
int paramIndex = -1;
|
||||
List<UParameter> lambdaParams = lambda.getParameters();
|
||||
for (int i = 0; i < lambdaParams.size(); i++) {
|
||||
if (lambdaParams.get(i).equals(uParam)) {
|
||||
paramIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (paramIndex == -1) return;
|
||||
RefElement method = refFrom.getRefManager().getReference(LambdaUtil.getFunctionalInterfaceMethod(lambda.getFunctionalInterfaceType()));
|
||||
if (method instanceof RefMethod) {
|
||||
RefParameter[] methodParams = ((RefMethod)method).getParameters();
|
||||
refFrom.addReference(methodParams[paramIndex], param, decl, false, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addClassReferenceForStaticImport(UExpression node,
|
||||
PsiMember psiResolved,
|
||||
RefJavaElementImpl refFrom, UDeclaration decl) {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Parameter 'j' is not used in either this method or any of its derived methods</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,17 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth((i, j) -> System.out.println(i + 1));
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123, 456);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>17</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>17</line>
|
||||
<description>Parameter 'i' is not used in either this method or any of its derived methods</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth(new Child() {
|
||||
@java.lang.Override
|
||||
public void execute(int i) {
|
||||
System.out.println(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Parameter 'i' is not used in either this method or any of its derived methods</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Parameter 'j' is not used in either this method or any of its derived methods</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,17 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth((i, j) -> System.out.println(1));
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123, 456);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>16</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>16</line>
|
||||
<description>Parameter 'i' is not used in either this method or any of its derived methods</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth(k -> doSmth(i -> test(1)));
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123);
|
||||
}
|
||||
|
||||
static void test(int i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>17</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth(new Child() {
|
||||
@java.lang.Override
|
||||
public void execute(int i) {
|
||||
System.out.println(i + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,17 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth((i, j) -> System.out.println(i + j));
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123, 456);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i, int j);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>12</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1,17 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth(System.out::println);
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>16</line>
|
||||
<description>Method is never used as a member of this interface, but only as a member of the implementation class(es). The project will stay compilable if the method is removed from the interface.</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
public class Clazz {
|
||||
public static void main(String[] args) {
|
||||
doSmth(k -> doSmth(i -> test(i + 1)));
|
||||
}
|
||||
|
||||
static void doSmth(Child child) {
|
||||
child.execute(123);
|
||||
}
|
||||
|
||||
static void test(int i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
|
||||
interface Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
|
||||
interface Child extends Parent {
|
||||
void execute(int i);
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInspection;
|
||||
|
||||
public class UnusedParameterDeclarationTest extends AbstractUnusedDeclarationTest {
|
||||
|
||||
public void testParameterUsedInLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterUsedInNestedLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testOnlyParameterUsedInLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterNotUsedInLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterNotUsedInNestedLambda() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterUsedInMethodRef() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterUsedInAnonymousClass() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testParameterNotUsedInAnonymousClass() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTest() {
|
||||
doTest("deadCode/" + getTestName(true), myToolWrapper);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user