From d181c17d2b23b4785ca3dc56c9d06bcaaf88cb61 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Wed, 29 May 2019 18:03:05 -0400 Subject: [PATCH] PT #166343444: Type hierarchy for anonymous inner types --- .../commons/test/JavaLangugeClientTest.java | 21 +++++++++++++++++++ .../src/main/java/org/test/Application.java | 7 +++++++ .../tooling/jdt/ls/commons/java/JavaData.java | 15 +++++++++++-- .../jdt/ls/commons/java/TypeHierarchy.java | 11 +++++----- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java index 977fbf8eb..b7a3080a5 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java @@ -182,6 +182,27 @@ public class JavaLangugeClientTest { assertEquals(expected, actual); } + @Test + public void anonymousInnerType_SuperTypes() throws Exception { + List data = client + .javaSuperTypes(new JavaTypeHierarchyParams(project.getLocationURI().toString(), "org.test.Application$1", false)) + .get(1000000000, TimeUnit.SECONDS); + assertNotNull(data); + Set actual = data.stream().map(t -> t.getFqName()).collect(Collectors.toSet()); + Set expected = new HashSet<>(Arrays.asList( + "org.springframework.scheduling.concurrent.ConcurrentTaskScheduler", + "java.util.concurrent.Executor", + "org.springframework.scheduling.SchedulingTaskExecutor", + "org.springframework.core.task.AsyncTaskExecutor", + "org.springframework.scheduling.concurrent.ConcurrentTaskExecutor", + "org.springframework.scheduling.TaskScheduler", + "org.springframework.core.task.TaskExecutor", + "org.springframework.core.task.AsyncListenableTaskExecutor", + "java.lang.Object" + )); + assertEquals(expected, actual); + } + @Test public void arrayList_SuperTypes_with_Itself() throws Exception { List data = client diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/test-projects/test-webflux-project/src/main/java/org/test/Application.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/test-projects/test-webflux-project/src/main/java/org/test/Application.java index bf2f6762a..37454ed6d 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/test-projects/test-webflux-project/src/main/java/org/test/Application.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/test-projects/test-webflux-project/src/main/java/org/test/Application.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; @SpringBootApplication public class Application { @@ -13,5 +14,11 @@ public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } + + ConcurrentTaskScheduler sched() { + return new ConcurrentTaskScheduler() { + + }; + } } diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaData.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaData.java index 86e50b874..f633e5f45 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaData.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaData.java @@ -90,7 +90,7 @@ public class JavaData { return element; } - private static IJavaElement findElement(IJavaProject project, String bindingKey) { + public static IJavaElement findElement(IJavaProject project, String bindingKey) { IJavaElement element = null; // JDT cannot find anonymous inner type from its binding key // Find its declaring type. If declaring type found then anonymous inner type is present in the binding key @@ -119,6 +119,17 @@ public class JavaData { return element; } + public static String toBindingKey(String fqName) { + StringBuilder sb = new StringBuilder("L"); + sb.append(fqName.replace('.', '/')); + sb.append(";"); + return sb.toString(); + } + + public static String toJdtFqName(String bindingKey) { + return bindingKey.substring(1, bindingKey.length() - 1).replace('/', '.').replace('$', '.'); + } + private static IJavaElement findInnerElement(IJavaElement container, String bindingKey) { if (container instanceof IField) { if (bindingKey.equals(((IField)container).getKey())) { @@ -156,7 +167,7 @@ public class JavaData { if (rest.charAt(rest.length() - 1) == ';') { rest = rest.substring(0, rest.length() - 1); } - String[] tokens = rest.split("$"); + String[] tokens = rest.split("\\$"); for (String token : tokens) { int dotIdx = token.indexOf('.'); String typeToken = dotIdx < 0 ? token : token.substring(0, dotIdx); diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeHierarchy.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeHierarchy.java index e43b306df..faa939346 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeHierarchy.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeHierarchy.java @@ -33,15 +33,13 @@ public class TypeHierarchy { this.javaData = javaData; } - private static String jdtCompatibleFqName(String fqName) { - return fqName.replace('$', '.'); - } - private ITypeHierarchy hierarchy(URI projectUri, String fqName, boolean superTypes) { try { + String bindingKey = JavaData.toBindingKey(fqName); if (projectUri == null) { for (IJavaProject jp : ResourceUtils.allJavaProjects()) { - IType type = jp.findType(jdtCompatibleFqName(fqName)); + // In case it's an anonymous inner type try the following rather than just find type on the project + IType type = (IType) JavaData.findElement(jp, bindingKey); if (type != null) { return superTypes ? type.newSupertypeHierarchy(new NullProgressMonitor()) : type.newTypeHierarchy(new NullProgressMonitor()); } @@ -50,7 +48,8 @@ public class TypeHierarchy { } else { IJavaProject javaProject = projectUri == null ? null : ResourceUtils.getJavaProject(projectUri); if (javaProject != null) { - IType type = javaProject.findType(jdtCompatibleFqName(fqName)); + // In case it's an anonymous inner type try the following rather than just find type on the project + IType type = (IType) JavaData.findElement(javaProject, bindingKey); if (type != null) { return superTypes ? type.newSupertypeHierarchy(new NullProgressMonitor()) : type.newTypeHierarchy(javaProject, new NullProgressMonitor()); }