From 13539bc26ee786500c639175d286a3137d7b0890 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Fri, 9 Aug 2013 12:54:57 +0400 Subject: [PATCH 1/2] CoreJavaFileManager.findClass: properly resolve $ in inner class names --- .../intellij/core/CoreJavaFileManager.java | 70 ++++++++---- .../intellij/psi/CoreJavaFileManagerTest.java | 103 +++++++++++++++++- 2 files changed, 146 insertions(+), 27 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java index 1df60969e17e..dd3904097351 100644 --- a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java +++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java @@ -26,10 +26,7 @@ import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author yole @@ -138,36 +135,48 @@ public class CoreJavaFileManager implements JavaFileManager { if (classes.length == 1) { PsiClass curClass = classes[0]; - if (bucks > 0) { - int newComponentStart = 0; - int lookupStart = 0; + if (bucks > 0) { + Stack currentPath = new Stack(); + currentPath.add(new ClassAndOffsets(curClass, 0, 0)); + currentPath.add(currentPath.peek()); - while (lookupStart <= className.length()) { - int b = className.indexOf("$", lookupStart); - b = b < 0 ? className.length(): b; + while (currentPath.size() > 1) { + ClassAndOffsets classAndOffset = currentPath.pop(); + int newComponentStart = classAndOffset.componentStart; + int lookupStart = classAndOffset.lookupStart; + curClass = currentPath.peek().clazz; //owner class - String component = className.substring(newComponentStart, b); - PsiClass inner = curClass.findInnerClassByName(component, false); + while (lookupStart <= className.length()) { + int bucksIndex = className.indexOf("$", lookupStart); + bucksIndex = bucksIndex < 0 ? className.length(): bucksIndex; - lookupStart = b + 1; - if (inner == null) { - continue; + String component = className.substring(newComponentStart, bucksIndex); + PsiClass inner = curClass.findInnerClassByName(component, false); + + lookupStart = bucksIndex + 1; + if (inner == null) { + continue; + } + + currentPath.add(new ClassAndOffsets(inner, newComponentStart, lookupStart)); + + newComponentStart = lookupStart; + curClass = inner; + } + + if (lookupStart == newComponentStart) { + return curClass; + } } - newComponentStart = lookupStart; - curClass = inner; - } - - if (lookupStart != newComponentStart) { return null; + + } else { + return curClass; } } - - - return curClass; } } - } return null; } @@ -196,4 +205,17 @@ public class CoreJavaFileManager implements JavaFileManager { public void addToClasspath(VirtualFile root) { myClasspath.add(root); } + + private static class ClassAndOffsets { + + final PsiClass clazz; + final int componentStart; + final int lookupStart; + + ClassAndOffsets(PsiClass clazz, int componentStart, int lookupStart) { + this.clazz = clazz; + this.componentStart = componentStart; + this.lookupStart = lookupStart; + } + } } diff --git a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java index 1cd630ccc2db..17be945bc4c1 100644 --- a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java @@ -22,26 +22,36 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.testFramework.PsiTestCase; import com.intellij.testFramework.PsiTestUtil; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + public class CoreJavaFileManagerTest extends PsiTestCase { - public void testNotNullInnerClass() throws Exception { + private VirtualFile prepareClasses(String clazzName, String clazzData) throws Exception { VirtualFile root = PsiTestUtil.createTestProjectStructure(myProject, myModule, myFilesToDelete); VirtualFile pkg = root.createChildDirectory(this, "foo"); PsiDirectory dir = myPsiManager.findDirectory(pkg); assertNotNull(dir); + PsiElement created = dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText(clazzName + ".java", JavaFileType.INSTANCE, clazzData)); + return root; + } + + public void testNotNullInnerClass() throws Exception { String text = "package foo;\n\n" + "public class Nested {\n" + "public class InnerGeneral {}\n" + - "public class Inner$ {}\n" + + "public class Inner$ {" + + "}\n" + "\n" + "public Inner$ inner() {\n" + " return new Inner$();\n" + "}\n" + "\n" + "}"; - PsiElement created = dir.add(PsiFileFactory.getInstance(getProject()).createFileFromText("Nested.java", JavaFileType.INSTANCE, text)); + VirtualFile root = prepareClasses("Nested", text); GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager); manager.addToClasspath(root); @@ -65,4 +75,91 @@ public class CoreJavaFileManagerTest extends PsiTestCase { assertNull(clazzInner$Wrong3); } + + public void testNotNullInnerClass2() throws Exception { + String text = "package foo;\n\n" + + "public class Nested {\n" + + + "public class Inner {" + + " public class XInner{}" + + " public class XInner${}" + + "}\n" + + "public class Inner$ {" + + " public class XInner{}" + + " public class XInner${}" + + "}\n" + + "\n" + + "}"; + + VirtualFile root = prepareClasses("Nested", text); + GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); + CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager); + manager.addToClasspath(root); + + PsiClass clazzInner = manager.findClass("foo.Nested.Inner", scope); + assertNotNull(clazzInner); + + PsiClass clazzXInner = manager.findClass("foo.Nested.Inner.XInner", scope); + assertNotNull(clazzXInner); + + PsiClass clazzXInner$ = manager.findClass("foo.Nested.Inner.XInner$", scope); + assertNotNull(clazzXInner$); + + PsiClass clazz$XInner = manager.findClass("foo.Nested.Inner$.XInner", scope); + assertNotNull(clazz$XInner); + + PsiClass clazz$XInner$ = manager.findClass("foo.Nested.Inner$.XInner$", scope); + assertNotNull(clazz$XInner$); + } + + + public void testNotNullInnerClass3() throws Exception { + String text = "package foo;\n\n" + + "public class NestedX {\n" + + + "public class XX {" + + " public class XXX{" + + " public class XXXX{ }" + + " public class XXXX${ }" + + " }" + + " public class XXX${" + + " public class XXXX{ }" + + " public class XXXX${ }" + + " }" + + "}\n" + + "public class XX$ {" + + " public class XXX{" + + " public class XXXX{ }" + + " public class XXXX${ }" + + " }" + + " public class XXX${" + + " public class XXXX{ }" + + " public class XXXX${ }" + + " }" + + "}\n" + + "\n" + + "}"; + + VirtualFile root = prepareClasses("NestedX", text); + GlobalSearchScope scope = GlobalSearchScope.allScope(getProject()); + CoreJavaFileManager manager = new CoreJavaFileManager(myPsiManager); + manager.addToClasspath(root); + + Queue queue = new LinkedList(); + queue.add("foo.NestedX"); + + while(!queue.isEmpty()) { + String head = queue.remove(); + PsiClass clazzInner = manager.findClass(head, scope); + assertNotNull(head, clazzInner); + System.out.println(head); + String lastSegment = head.substring(head.lastIndexOf('.')); + String xs = lastSegment.substring(lastSegment.indexOf("X")).replace("$", ""); + if (xs.length() < 4) { + queue.add(head + "." + xs + "X"); + queue.add(head + "." + xs + "X$"); + } + } + } + } From 857bfd57f67c125172adbcc0c20e3854144bcaa1 Mon Sep 17 00:00:00 2001 From: max-kammerer Date: Mon, 12 Aug 2013 15:14:50 +0400 Subject: [PATCH 2/2] Update CoreJavaFileManagerTest.java --- .../testSrc/com/intellij/psi/CoreJavaFileManagerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java index 17be945bc4c1..01365c2d1b5a 100644 --- a/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/CoreJavaFileManagerTest.java @@ -151,8 +151,7 @@ public class CoreJavaFileManagerTest extends PsiTestCase { while(!queue.isEmpty()) { String head = queue.remove(); PsiClass clazzInner = manager.findClass(head, scope); - assertNotNull(head, clazzInner); - System.out.println(head); + assertNotNull(head, clazzInner); String lastSegment = head.substring(head.lastIndexOf('.')); String xs = lastSegment.substring(lastSegment.indexOf("X")).replace("$", ""); if (xs.length() < 4) {