diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java new file mode 100644 index 000000000000..c23078e3a11a --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * -Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * -Redistribution in binary form must reproduct the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * Neither the name of JetBrains or IntelliJ IDEA + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING + * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT + * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT + * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS + * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST + * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, + * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY + * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN + * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ +package com.intellij.projectView; + +import com.intellij.ide.projectView.PresentationData; +import com.intellij.ide.projectView.TreeStructureProvider; +import com.intellij.ide.projectView.ViewSettings; +import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane; +import com.intellij.ide.projectView.impl.ClassesTreeStructureProvider; +import com.intellij.ide.util.treeView.AbstractTreeNode; +import com.intellij.ide.util.treeView.NodeDescriptor; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.refactoring.rename.RenameProcessor; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.uiDesigner.projectView.FormMergerTreeStructureProvider; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + +@SuppressWarnings({"HardCodedStringLiteral"}) +public class ProjectViewUpdatingTest extends BaseProjectViewTestCase { + public void testStandardProviders() throws Exception{ + PsiFile element = JavaDirectoryService.getInstance().getClasses(getPackageDirectory())[0].getContainingFile(); + final AbstractProjectViewPSIPane pane = myStructure.createPane(); + getProjectTreeStructure().setProviders(); + pane.select(element, element.getContainingFile().getVirtualFile(), true); + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: standardProviders\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " Class1.java\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + getRootFiles() + + " +External Libraries\n" + ); + final PsiClass[] classes = JavaDirectoryService.getInstance() + .getPackage(getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1")).getClasses(); + sortClassesByName(classes); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + classes[0].delete(); + } + }); + + + PlatformTestUtil.waitForAlarm(600); + + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: standardProviders\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " Class2.java\n" + + " Class4.java\n" + + " Form1.form\n" + + " Form1.java\n" + + " Form2.form\n" + + getRootFiles() + + " +External Libraries\n"); + + } + + public void testUpdateProjectView() throws Exception { + getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject), new FormMergerTreeStructureProvider(myProject)); + + final AbstractProjectViewPSIPane pane = myStructure.createPane(); + final JTree tree = pane.getTree(); + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " +PsiDirectory: updateProjectView\n" + + getRootFiles() + + " +External Libraries\n"); + + final PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Form1.java"); + final PsiClass aClass = classFile.getClasses()[0]; + final PsiFile containingFile = aClass.getContainingFile(); + pane.select(aClass, containingFile.getVirtualFile(), true); + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: updateProjectView\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " Class1\n" + + " +Class2.java\n" + + " Class4.java\n" + + " Form2.form\n" + + " -Form:Form1\n" + + " [Form1]\n" + + " Form1.form\n" + + getRootFiles() + + " +External Libraries\n", true); + + CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + @Override + public void run() { + new RenameProcessor(myProject, aClass, "Form1_renamed", false, false).run(); + } + }, null, null); + + PlatformTestUtil.waitForAlarm(600); + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " -PsiDirectory: updateProjectView\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " Class1\n" + + " +Class2.java\n" + + " Class4.java\n" + + " Form2.form\n" + + " -Form:Form1_renamed\n" + + " Form1.form\n" + + " [Form1_renamed]\n" + + getRootFiles() + + " +External Libraries\n", true); + + TreeUtil.collapseAll(pane.getTree(), -1); + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " +PsiDirectory: updateProjectView\n" + + getRootFiles() + + " +External Libraries\n"); + + final PsiClass aClass2 = JavaDirectoryService.getInstance() + .createClass(getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1"), "Class6"); + PlatformTestUtil.waitForAlarm(600); + final PsiFile containingFile2 = aClass2.getContainingFile(); + pane.select(aClass2, containingFile2.getVirtualFile(), true); + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: updateProjectView\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " Class1\n" + + " +Class2.java\n" + + " Class4.java\n" + + " [Class6]\n" + + " Form2.form\n" + + " +Form:Form1_renamed\n" + + getRootFiles() + + " +External Libraries\n", true); + } + + public void testShowClassMembers() throws Exception{ + + getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject), new FormMergerTreeStructureProvider(myProject)); + + final AbstractProjectViewPSIPane pane = myStructure.createPane(); + final JTree tree = pane.getTree(); + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " +PsiDirectory: showClassMembers\n" + + getRootFiles() + + " +External Libraries\n"); + + myStructure.setShowMembers(true); + + PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java"); + PsiClass aClass = classFile.getClasses()[0]; + PsiFile containingFile = aClass.getContainingFile(); + pane.select(aClass, containingFile.getVirtualFile(), true); + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: showClassMembers\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " -[Class1]\n" + + " +InnerClass\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " +Class2\n" + + getRootFiles() + + " +External Libraries\n", true); + + + final Document document = FileDocumentManager.getInstance().getDocument(containingFile.getVirtualFile()); + final int caretPosition = document.getText().indexOf("public class InnerClass") - 1; + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + CommandProcessor.getInstance().executeCommand(myProject, + new Runnable() { + @Override + public void run() { + document.insertString(caretPosition, "\n"); + } + }, + "typing", + null); + } + }); + + + PsiDocumentManager.getInstance(myProject).commitDocument(document); + PlatformTestUtil.waitForAlarm(600); + + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: showClassMembers\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " -[Class1]\n" + + " +InnerClass\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " myField2:boolean\n" + + " +Class2\n" + + getRootFiles() + + " +External Libraries\n", true); + + classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java"); + aClass = classFile.getClasses()[0]; + final PsiField lastField = aClass.getFields()[1]; + pane.select(lastField, containingFile.getVirtualFile(), true); + + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: showClassMembers\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " -Class1\n" + + " +InnerClass\n" + + " getValue():int\n" + + " myField1:boolean\n" + + " [myField2:boolean]\n" + + " +Class2\n" + + getRootFiles() + + " +External Libraries\n", true); + + CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + assertEquals("myField2", lastField.getName()); + lastField.setName("_firstField"); + } + catch (IncorrectOperationException e) { + fail(e.getMessage()); + } + } + }); + } + }, null, null); + + PlatformTestUtil.waitForAlarm(600); + + PlatformTestUtil.assertTreeEqual(pane.getTree(), "-Project\n" + + " -PsiDirectory: showClassMembers\n" + + " -PsiDirectory: src\n" + + " -PsiDirectory: com\n" + + " -PsiDirectory: package1\n" + + " -Class1\n" + + " +InnerClass\n" + + " getValue():int\n" + + " [_firstField:boolean]\n" + + " myField1:boolean\n" + + " +Class2\n" + + getRootFiles() + + " +External Libraries\n", true); + } + + public void testAnnoyingScrolling() throws Exception{ + + getProjectTreeStructure().setProviders(new ClassesTreeStructureProvider(myProject)); + + final AbstractProjectViewPSIPane pane = myStructure.createPane(); + final JTree tree = pane.getTree(); + + myStructure.setShowMembers(true); + + PsiJavaFile classFile = (PsiJavaFile)getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1").findFile("Class1.java"); + PsiClass aClass = classFile.getClasses()[0]; + PsiFile containingFile = aClass.getContainingFile(); + PsiDirectory directory = containingFile.getContainingDirectory(); + pane.select(aClass, containingFile.getVirtualFile(), true); + Point viewPosition = ((JViewport)tree.getParent()).getViewPosition(); + for (int i=0;i<100;i++) { + JavaDirectoryService.getInstance().createClass(directory, "A" + i); + } + PlatformTestUtil.waitForAlarm(600); + Point viewPositionAfter = ((JViewport)tree.getParent()).getViewPosition(); + assertEquals(viewPosition, viewPositionAfter); + + } + + class NodeWrapper extends AbstractTreeNode { + String myName; + List myChildren = new ArrayList(); + + public NodeWrapper(final Project project, final String value) { + super(project, new Object()); + myName = value; + } + + @Override + @NotNull + public Collection getChildren() { + return myChildren; + } + + @Override + protected void update(final PresentationData presentation) { + presentation.setPresentableText(myName); + } + + public void addChild(final NodeWrapper nodeWrapper) { + myChildren.add(nodeWrapper); + } + + public void setName(final String s) { + myName = s; + } + } + + public void testUpdatingAfterRename() throws Exception{ + + final NodeWrapper rootWrapper = new NodeWrapper(myProject, "1"); + + final NodeWrapper wr11 = new NodeWrapper(myProject, "1.1"); + final NodeWrapper wr12 = new NodeWrapper(myProject, "1.2"); + final NodeWrapper wr13 = new NodeWrapper(myProject, "1.3"); + final NodeWrapper wr111 = new NodeWrapper(myProject, "1.1.1"); + final NodeWrapper wr112 = new NodeWrapper(myProject, "1.1.2"); + final NodeWrapper wr113 = new NodeWrapper(myProject, "1.1.3"); + final NodeWrapper wr121 = new NodeWrapper(myProject, "1.2.1"); + final NodeWrapper wr122 = new NodeWrapper(myProject, "1.2.2"); + final NodeWrapper wr123 = new NodeWrapper(myProject, "1.2.3"); + final NodeWrapper wr131 = new NodeWrapper(myProject, "1.3.1"); + final NodeWrapper wr132 = new NodeWrapper(myProject, "1.3.2"); + final NodeWrapper wr133 = new NodeWrapper(myProject, "1.3.3"); + + rootWrapper.addChild(wr11); + rootWrapper.addChild(wr12); + rootWrapper.addChild(wr13); + + wr11.addChild(wr111); + wr11.addChild(wr112); + wr11.addChild(wr113); + + wr12.addChild(wr121); + wr12.addChild(wr122); + wr12.addChild(wr123); + + wr13.addChild(wr131); + wr13.addChild(wr132); + wr13.addChild(wr133); + + + getProjectTreeStructure().setProviders(createWrapProvider(rootWrapper)); + + final AbstractProjectViewPSIPane pane = myStructure.createPane(); + + final JTree tree = pane.getTree(); + + pane.getTreeBuilder().setNodeDescriptorComparator(new Comparator() { + @Override + public int compare(final NodeDescriptor o1, final NodeDescriptor o2) { + if (o1 instanceof NodeWrapper && o2 instanceof NodeWrapper) { + return ((NodeWrapper)o1).getName().compareTo(((NodeWrapper)o2).getName()); + } + else { + return 0; + } + } + }); + + tree.expandRow(2); + TreeUtil.selectPath(tree, tree.getPathForRow(4)); + + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " -1\n" + + " +1.1\n" + + " -1.2\n" + + " 1.2.1\n" + + " [1.2.2]\n" + + " 1.2.3\n" + + " +1.3\n", true); + + wr12.setName("01.2"); + wr122.setName("01.2.2"); + + pane.getTreeBuilder().updateFromRoot(); + + PlatformTestUtil.assertTreeEqual(tree, "-Project\n" + + " -1\n" + + " -01.2\n" + + " [01.2.2]\n" + + " 1.2.1\n" + + " 1.2.3\n" + + " +1.1\n" + + " +1.3\n", true); + + + } + + private TreeStructureProvider createWrapProvider(final NodeWrapper rootWrapper) { + return new TreeStructureProvider() { + @Override + public Collection modify(AbstractTreeNode parent, Collection children, ViewSettings settings) { + + if (parent instanceof NodeWrapper) { + return children; + } + List result = new ArrayList(); + result.add(rootWrapper); + return result; + } + + @Override + @Nullable + public Object getData(Collection selected, String dataName) { + return null; + } + }; + } + +}