From f4e3ab41cf78dd79c84c2bc83b96bd71619ce40a Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Wed, 28 May 2025 23:32:06 +0200 Subject: [PATCH] [java] Support inner class members in `JavaLangClassMemberReference` #IDEA-373584 Fixed GitOrigin-RevId: b9a2862766d62df666202694fa0be39d2625777c --- .../impl/JavaLangClassMemberReference.java | 24 +++++++++++++++---- .../ConstructorInnerClass.java | 14 +++++++++++ .../ConstructorLocalClass.java | 14 +++++++++++ .../JavaReflectionMemberAccessTest.kt | 18 +++----------- 4 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorInnerClass.java create mode 100644 java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorLocalClass.java diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java index 5b2b6db45d18..577cc3e17408 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.psi.impl.source.resolve.reference.impl; import com.intellij.codeInsight.completion.InsertHandler; @@ -6,6 +6,7 @@ import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.completion.JavaLookupElementBuilder; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInspection.reference.PsiMemberReference; +import com.intellij.lang.jvm.JvmModifier; import com.intellij.psi.*; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiTreeUtil; @@ -183,18 +184,31 @@ public class JavaLangClassMemberReference extends PsiReferenceBase argumentTypes) { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - if (parameters.length != argumentTypes.size()) { + // Get nested classes because they need to be passed if not static + List enclosingClasses = PsiTreeUtil.collectParents(method, PsiClass.class, false, parent -> { + return parent instanceof PsiFile || parent instanceof PsiClass cls && cls.hasModifier(JvmModifier.STATIC); + }); + if (!enclosingClasses.isEmpty()) { + // the containing class of the method doesn't need to be passed + enclosingClasses = ContainerUtil.reverse(enclosingClasses).subList(0, enclosingClasses.size() - 1); + } + final List containingClassTypes = ContainerUtil.map( + enclosingClasses, cls -> JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createType(cls) + ); + final List methodParamTypes = ContainerUtil.map(method.getParameterList().getParameters(), p -> p.getType()); + final List allTypes = ContainerUtil.concat(containingClassTypes, methodParamTypes); + + if (allTypes.size() != argumentTypes.size()) { return -1; } int mismatchCount = 0; - for (int i = 0; i < parameters.length; i++) { + for (int i = 0; i < allTypes.size(); i++) { final ReflectiveType argumentType = argumentTypes.get(i); if (argumentType == null) { mismatchCount++; continue; } - if (!argumentType.isEqualTo(parameters[i].getType())) { + if (!argumentType.isEqualTo(allTypes.get(i))) { return -1; } } diff --git a/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorInnerClass.java b/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorInnerClass.java new file mode 100644 index 000000000000..29157ade0ada --- /dev/null +++ b/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorInnerClass.java @@ -0,0 +1,14 @@ +class Constructors { + class X { + X() {} + X(String a) {} + } + + public void testConstructor() throws Exception { + X.class.getDeclaredConstructor(); + X.class.getDeclaredConstructor(String.class); + + X.class.getDeclaredConstructor(Constructors.class); + X.class.getDeclaredConstructor(Constructors.class, String.class); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorLocalClass.java b/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorLocalClass.java new file mode 100644 index 000000000000..c4d48c1fd3ca --- /dev/null +++ b/java/java-tests/testData/inspection/javaReflectionMemberAccess/ConstructorLocalClass.java @@ -0,0 +1,14 @@ +class Constructors { + public void testConstructor() throws Exception { + class X { + X() {} + X(String a) {} + } + + X.class.getDeclaredConstructor(); + X.class.getDeclaredConstructor(String.class); + + X.class.getDeclaredConstructor(Constructors.class); + X.class.getDeclaredConstructor(Constructors.class, String.class); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaReflectionMemberAccessTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaReflectionMemberAccessTest.kt index 1c554c34d2d2..ad64a4f26041 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaReflectionMemberAccessTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaReflectionMemberAccessTest.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.codeInspection import com.intellij.JavaTestUtil @@ -40,6 +26,8 @@ class JavaReflectionMemberAccessTest : LightJavaCodeInsightFixtureTestCase() { fun testFieldExists() = doTest(true) fun testMethodExists() = doTest(true) fun testConstructorExists() = doTest(true) + fun testConstructorInnerClass() = doTest(true) + fun testConstructorLocalClass() = doTest(true) fun testNewInstance() = doTest(true) fun testBugs() = doTest(true)