diff --git a/java/java-tests/testData/fileStructure/filtering/AnonymousType.java b/java/java-tests/testData/fileStructure/filtering/AnonymousType.java new file mode 100644 index 000000000000..21731dad4435 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/AnonymousType.java @@ -0,0 +1,8 @@ +import java.awt.*; + +class AnonymousType { + int num; + void foo() { + new java.awt.Point(){}; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/AnonymousType.tree b/java/java-tests/testData/fileStructure/filtering/AnonymousType.tree new file mode 100644 index 000000000000..6c7561fb2434 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/AnonymousType.tree @@ -0,0 +1,4 @@ +-AnonymousType.java + -AnonymousType + -foo():void + [$1] \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/Camel.java b/java/java-tests/testData/fileStructure/filtering/Camel.java new file mode 100644 index 000000000000..c0794f73c365 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Camel.java @@ -0,0 +1,7 @@ +class Camel { + void doSomething(){} + void doSomethingWith(){} + void doSomethingWithMyHead(){} + void getSomeHead(){} + void getSomeArtHeader(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/Camel.tree b/java/java-tests/testData/fileStructure/filtering/Camel.tree new file mode 100644 index 000000000000..0abeed943e4c --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Camel.tree @@ -0,0 +1,3 @@ +-Camel.java + -Camel + [getSomeHead():void] \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/Camel2.java b/java/java-tests/testData/fileStructure/filtering/Camel2.java new file mode 100644 index 000000000000..a30da131306b --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Camel2.java @@ -0,0 +1,7 @@ +class Camel2 { + void doSomething(){} + void doSomethingWith(){} + void doSomethingWithMyHead(){} + void doSomeHead(){} + void doSomeArtHeader(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/Camel2.tree b/java/java-tests/testData/fileStructure/filtering/Camel2.tree new file mode 100644 index 000000000000..f909604690a3 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Camel2.tree @@ -0,0 +1,5 @@ +-Camel2.java + -Camel2 + doSomeArtHeader():void + [doSomeHead():void] + doSomethingWithMyHead():void \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/ReturnValue.java b/java/java-tests/testData/fileStructure/filtering/ReturnValue.java new file mode 100644 index 000000000000..d99fd724d710 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/ReturnValue.java @@ -0,0 +1,10 @@ +import java.awt.*; + +class ReturnValue { + void aaa(){} + Point getLocationOnScreen(){} + Point getPoint(){} + void fff2(){} + void fff3(){} + void fff4(){} +} \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/ReturnValue.tree b/java/java-tests/testData/fileStructure/filtering/ReturnValue.tree new file mode 100644 index 000000000000..f8bfa0909339 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/ReturnValue.tree @@ -0,0 +1,4 @@ +-ReturnValue.java + -ReturnValue + getLocationOnScreen():Point + [getPoint():Point] \ No newline at end of file diff --git a/java/java-tests/testData/fileStructure/filtering/Simple.java b/java/java-tests/testData/fileStructure/filtering/Simple.java new file mode 100644 index 000000000000..24a62e978d61 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Simple.java @@ -0,0 +1,8 @@ +class Simple { + void aaa(){} + void bbb(){} + void fff(){} + void fff2(){} + void fff3(){} + void fff4(){} +} diff --git a/java/java-tests/testData/fileStructure/filtering/Simple.tree b/java/java-tests/testData/fileStructure/filtering/Simple.tree new file mode 100644 index 000000000000..c2c6413dd7b5 --- /dev/null +++ b/java/java-tests/testData/fileStructure/filtering/Simple.tree @@ -0,0 +1,6 @@ +-Simple.java + -Simple + [fff():void] + fff2():void + fff3():void + fff4():void diff --git a/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java new file mode 100644 index 000000000000..848828f915b6 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureFilteringTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2012 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. + */ +package com.intellij.ide.fileStructure; + +/** + * @author Konstantin Bulenkov + */ +public class JavaFileStructureFilteringTest extends JavaFileStructureTestCase { + @Override + protected String getTestDataFolderName() { + return "filtering"; + } + + public void testSimple()throws Exception{checkTree("f");} + public void testReturnValue()throws Exception{checkTree("point");} + public void testAnonymousType()throws Exception{checkTree("point");} + public void testCamel()throws Exception{checkTree("sohe");} + public void testCamel2()throws Exception{checkTree("soHe");} + +} diff --git a/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureTestCase.java b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureTestCase.java index c3559b0370f3..f5c6da4031cc 100644 --- a/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureTestCase.java +++ b/java/java-tests/testSrc/com/intellij/ide/fileStructure/JavaFileStructureTestCase.java @@ -20,6 +20,7 @@ import com.intellij.ide.structureView.impl.java.JavaAnonymousClassesNodeProvider import com.intellij.ide.util.FileStructurePopup; import com.intellij.ide.util.PropertiesComponent; import com.intellij.testFramework.FileStructureTestBase; +import com.intellij.testFramework.IdeaTestCase; /** * @author Konstantin Bulenkov @@ -27,6 +28,10 @@ import com.intellij.testFramework.FileStructureTestBase; public abstract class JavaFileStructureTestCase extends FileStructureTestBase { private boolean myShowAnonymousByDefault; + protected JavaFileStructureTestCase() { + IdeaTestCase.initPlatformPrefix(); + } + protected abstract String getTestDataFolderName(); @Override diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 3238ffc635d0..58ecff594a9c 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -179,132 +179,7 @@ public class FileStructurePopup implements Disposable { myTree.setRootVisible(false); myTree.setShowsRootHandles(true); - mySpeedSearch = new TreeSpeedSearch(myTree, new Convertor() { - @Nullable - public String convert(TreePath path) { - final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); - final Object userObject = node.getUserObject(); - if (userObject instanceof FilteringTreeStructure.FilteringNode) { - return getText(((FilteringTreeStructure.FilteringNode)userObject).getDelegate()); - } - return ""; - } - }, true) { - @Override - protected Point getComponentLocationOnScreen() { - return myPopup.getContent().getLocationOnScreen(); - } - - @Override - protected Rectangle getComponentVisibleRect() { - return myPopup.getContent().getVisibleRect(); - } - - @Override - protected Object findElement(String s) { - List elements = new ArrayList(); - s = s.trim(); - final ListIterator it = getElementIterator(0); - while (it.hasNext()) { - final ObjectWithWeight o = new ObjectWithWeight(it.next(), s, getComparator()); - if (!o.weights.isEmpty()) { - elements.add(o); - } - } - ObjectWithWeight cur = null; - ArrayList current = new ArrayList(); - for (ObjectWithWeight element : elements) { - if (cur == null) { - cur = element; - current.add(cur); - continue; - } - - final int i = element.compareWith(cur); - if (i == 0) { - current.add(element); - } else if (i < 0) { - cur = element; - current.clear(); - current.add(cur); - } - } - - return current.isEmpty() ? null : findClosestTo(myInitialPsiElement, current); - } - - @Nullable - private Object findClosestTo(PsiElement path, ArrayList paths) { - if (path == null || myInitialPsiElement == null) { - return paths.get(0).node; - } - final Set parents = getAllParents(myInitialPsiElement); - ArrayList cur = new ArrayList(); - int max = -1; - for (ObjectWithWeight p : paths) { - final Object last = ((TreePath)p.node).getLastPathComponent(); - final List elements = new ArrayList(); - final Object object = ((DefaultMutableTreeNode)last).getUserObject(); - if (object instanceof FilteringTreeStructure.FilteringNode) { - FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object; - while (node != null) { - elements.add(getPsi(node)); - node = node.getParentNode(); - } - final int size = ContainerUtil.intersection(parents, elements).size(); - if (size > max) { - max = size; - cur.clear(); - cur.add((TreePath)p.node); - } else if (size == max) { - cur.add((TreePath)p.node); - } - } - } - - Collections.sort(cur, new Comparator() { - @Override - public int compare(TreePath o1, TreePath o2) { - return o2.getPathCount() - o1.getPathCount(); - } - }); - return cur.isEmpty() ? null : cur.get(0); - } - - class ObjectWithWeight { - final Object node; - final List weights = new ArrayList(); - - ObjectWithWeight(Object element, String pattern, SpeedSearchComparator comparator) { - this.node = element; - final String text = getElementText(element); - if (text != null) { - final Iterable ranges = comparator.matchingFragments(pattern, text); - if (ranges != null) { - for (TextRange range : ranges) { - weights.add(range); - } - } - } - Collections.sort(weights, TEXT_RANGE_COMPARATOR); - } - - int compareWith(ObjectWithWeight obj) { - final List w = obj.weights; - for (int i = 0; i < weights.size(); i++) { - if (i >= w.size()) return 1; - final int result = TEXT_RANGE_COMPARATOR.compare(weights.get(i), w.get(i)); - if (result != 0) { - return result; - } - } - - return 0; - } - - } - - }; + mySpeedSearch = new MyTreeSpeedSearch(); mySpeedSearch.setComparator(new SpeedSearchComparator(false, true)); final FileStructurePopupFilter filter = new FileStructurePopupFilter(); @@ -327,8 +202,8 @@ public class FileStructurePopup implements Disposable { } }; - myAbstractTreeBuilder.getUi().getUpdater().setDelay(1); - + myAbstractTreeBuilder.getUi().getUpdater().setPassThroughMode(true); + myInitialPsiElement = getCurrentElement(getPsiFile(myProject)); //myAbstractTreeBuilder.setCanYieldUpdate(true); Disposer.register(this, myAbstractTreeBuilder); } @@ -399,7 +274,6 @@ public class FileStructurePopup implements Disposable { myAbstractTreeBuilder.queueUpdate().doWhenDone(new Runnable() { @Override public void run() { - myInitialPsiElement = getCurrentElement(getPsiFile(myProject)); selectPsiElement(myInitialPsiElement); treeHasBuilt.setDone(); //long t = System.currentTimeMillis() - time; @@ -856,4 +730,136 @@ public class FileStructurePopup implements Disposable { return mySpeedSearch != null && !StringUtil.isEmpty(mySpeedSearch.getEnteredPrefix()) ? mySpeedSearch.getEnteredPrefix() : null; } + + public class MyTreeSpeedSearch extends TreeSpeedSearch { + public MyTreeSpeedSearch() { + super(FileStructurePopup.this.myTree, new Convertor() { + @Nullable + public String convert(TreePath path) { + final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + final Object userObject = node.getUserObject(); + if (userObject instanceof FilteringTreeStructure.FilteringNode) { + return FileStructurePopup.getText(((FilteringTreeStructure.FilteringNode)userObject).getDelegate()); + } + return ""; + } + }, true); + } + + @Override + protected Point getComponentLocationOnScreen() { + return myPopup.getContent().getLocationOnScreen(); + } + + @Override + protected Rectangle getComponentVisibleRect() { + return myPopup.getContent().getVisibleRect(); + } + + @Override + public Object findElement(String s) { + List elements = new ArrayList(); + s = s.trim(); + final ListIterator it = getElementIterator(0); + while (it.hasNext()) { + final ObjectWithWeight o = new ObjectWithWeight(it.next(), s, getComparator()); + if (!o.weights.isEmpty()) { + elements.add(o); + } + } + ObjectWithWeight cur = null; + ArrayList current = new ArrayList(); + for (ObjectWithWeight element : elements) { + if (cur == null) { + cur = element; + current.add(cur); + continue; + } + + final int i = element.compareWith(cur); + if (i == 0) { + current.add(element); + } else if (i < 0) { + cur = element; + current.clear(); + current.add(cur); + } + } + + return current.isEmpty() ? null : findClosestTo(myInitialPsiElement, current); + } + + @Nullable + private Object findClosestTo(PsiElement path, ArrayList paths) { + if (path == null || myInitialPsiElement == null) { + return paths.get(0).node; + } + final Set parents = getAllParents(myInitialPsiElement); + ArrayList cur = new ArrayList(); + int max = -1; + for (ObjectWithWeight p : paths) { + final Object last = ((TreePath)p.node).getLastPathComponent(); + final List elements = new ArrayList(); + final Object object = ((DefaultMutableTreeNode)last).getUserObject(); + if (object instanceof FilteringTreeStructure.FilteringNode) { + FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object; + while (node != null) { + elements.add(getPsi(node)); + node = node.getParentNode(); + } + final int size = ContainerUtil.intersection(parents, elements).size(); + if (size > max) { + max = size; + cur.clear(); + cur.add(p); + } else if (size == max) { + cur.add(p); + } + } + } + + Collections.sort(cur, new Comparator() { + @Override + public int compare(ObjectWithWeight o1, ObjectWithWeight o2) { + final int i = o1.compareWith(o2); + return i != 0 ? i + : ((TreePath)o2.node).getPathCount() - ((TreePath)o1.node).getPathCount(); + } + }); + return cur.isEmpty() ? null : cur.get(0).node; + } + + class ObjectWithWeight { + final Object node; + final List weights = new ArrayList(); + + ObjectWithWeight(Object element, String pattern, SpeedSearchComparator comparator) { + this.node = element; + final String text = getElementText(element); + if (text != null) { + final Iterable ranges = comparator.matchingFragments(pattern, text); + if (ranges != null) { + for (TextRange range : ranges) { + weights.add(range); + } + } + } + Collections.sort(weights, TEXT_RANGE_COMPARATOR); + } + + int compareWith(ObjectWithWeight obj) { + final List w = obj.weights; + for (int i = 0; i < weights.size(); i++) { + if (i >= w.size()) return 1; + final int result = TEXT_RANGE_COMPARATOR.compare(weights.get(i), w.get(i)); + if (result != 0) { + return result; + } + } + + return 0; + } + + } + } } diff --git a/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java b/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java index 99c205834e94..269ed4ca8546 100644 --- a/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java +++ b/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java @@ -22,7 +22,6 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; -import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.treeStructure.Tree; import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; @@ -30,6 +29,7 @@ import com.intellij.util.ui.tree.TreeUtil; import junit.framework.Assert; import org.junit.Before; +import javax.swing.tree.TreePath; import java.io.File; /** @@ -68,6 +68,14 @@ public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase { return getFileName("tree"); } + protected void checkTree(String filter) throws Exception { + myPopup.setSearchFilterForTests(filter); + getBuilder().refilter(null, false, true); + getBuilder().queueUpdate(); + TreeUtil.selectPath(getTree(), (TreePath)getSpeedSearch().findElement(filter)); + checkTree(); + } + protected void checkTree() throws Exception { final String expected = FileUtil.loadFile(new File(getTestDataPath() + "/" + getTreeFileName()), true); Assert.assertEquals(expected.trim(), PlatformTestUtil.print(getTree(), true).trim()); @@ -97,8 +105,8 @@ public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase { return myPopup.getTreeBuilder(); } - protected TreeSpeedSearch getSpeedSearch() { - return myPopup.getSpeedSearch(); + protected FileStructurePopup.MyTreeSpeedSearch getSpeedSearch() { + return (FileStructurePopup.MyTreeSpeedSearch)myPopup.getSpeedSearch(); }