mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: Provide completion for nested class names in reflection API (IDEA-181545)
This commit is contained in:
+25
-9
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source.resolve.reference.impl;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PsiJavaElementPattern;
|
||||
import com.intellij.patterns.PsiJavaPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceSet;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -73,15 +75,7 @@ public class JavaReflectionReferenceContributor extends PsiReferenceContributor
|
||||
}
|
||||
});
|
||||
|
||||
registrar.registerReferenceProvider(CLASS_PATTERN, new JavaReflectionReferenceProvider() {
|
||||
@Override
|
||||
protected PsiReference[] getReferencesByMethod(@NotNull PsiLiteralExpression literalArgument,
|
||||
@NotNull PsiReferenceExpression methodReference,
|
||||
@NotNull ProcessingContext context) {
|
||||
|
||||
return new JavaClassReferenceProvider().getReferencesByElement(literalArgument, context);
|
||||
}
|
||||
});
|
||||
registrar.registerReferenceProvider(CLASS_PATTERN, new ReflectionClassNameReferenceProvider());
|
||||
|
||||
registrar.registerReferenceProvider(METHOD_HANDLE_PATTERN, new JavaLangInvokeHandleReference.JavaLangInvokeHandleReferenceProvider());
|
||||
|
||||
@@ -101,4 +95,26 @@ public class JavaReflectionReferenceContributor extends PsiReferenceContributor
|
||||
registrar.registerReferenceProvider(ATOMIC_NUMERIC_PATTERN, atomicProvider);
|
||||
registrar.registerReferenceProvider(ATOMIC_REFERENCE_PATTERN, atomicProvider);
|
||||
}
|
||||
|
||||
private static class ReflectionClassNameReferenceProvider extends JavaClassReferenceProvider {
|
||||
|
||||
ReflectionClassNameReferenceProvider() {
|
||||
setOption(JavaClassReferenceProvider.ALLOW_DOLLAR_NAMES, Boolean.TRUE);
|
||||
setOption(JavaClassReferenceProvider.JVM_FORMAT, Boolean.TRUE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByString(String str, @NotNull PsiElement position, int offsetInPosition) {
|
||||
if (StringUtil.isEmpty(str)) {
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
return new JavaClassReferenceSet(str, position, offsetInPosition, true, this) {
|
||||
@Override
|
||||
public boolean isAllowDollarInNames() {
|
||||
return true;
|
||||
}
|
||||
}.getAllReferences();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import foo.bar.*;
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
Class.forName("foo.bar.PublicClass.<caret>");
|
||||
Class.forName("foo.bar.PublicClass$<caret>");
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import foo.bar.*;
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
Class.forName("foo.bar.PublicClass$Nested<caret>");
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import foo.bar.*;
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
Class.forName("foo.bar.PublicClass$NestedClass");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import foo.bar.*;
|
||||
class Main {
|
||||
void foo() throws ReflectiveOperationException {
|
||||
Class.forName("foo.bar.PublicClass.NestedClass");
|
||||
Class.forName("foo.bar.PublicClass$NestedClass");
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -165,9 +165,17 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase
|
||||
doTest(0, "one", "two");
|
||||
}
|
||||
|
||||
public void testClassForNameNested() {
|
||||
public void testClassForNameNestedAutocomplete() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass { public static class NestedClass {} }");
|
||||
doTest(0, "NestedClass");
|
||||
doTest(-1, () -> assertNull("Auto-completed", myFixture.getLookupElementStrings()));
|
||||
}
|
||||
|
||||
public void testClassForNameNested() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass {" +
|
||||
" public static class NestedClass {}" +
|
||||
" public class InnerClass {}" +
|
||||
"}");
|
||||
doTest(1, "InnerClass", "NestedClass");
|
||||
}
|
||||
|
||||
public void testWithClassLoader() {
|
||||
|
||||
+13
-8
@@ -31,12 +31,12 @@ class JavaReflectionClassNavigationTest : JavaReflectionClassNavigationTestBase(
|
||||
|
||||
fun testPublicInnerClass() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass { public class PublicInnerClass {} }")
|
||||
doTest("foo.bar.PublicClass.PublicInnerClass")
|
||||
doTest("foo.bar.PublicClass\$PublicInnerClass")
|
||||
}
|
||||
|
||||
fun testPublicInnerClass2() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass { public class PublicInnerClass {} }")
|
||||
doTest("foo.bar.<caret>PublicClass.PublicInnerClass")
|
||||
doTest("foo.bar.<caret>PublicClass\$PublicInnerClass")
|
||||
}
|
||||
|
||||
fun testPackageLocalClass() {
|
||||
@@ -46,17 +46,22 @@ class JavaReflectionClassNavigationTest : JavaReflectionClassNavigationTestBase(
|
||||
|
||||
fun testPrivateInnerClass() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass { private class PrivateInnerClass {} }")
|
||||
doTest("foo.bar.PublicClass.PrivateInnerClass")
|
||||
doTest("foo.bar.PublicClass\$PrivateInnerClass")
|
||||
}
|
||||
|
||||
fun testPrivateInnerClass2() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass { private class PrivateInnerClass {} }")
|
||||
doTest("foo.bar.<caret>PublicClass.PrivateInnerClass")
|
||||
doTest("foo.bar.<caret>PublicClass\$PrivateInnerClass")
|
||||
}
|
||||
|
||||
fun testWithClassLoader() {
|
||||
myFixture.addClass("package foo.bar; public class PublicClass {}")
|
||||
doTest("foo.bar.<caret>PublicClass.PrivateInnerClass", { "Thread.currentThread().getContextClassLoader().loadClass(\"$it\")" })
|
||||
doTest("foo.bar.<caret>PublicClass\$PrivateInnerClass", { "Thread.currentThread().getContextClassLoader().loadClass(\"$it\")" })
|
||||
}
|
||||
|
||||
fun testNestedClassDefaultPackage() {
|
||||
myFixture.addClass("public class Outer { public static class Inner {} }")
|
||||
doTest("Outer\$Inner")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +78,11 @@ abstract class JavaReflectionClassNavigationTestBase : LightCodeInsightFixtureTe
|
||||
protected fun doTest(className: String, usageFormatter: (String) -> String = { "Class.forName(\"$it\")" }) {
|
||||
val caretPos = className.indexOf("<caret>")
|
||||
val atCaret: String
|
||||
var expectedName = className
|
||||
var expectedName = className.replace('$', '.')
|
||||
if (caretPos >= 0) {
|
||||
atCaret = className
|
||||
val dotPos = className.indexOf(".", caretPos + 1)
|
||||
if (dotPos >= 0) expectedName = className.substring(0, dotPos).replace("<caret>", "")
|
||||
val dotPos = expectedName.indexOf(".", caretPos + 1)
|
||||
if (dotPos >= 0) expectedName = expectedName.substring(0, dotPos).replace("<caret>", "")
|
||||
}
|
||||
else {
|
||||
atCaret = className + "<caret>"
|
||||
|
||||
Reference in New Issue
Block a user