From 7326b79b16843689b54187d78888992010fc400c Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 29 Mar 2012 20:40:35 +0400 Subject: [PATCH 01/20] Add caching for jar paths, because FS event can come often. --- .../vfs/impl/jar/JarFileSystemImpl.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 3ee71c67efc1..6262b7eabb94 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -50,6 +50,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo private File myNoCopyJarDir; private final Map myHandlers = new HashMap(); + private String[] jarPathsCache; // jarPathsCache = myHandlers.keySet() private static final class JarFileSystemImplLock { } @@ -68,16 +69,22 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo for (VFileEvent event : events) { if (event.getFileSystem() instanceof LocalFileSystem) { - final String path = event.getPath(); - List jarPaths = new ArrayList(); + String path = event.getPath(); + + String[] jarPaths; synchronized (LOCK) { - jarPaths.addAll(myHandlers.keySet()); + if (jarPathsCache == null) { + jarPathsCache = new String[myHandlers.size()]; + int i = 0; + for (String p : myHandlers.keySet()) { + jarPathsCache[i++] = p.substring(0, p.length() - JAR_SEPARATOR.length()); + } + } + jarPaths = jarPathsCache; } for (String jarPath : jarPaths) { - if (FileUtil.startsWith(jarPath.substring(0, jarPath.length() - JAR_SEPARATOR.length()), - path, - SystemInfo.isFileSystemCaseSensitive)) { + if (FileUtil.startsWith(jarPath, path, SystemInfo.isFileSystemCaseSensitive)) { VirtualFile jarRootToRefresh = markDirty(jarPath); if (jarRootToRefresh != null) { rootsToRefresh.add(jarRootToRefresh); @@ -119,6 +126,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo final JarHandler handler; synchronized (LOCK) { handler = myHandlers.remove(path); + jarPathsCache = null; } if (handler != null) { @@ -193,6 +201,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo if (handler == null) { freshHandler = handler = new JarHandler(this, jarRootPath.substring(0, jarRootPath.length() - JAR_SEPARATOR.length())); myHandlers.put(jarRootPath, handler); + jarPathsCache = null; } else { freshHandler = null; From 2817dd09c8fa454b888fc82bb24af653081252b9 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 30 Mar 2012 14:14:24 +0400 Subject: [PATCH 02/20] Add additional logining to understand cause of failing maven tests. --- .../jetbrains/idea/maven/indices/MavenIndex.java | 13 ++++++++++++- .../MavenExtensionCompletionAndResolutionTest.java | 12 ++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index 610522ec592f..fdb24a97580b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -421,7 +421,7 @@ public class MavenIndex { } @TestOnly - protected File getDir() { + public File getDir() { return myDir; } @@ -491,6 +491,17 @@ public class MavenIndex { }, Collections.emptySet()); } + @TestOnly + public void printInfo() { + doIndexTask(new IndexTask>() { + public Set doTask() throws Exception { + System.out.println("BaseFile: " + myData.groupToArtifactMap.getBaseFile()); + System.out.println("All data objects: " + myData.groupToArtifactMap.getAllDataObjects(null)); + return Collections.emptySet(); + } + }, Collections.emptySet()); + } + public synchronized Set getVersions(final String groupId, final String artifactId) { return doIndexTask(new IndexTask>() { public Set doTask() throws Exception { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java index 211cf736ca95..58800d25137b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.dom; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiReference; +import org.jetbrains.idea.maven.indices.MavenIndex; import org.jetbrains.idea.maven.indices.MavenIndicesTestFixture; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; @@ -74,9 +75,16 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic if (!new HashSet(actual).equals(new HashSet(Arrays.asList("maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin")))) { MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); - System.out.println("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins")); + System.out.println("GetArtifacts: " + new HashSet(instance.getArtifactIds("org.apache.maven.plugins"))); System.out.println("Indexes: " + instance.getIndices()); - throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + "Indexes: " + instance.getIndices()); + + for (MavenIndex index : instance.getIndices()) { + System.out.println("Index: repositoryId=" + index.getRepositoryId() + " repositoryUrl=" + index.getRepositoryUrl() + " repositoryPathOrUrl" + index.getRepositoryPathOrUrl()); + System.out.println("Dir: " + index.getDir()); + index.printInfo(); + } + + throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + " Indexes: " + instance.getIndices()); } assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); From d593387fa70f31337dd36ab53508315b0056fb6e Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 30 Mar 2012 10:15:09 +0400 Subject: [PATCH 03/20] IDEA-83702: Context menu in Dependency editor should has 'edit' action --- .../classpath/ClasspathPanelImpl.java | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java index 270ddf4fd1ef..d5566631b5b8 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java @@ -178,8 +178,13 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { WHEN_FOCUSED ); + myEditButton = new AnActionButton(ProjectBundle.message("module.classpath.button.edit"), null, IconUtil.getEditIcon()) { + @Override + public void actionPerformed(AnActionEvent e) { + doEdit(); + } + }; add(createTableWithButtons(), BorderLayout.CENTER); - //add(createButtonsBlock(), BorderLayout.EAST); if (myEntryTable.getRowCount() > 0) { myEntryTable.getSelectionModel().setSelectionInterval(0,0); @@ -212,6 +217,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { }; navigateAction.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE).getShortcutSet(), myEntryTable); + actionGroup.add(myEditButton); actionGroup.add(navigateAction); actionGroup.add(new MyFindUsagesAction()); actionGroup.add(new AnalyzeDependencyAction()); @@ -280,30 +286,6 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { } }; - myEditButton = new AnActionButton(ProjectBundle.message("module.classpath.button.edit"), null, IconUtil.getEditIcon()) { - @Override - public void actionPerformed(AnActionEvent e) { - final OrderEntry entry = getSelectedEntry(); - if (!(entry instanceof LibraryOrderEntry)) return; - - final Library library = ((LibraryOrderEntry)entry).getLibrary(); - if (library == null) { - return; - } - final LibraryTable table = library.getTable(); - final String tableLevel = table != null ? table.getTableLevel() : LibraryTableImplUtil.MODULE_LEVEL; - final LibraryTablePresentation presentation = LibraryEditingUtil.getLibraryTablePresentation(getProject(), tableLevel); - final LibraryTableModifiableModelProvider provider = getModifiableModelProvider(tableLevel); - EditExistingLibraryDialog dialog = EditExistingLibraryDialog.createDialog(ClasspathPanelImpl.this, provider, library, myState.getProject(), - presentation, getStructureConfigurableContext()); - dialog.setContextModule(getRootModel().getModule()); - dialog.show(); - myEntryTable.repaint(); - ModuleStructureConfigurable.getInstance(myState.getProject()).getTree().repaint(); - } - }; - - final AnActionButton analyzeButton = new AnActionButton(ProjectBundle.message("classpath.panel.analyze"), null, SystemInfo.isMac ? PlatformIcons.TABLE_ANALYZE : PlatformIcons.ANALYZE) { @Override public void actionPerformed(AnActionEvent e) { @@ -395,6 +377,26 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { return panel; } + private void doEdit() { + final OrderEntry entry = getSelectedEntry(); + if (!(entry instanceof LibraryOrderEntry)) return; + + final Library library = ((LibraryOrderEntry)entry).getLibrary(); + if (library == null) { + return; + } + final LibraryTable table = library.getTable(); + final String tableLevel = table != null ? table.getTableLevel() : LibraryTableImplUtil.MODULE_LEVEL; + final LibraryTablePresentation presentation = LibraryEditingUtil.getLibraryTablePresentation(getProject(), tableLevel); + final LibraryTableModifiableModelProvider provider = getModifiableModelProvider(tableLevel); + EditExistingLibraryDialog dialog = EditExistingLibraryDialog.createDialog(this, provider, library, myState.getProject(), + presentation, getStructureConfigurableContext()); + dialog.setContextModule(getRootModel().getModule()); + dialog.show(); + myEntryTable.repaint(); + ModuleStructureConfigurable.getInstance(myState.getProject()).getTree().repaint(); + } + @Override public void addNotify() { super.addNotify(); From d0c91e51ea7bb978781d2fcc292fcdc23bf6cf43 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 30 Mar 2012 11:22:14 +0400 Subject: [PATCH 04/20] IDEA-83177: New project image in the Add Module wizard --- .../ide/util/newProjectWizard/ProjectCreateModeStep.java | 5 +---- .../ide/util/newProjectWizard/ProjectNameStep.java | 5 +---- .../newProjectWizard/modes/CreateFromSourcesMode.java | 4 +--- .../modes/CreateModuleFromSourcesMode.java | 6 ------ .../modes/CreateProjectFromSourcesMode.java | 9 --------- .../ide/util/projectWizard/ProjectJdkForModuleStep.java | 4 +--- .../intellij/ide/util/projectWizard/ProjectJdkStep.java | 4 +--- .../intellij/ide/util/projectWizard/ProjectNameStep.java | 6 ++---- .../intellij/projectImport/ProjectImportWizardStep.java | 4 +--- .../intellij/ide/util/projectWizard/WizardContext.java | 8 ++++++++ 10 files changed, 16 insertions(+), 39 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectCreateModeStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectCreateModeStep.java index d55e0756fe03..cd13249fd076 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectCreateModeStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectCreateModeStep.java @@ -43,9 +43,6 @@ import java.util.ArrayList; import java.util.List; public class ProjectCreateModeStep extends ModuleWizardStep { - private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); - - private final JPanel myWholePanel; private WizardMode myMode; @@ -138,7 +135,7 @@ public class ProjectCreateModeStep extends ModuleWizardStep { } public Icon getIcon() { - return myWizardContext.getProject() == null ? NEW_PROJECT_ICON : ICON; + return myWizardContext.getStepIcon(); } public WizardMode getMode() { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameStep.java index d809d07bddf9..cadc59d215f2 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameStep.java @@ -25,7 +25,6 @@ import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; import com.intellij.projectImport.ProjectFormatPanel; @@ -38,8 +37,6 @@ import java.io.File; * Date: Jul 17, 2007 */ public class ProjectNameStep extends ModuleWizardStep { - private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); - private final JPanel myPanel; protected final JPanel myAdditionalContentPanel; protected NamePathComponent myNamePathComponent; @@ -97,7 +94,7 @@ public class ProjectNameStep extends ModuleWizardStep { } public Icon getIcon() { - return myWizardContext.getProject() == null ? NEW_PROJECT_ICON : ICON; + return myWizardContext.getStepIcon(); } public JComponent getPreferredFocusedComponent() { diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java index d514b0067edc..fbc9d9a364f4 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromSourcesMode.java @@ -61,7 +61,7 @@ public abstract class CreateFromSourcesMode extends WizardMode { myProjectBuilder = projectBuilder; final StepSequence sequence = new StepSequence(); - final Icon icon = getIcon(); + final Icon icon = context.getStepIcon(); if (context.isCreatingNewProject()) { sequence.addCommonStep(new ProjectNameStep(context, this)); } @@ -89,8 +89,6 @@ public abstract class CreateFromSourcesMode extends WizardMode { return sequence; } - protected abstract Icon getIcon(); - public ProjectBuilder getModuleBuilder() { return myProjectBuilder; } diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateModuleFromSourcesMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateModuleFromSourcesMode.java index 6d4294f4a99b..3fec5ca5cfac 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateModuleFromSourcesMode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateModuleFromSourcesMode.java @@ -31,14 +31,8 @@ import java.io.File; * @author nik */ public class CreateModuleFromSourcesMode extends CreateFromSourcesMode { - private static final Icon STEP_ICON = IconLoader.getIcon("/addmodulewizard.png"); private TextFieldWithBrowseButton myPathPanel; - - protected Icon getIcon() { - return STEP_ICON; - } - public boolean isAvailable(WizardContext context) { return !context.isCreatingNewProject(); } diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateProjectFromSourcesMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateProjectFromSourcesMode.java index 290e72071d42..1f129f6c62d2 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateProjectFromSourcesMode.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateProjectFromSourcesMode.java @@ -16,20 +16,11 @@ package com.intellij.ide.util.newProjectWizard.modes; import com.intellij.ide.util.projectWizard.WizardContext; -import com.intellij.openapi.util.IconLoader; - -import javax.swing.*; /** * @author nik */ public class CreateProjectFromSourcesMode extends CreateFromSourcesMode { - private static final Icon STEP_ICON = IconLoader.getIcon("/newprojectwizard.png"); - - protected Icon getIcon() { - return STEP_ICON; - } - public boolean isAvailable(WizardContext context) { return context.isCreatingNewProject(); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java index f3c0925f423c..6ab1c7f392dc 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java @@ -28,7 +28,6 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.JdkListConfigurab import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.MultiLineLabelUI; -import com.intellij.openapi.util.IconLoader; import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; @@ -43,7 +42,6 @@ import java.awt.event.ActionListener; * Date: Jan 21, 2004 */ public class ProjectJdkForModuleStep extends ModuleWizardStep { - private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); private final JdkChooserPanel myJdkChooser; private final JPanel myPanel; private final WizardContext myContext; @@ -147,7 +145,7 @@ public class ProjectJdkForModuleStep extends ModuleWizardStep { } public Icon getIcon() { - return NEW_PROJECT_ICON; + return myContext.getStepIcon(); } @Nullable diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java index bd9bb698d28a..3e996c0e54c5 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java @@ -29,7 +29,6 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ui.configuration.ProjectJdksConfigurable; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.MultiLineLabelUI; -import com.intellij.openapi.util.IconLoader; import javax.swing.*; import java.awt.*; @@ -39,7 +38,6 @@ import java.awt.*; * Date: Jan 21, 2004 */ public class ProjectJdkStep extends ModuleWizardStep { - private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); private final WizardContext myContext; protected final ProjectJdksConfigurable myProjectJdksConfigurable; @@ -85,7 +83,7 @@ public class ProjectJdkStep extends ModuleWizardStep { } public Icon getIcon() { - return NEW_PROJECT_ICON; + return myContext.getStepIcon(); } public boolean validate() throws ConfigurationException { diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java index 0d7cdbb3621d..e5c2be752ee5 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java @@ -16,14 +16,13 @@ package com.intellij.ide.util.projectWizard; import com.intellij.ide.IdeBundle; -import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.highlighter.ModuleFileType; +import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; @@ -40,7 +39,6 @@ import static com.intellij.openapi.components.StorageScheme.DIRECTORY_BASED; * Date: Jan 21, 2004 */ public class ProjectNameStep extends ModuleWizardStep { - private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); private final NamePathComponent myNamePathComponent; private final JPanel myPanel; private final WizardContext myWizardContext; @@ -97,7 +95,7 @@ public class ProjectNameStep extends ModuleWizardStep { } public Icon getIcon() { - return NEW_PROJECT_ICON; + return myWizardContext.getStepIcon(); } public boolean validate() throws ConfigurationException { diff --git a/java/idea-ui/src/com/intellij/projectImport/ProjectImportWizardStep.java b/java/idea-ui/src/com/intellij/projectImport/ProjectImportWizardStep.java index 65597abd80ed..ca3e311f86eb 100644 --- a/java/idea-ui/src/com/intellij/projectImport/ProjectImportWizardStep.java +++ b/java/idea-ui/src/com/intellij/projectImport/ProjectImportWizardStep.java @@ -17,7 +17,6 @@ package com.intellij.projectImport; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.WizardContext; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.io.FileUtil; import javax.swing.*; @@ -26,7 +25,6 @@ import javax.swing.*; * @author Vladislav.Kaznacheev */ public abstract class ProjectImportWizardStep extends ModuleWizardStep { - protected static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); private final WizardContext myContext; public ProjectImportWizardStep(WizardContext context) { @@ -34,7 +32,7 @@ public abstract class ProjectImportWizardStep extends ModuleWizardStep { } public Icon getIcon() { - return myContext.isCreatingNewProject() ? NEW_PROJECT_ICON : ICON; + return myContext.getStepIcon(); } protected ProjectImportBuilder getBuilder() { diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java index 4cdf2a27a9ac..8cb3e36021f7 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java @@ -22,15 +22,19 @@ import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.IconLoader; import com.intellij.util.SystemProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; import java.util.ArrayList; import java.util.List; public class WizardContext { + private static final Icon NEW_PROJECT_ICON = IconLoader.getIcon("/newprojectwizard.png"); + private static final Icon NEW_MODULE_ICON = IconLoader.getIcon("/addmodulewizard.png"); /** * a project where the module should be added, can be null => the wizard creates a new project */ @@ -118,6 +122,10 @@ public class WizardContext { return myProject == null; } + public Icon getStepIcon() { + return isCreatingNewProject() ? NEW_PROJECT_ICON : NEW_MODULE_ICON; + } + public void requestWizardButtonsUpdate() { final Listener[] listeners = myListeners.toArray(new Listener[myListeners.size()]); for (Listener listener : listeners) { From 1a15c211ee270aa9458165aa42febb4c4a95470b Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 30 Mar 2012 14:19:11 +0400 Subject: [PATCH 05/20] IDEA-13188: When switching a source root between source and test root, package prefix is erased --- .../openapi/roots/ui/configuration/ContentEntryEditor.java | 4 ++-- .../ui/configuration/actions/ToggleSourcesStateAction.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java index dcf5a45ca247..9b0db57dd926 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java @@ -191,10 +191,10 @@ public abstract class ContentEntryEditor implements ContentRootPanel.ActionCallb } @Nullable - public SourceFolder addSourceFolder(@NotNull final VirtualFile file, boolean isTestSource) { + public SourceFolder addSourceFolder(@NotNull final VirtualFile file, boolean isTestSource, String packagePrefix) { final ContentEntry contentEntry = getContentEntry(); if (contentEntry != null) { - final SourceFolder sourceFolder = contentEntry.addSourceFolder(file, isTestSource); + final SourceFolder sourceFolder = contentEntry.addSourceFolder(file, isTestSource, packagePrefix); try { return sourceFolder; } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java index 1bf6fc986296..e5b810f66229 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ToggleSourcesStateAction.java @@ -71,12 +71,13 @@ public class ToggleSourcesStateAction extends ContentEntryEditingAction { final SourceFolder sourceFolder = contentEntryEditor.getSourceFolder(selectedFile); if (isSelected) { if (sourceFolder == null) { // not marked yet - contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources); + contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources, ""); } else { if (myEditTestSources != sourceFolder.isTestSource()) { + final String packagePrefix = sourceFolder.getPackagePrefix(); contentEntryEditor.removeSourceFolder(sourceFolder); - contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources); + contentEntryEditor.addSourceFolder(selectedFile, myEditTestSources, packagePrefix); } } } From 136e5dd25712b6f5bab622256f633d0725ca97a2 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 30 Mar 2012 14:25:33 +0400 Subject: [PATCH 06/20] IDEA-83278 "Wrapping and Braces -> Keep when reformatting -> Multiple expressions in one line" prevents refactorings/intentions from producing correctly formatted code Make it possible to use 'multiple expressions on the same line' from tests as well --- .../psi/formatter/java/JavaSpacePropertyProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 8d04c48535b9..8da301fb80c6 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.lang.java.JavaLanguage; import com.intellij.lexer.JavaLexer; import com.intellij.lexer.Lexer; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; @@ -772,7 +773,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { // 1. Call 'introduce variable' refactoring for the code like 'System.out.println(1);'; // 2. When KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE is on, the output looks like 'int i = 1; System.out.println(i);'; // That's why we process the option only during the explicit reformat (directly invoked by an user). - if ((mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE && FormatterUtil.isFormatterCalledExplicitly()) + if ((mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE + && (FormatterUtil.isFormatterCalledExplicitly() || ApplicationManager.getApplication().isUnitTestMode())) || psi != null && PsiTreeUtil.hasErrorElements(psi)) { minSpaces = 1; From 25bdac17fa0e56adeefb11ab90e3dc3c806ffbbe Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 30 Mar 2012 15:06:03 +0400 Subject: [PATCH 07/20] Fix broken test. --- .../openapi/vfs/impl/jar/JarFileSystemImpl.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index 6262b7eabb94..ab98512cc9e4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -74,17 +74,16 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo String[] jarPaths; synchronized (LOCK) { if (jarPathsCache == null) { - jarPathsCache = new String[myHandlers.size()]; - int i = 0; - for (String p : myHandlers.keySet()) { - jarPathsCache[i++] = p.substring(0, p.length() - JAR_SEPARATOR.length()); - } + Set jarPathsSet = myHandlers.keySet(); + jarPathsCache = jarPathsSet.toArray(new String[jarPathsSet.size()]); } jarPaths = jarPathsCache; } for (String jarPath : jarPaths) { - if (FileUtil.startsWith(jarPath, path, SystemInfo.isFileSystemCaseSensitive)) { + if (FileUtil.startsWith(jarPath.substring(0, jarPath.length() - JAR_SEPARATOR.length()), + path, + SystemInfo.isFileSystemCaseSensitive)) { VirtualFile jarRootToRefresh = markDirty(jarPath); if (jarRootToRefresh != null) { rootsToRefresh.add(jarRootToRefresh); From e614b0aabc30137bb5d3c61859874f60231f3bea Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 30 Mar 2012 15:09:54 +0400 Subject: [PATCH 08/20] RUBY-10731 --- .../editorActions/enter/BaseIndentEnterHandler.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java index 1b64aa35513d..9c8a98fb7b7c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/BaseIndentEnterHandler.java @@ -125,7 +125,7 @@ public class BaseIndentEnterHandler extends EnterHandlerDelegateAdapter { } else { if (myIndentTokens.contains(type)) { - final String singleIndent = getSingleIndent(file); + final String singleIndent = getSingleIndent(file, lineIndent); EditorModificationUtil.insertStringAtCaret(editor, "\n" + lineIndent + singleIndent); return Result.Stop; } @@ -136,9 +136,12 @@ public class BaseIndentEnterHandler extends EnterHandlerDelegateAdapter { } } - protected static String getSingleIndent(final PsiFile file) { - CodeStyleSettings currantSettings = CodeStyleSettingsManager.getSettings(file.getProject()); - CommonCodeStyleSettings.IndentOptions indentOptions = currantSettings.getIndentOptions(file.getFileType()); + protected static String getSingleIndent(final PsiFile file, CharSequence lineIndent) { + if (lineIndent.length() > 0 && lineIndent.charAt(lineIndent.length() - 1) == '\t') { + return "\t"; + } + CodeStyleSettings currentSettings = CodeStyleSettingsManager.getSettings(file.getProject()); + CommonCodeStyleSettings.IndentOptions indentOptions = currentSettings.getIndentOptions(file.getFileType()); return StringUtil.repeatSymbol(' ', indentOptions.INDENT_SIZE); } From a0552e9d11d7cc97ae2c3ecc5b61d9744ede51b6 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 30 Mar 2012 15:29:30 +0400 Subject: [PATCH 09/20] library root detection: allow to detect several root types in one detector --- .../actions/MarkLibraryRootAction.java | 2 +- .../roots/ui/configuration/PathUIUtils.java | 4 +- .../classpath/CreateModuleLibraryChooser.java | 2 +- .../libraryEditor/LibraryRootsComponent.java | 12 +-- .../libraries/LibraryTypeServiceImpl.java | 25 ++---- .../ui/LibraryRootsComponentDescriptor.java | 20 ++++- .../libraries/ui/LibraryRootsDetector.java | 43 ++++++++++ .../ui/impl/DetectedRootsChooserDialog.java | 6 +- .../ui/impl/LibraryRootsDetectorImpl.java | 61 ++++++++++++++ .../libraries/ui/impl/RootDetectionUtil.java | 80 +++++++++++-------- .../ui/impl/SuggestedChildRootInfo.java | 22 ++--- 11 files changed, 200 insertions(+), 77 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsDetector.java create mode 100644 platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/LibraryRootsDetectorImpl.java diff --git a/java/idea-ui/src/com/intellij/ide/projectView/actions/MarkLibraryRootAction.java b/java/idea-ui/src/com/intellij/ide/projectView/actions/MarkLibraryRootAction.java index 3a78f17d56ed..8da8e87c2af9 100644 --- a/java/idea-ui/src/com/intellij/ide/projectView/actions/MarkLibraryRootAction.java +++ b/java/idea-ui/src/com/intellij/ide/projectView/actions/MarkLibraryRootAction.java @@ -45,7 +45,7 @@ public class MarkLibraryRootAction extends AnAction { final List jars = getRoots(e); if (jars.isEmpty()) return; - final List roots = RootDetectionUtil.detectRoots(jars, null, project, new DefaultLibraryRootsComponentDescriptor().getRootDetectors(), true); + final List roots = RootDetectionUtil.detectRoots(jars, null, project, new DefaultLibraryRootsComponentDescriptor()); new CreateLibraryFromFilesDialog(project, roots).show(); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java index 7792405a0cfc..435640d89c94 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/PathUIUtils.java @@ -19,6 +19,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.ui.OrderRoot; import com.intellij.openapi.roots.libraries.ui.RootDetector; +import com.intellij.openapi.roots.libraries.ui.impl.LibraryRootsDetectorImpl; import com.intellij.openapi.roots.libraries.ui.impl.RootDetectionUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -56,7 +57,8 @@ public class PathUIUtils { */ public static VirtualFile[] scanAndSelectDetectedJavaSourceRoots(Component parentComponent, final VirtualFile[] rootCandidates) { final List orderRoots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, null, - Collections.singletonList(JAVA_SOURCE_ROOT_DETECTOR), false); + new LibraryRootsDetectorImpl(Collections.singletonList(JAVA_SOURCE_ROOT_DETECTOR)), + new OrderRootType[0]); final List result = new ArrayList(); for (OrderRoot root : orderRoots) { result.add(root.getFile()); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/CreateModuleLibraryChooser.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/CreateModuleLibraryChooser.java index 7cc91c66cbcf..547112d1ee5c 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/CreateModuleLibraryChooser.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/CreateModuleLibraryChooser.java @@ -168,7 +168,7 @@ public class CreateModuleLibraryChooser implements ClasspathElementChooser chosenRoots = RootDetectionUtil.detectRoots(Arrays.asList(files), myParentComponent, myModule.getProject(), - rootsComponentDescriptor.getRootDetectors(), true); + rootsComponentDescriptor); final List roots = filterAlreadyAdded(chosenRoots); if (roots.isEmpty()) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java index be3f59f985d2..3a9daaa32146 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java @@ -173,7 +173,6 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } }); - final List detectors = myDescriptor.getRootDetectors(); toolbarDecorator.setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { @@ -188,9 +187,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent private AnAction[] getActions() { List actions = new ArrayList(); - if (!detectors.isEmpty()) { - actions.add(new AttachFilesAction(detectors, ProjectBundle.message("button.text.attach.files"))); - } + actions.add(new AttachFilesAction(ProjectBundle.message("button.text.attach.files"))); for (AttachRootButtonDescriptor descriptor : myDescriptor.createAttachButtons()) { actions.add(new AttachItemAction(descriptor, descriptor.getButtonText())); } @@ -348,11 +345,8 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } private class AttachFilesAction extends AttachItemActionBase { - private final List myDetectors; - - public AttachFilesAction(List detectors, String title) { + public AttachFilesAction(String title) { super(title); - myDetectors = detectors; } @Override @@ -368,7 +362,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent final VirtualFile[] files = FileChooser.chooseFiles(myPanel, chooserDescriptor, initialSelection); if (files.length == 0) return Collections.emptyList(); - return RootDetectionUtil.detectRoots(Arrays.asList(files), myPanel, myProject, myDetectors, true); + return RootDetectionUtil.detectRoots(Arrays.asList(files), myPanel, myProject, myDescriptor); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTypeServiceImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTypeServiceImpl.java index b618d4d3c514..60d7059e40c6 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTypeServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryTypeServiceImpl.java @@ -24,7 +24,6 @@ import com.intellij.openapi.roots.libraries.LibraryTypeService; import com.intellij.openapi.roots.libraries.NewLibraryConfiguration; import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; import com.intellij.openapi.roots.libraries.ui.OrderRoot; -import com.intellij.openapi.roots.libraries.ui.RootDetector; import com.intellij.openapi.roots.libraries.ui.impl.RootDetectionUtil; import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor; import com.intellij.openapi.util.io.FileUtil; @@ -35,7 +34,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Arrays; -import java.util.Collections; import java.util.List; /** @@ -60,22 +58,15 @@ public class LibraryTypeServiceImpl extends LibraryTypeService { @Nullable VirtualFile contextDirectory, LibraryType type, final Project project) { - final List rootDetectors = descriptor.getRootDetectors(); - final List roots; - if (!rootDetectors.isEmpty()) { - final FileChooserDescriptor chooserDescriptor = descriptor.createAttachFilesChooserDescriptor(); - chooserDescriptor.setTitle("Select Library Files"); - final VirtualFile[] rootCandidates = FileChooser.chooseFiles(parentComponent, chooserDescriptor, contextDirectory); - if (rootCandidates.length == 0) { - return null; - } + final FileChooserDescriptor chooserDescriptor = descriptor.createAttachFilesChooserDescriptor(); + chooserDescriptor.setTitle("Select Library Files"); + final VirtualFile[] rootCandidates = FileChooser.chooseFiles(parentComponent, chooserDescriptor, contextDirectory); + if (rootCandidates.length == 0) { + return null; + } - roots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, project, rootDetectors, true); - if (roots.isEmpty()) return null; - } - else { - roots = Collections.emptyList(); - } + final List roots = RootDetectionUtil.detectRoots(Arrays.asList(rootCandidates), parentComponent, project, descriptor); + if (roots.isEmpty()) return null; String name = suggestLibraryName(roots); return doCreate(type, name, roots); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsComponentDescriptor.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsComponentDescriptor.java index e4309604a0d6..6e3ceff4a522 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsComponentDescriptor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsComponentDescriptor.java @@ -15,6 +15,7 @@ package com.intellij.openapi.roots.libraries.ui; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.ui.impl.LibraryRootsDetectorImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,14 +37,29 @@ public abstract class LibraryRootsComponentDescriptor { public abstract OrderRootTypePresentation getRootTypePresentation(@NotNull OrderRootType type); /** - * Provides root detectors for 'Attach Files' button. They will be used to automatically assign {@link OrderRootType}s for selected files. - * Also these detectors are used when a new library is created so the list must not be empty. + * Provides separate detectors for root types supported by the library type. * * @return non-empty list of {@link RootDetector}'s implementations */ @NotNull public abstract List getRootDetectors(); + /** + * Provides root detector for 'Attach Files' button. It will be used to automatically assign {@link OrderRootType}s for selected files. + * Also this detector is used when a new library is created + * + * @return {@link LibraryRootsDetector}'s implementation + */ + @NotNull + public LibraryRootsDetector getRootsDetector() { + final List detectors = getRootDetectors(); + if (detectors.isEmpty()) { + throw new IllegalStateException("Detectors list is empty for " + this); + } + return new LibraryRootsDetectorImpl(detectors); + } + + /** * @return descriptor for the file chooser which will be shown when 'Attach Files' button is pressed */ diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsDetector.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsDetector.java new file mode 100644 index 000000000000..7abaacb19ab8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/LibraryRootsDetector.java @@ -0,0 +1,43 @@ +/* + * 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.openapi.roots.libraries.ui; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author nik + */ +public abstract class LibraryRootsDetector { + /** + * Find suitable roots in {@code rootCandidate} or its descendants. + * @param rootCandidate file selected in the file chooser by user + * @param progressIndicator can be used to show information about the progress and to abort searching if process is cancelled + * @return suitable roots + */ + public abstract Collection detectRoots(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator); + + /** + * @return presentable name for the root type or {@code null} if the root type isn't supported by this detector + */ + @Nullable + public abstract String getRootTypeName(@NotNull OrderRootType rootType, boolean isJarDirectory); +} diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java index 49685ce66976..865a26965723 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java @@ -141,7 +141,7 @@ public class DetectedRootsChooserDialog extends DialogWrapper { private static CheckedTreeNode createTree(List suggestedRoots) { TObjectIntHashMap rootTypesCount = new TObjectIntHashMap(); for (SuggestedChildRootInfo suggestedRoot : suggestedRoots) { - final VirtualFile root = suggestedRoot.getSuggestedRoot(); + final VirtualFile root = suggestedRoot.getSuggestedRoot().getFile(); if (!rootTypesCount.containsKey(root)) { rootTypesCount.put(root, 0); } @@ -158,7 +158,7 @@ public class DetectedRootsChooserDialog extends DialogWrapper { rootCandidateNodes.put(rootCandidate, parent); root.add(parent); } - final String rootType = rootTypesCount.get(rootInfo.getSuggestedRoot()) > 1 ? rootInfo.getDetector().getPresentableRootTypeName() : null; + final String rootType = rootTypesCount.get(rootInfo.getSuggestedRoot().getFile()) > 1 ? rootInfo.getRootTypeName() : null; parent.add(new VirtualFileCheckedTreeNode(rootInfo, rootType)); } return root; @@ -197,7 +197,7 @@ public class DetectedRootsChooserDialog extends DialogWrapper { public VirtualFileCheckedTreeNode(SuggestedChildRootInfo rootInfo, String rootType) { super(rootInfo); - myFile = rootInfo.getSuggestedRoot(); + myFile = rootInfo.getSuggestedRoot().getFile(); myRootType = rootType; } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/LibraryRootsDetectorImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/LibraryRootsDetectorImpl.java new file mode 100644 index 000000000000..e1f87fc9d7c1 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/LibraryRootsDetectorImpl.java @@ -0,0 +1,61 @@ +/* + * 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.openapi.roots.libraries.ui.impl; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.ui.LibraryRootsDetector; +import com.intellij.openapi.roots.libraries.ui.OrderRoot; +import com.intellij.openapi.roots.libraries.ui.RootDetector; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author nik + */ +public class LibraryRootsDetectorImpl extends LibraryRootsDetector { + private List myDetectors; + + public LibraryRootsDetectorImpl(List detectors) { + myDetectors = detectors; + } + + @Override + public Collection detectRoots(@NotNull VirtualFile rootCandidate, @NotNull ProgressIndicator progressIndicator) { + List result = new ArrayList(); + for (RootDetector detector : myDetectors) { + final Collection files = detector.detectRoots(rootCandidate, progressIndicator); + for (VirtualFile file : files) { + result.add(new OrderRoot(file, detector.getRootType(), detector.isJarDirectory())); + } + } + return result; + } + + @Override + public String getRootTypeName(@NotNull OrderRootType rootType, boolean isJarDirectory) { + for (RootDetector detector : myDetectors) { + if (detector.getRootType().equals(rootType) && detector.isJarDirectory() == isJarDirectory) { + return detector.getPresentableRootTypeName(); + } + } + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java index 8c309292945f..8ef97a8d10a5 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/RootDetectionUtil.java @@ -20,12 +20,14 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor; +import com.intellij.openapi.roots.libraries.ui.LibraryRootsDetector; import com.intellij.openapi.roots.libraries.ui.OrderRoot; -import com.intellij.openapi.roots.libraries.ui.RootDetector; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,26 +48,31 @@ public class RootDetectionUtil { public static List detectRoots(@NotNull final Collection rootCandidates, @Nullable Component parentComponent, @Nullable Project project, - @NotNull final List detectors, - boolean allowUserToSelectRootTypeIfNothingIsDetected) { - LOG.assertTrue(!detectors.isEmpty()); + @NotNull final LibraryRootsComponentDescriptor rootsComponentDescriptor) { + return detectRoots(rootCandidates, parentComponent, project, rootsComponentDescriptor.getRootsDetector(), + rootsComponentDescriptor.getRootTypes()); + } + + @NotNull + public static List detectRoots(@NotNull final Collection rootCandidates, @Nullable Component parentComponent, + @Nullable Project project, @NotNull final LibraryRootsDetector detector, + @NotNull OrderRootType[] rootTypesAllowedToBeSelectedByUserIfNothingIsDetected) { final List result = new ArrayList(); final List suggestedRoots = new ArrayList(); new Task.Modal(project, "Scanning for Roots", true) { @Override public void run(@NotNull ProgressIndicator indicator) { try { - for (RootDetector detector : detectors) { - for (VirtualFile rootCandidate : rootCandidates) { - final Collection roots = detector.detectRoots(rootCandidate, indicator); - final VirtualFile first = ContainerUtil.getFirstItem(roots); - if (first != null && roots.size() == 1 && first.equals(rootCandidate)) { - result.add(new OrderRoot(first, detector.getRootType(), detector.isJarDirectory())); - } - else { - for (VirtualFile root : roots) { - suggestedRoots.add(new SuggestedChildRootInfo(detector, rootCandidate, root)); - } + for (VirtualFile rootCandidate : rootCandidates) { + final Collection roots = detector.detectRoots(rootCandidate, indicator); + if (!roots.isEmpty() && allRootsEqualTo(roots, rootCandidate)) { + result.addAll(roots); + } + else { + for (OrderRoot root : roots) { + final String typeName = detector.getRootTypeName(root.getType(), root.isJarDirectory()); + LOG.assertTrue(typeName != null, "Unexpected root type " + root.getType().name() + (root.isJarDirectory() ? " (jar directory)" : "") + ", detectors: " + detector); + suggestedRoots.add(new SuggestedChildRootInfo(rootCandidate, root, typeName)); } } } @@ -84,33 +91,42 @@ public class RootDetectionUtil { return Collections.emptyList(); } for (SuggestedChildRootInfo rootInfo : dialog.getChosenRoots()) { - result - .add(new OrderRoot(rootInfo.getSuggestedRoot(), rootInfo.getDetector().getRootType(), rootInfo.getDetector().isJarDirectory())); + result.add(rootInfo.getSuggestedRoot()); } } - if (result.isEmpty() && allowUserToSelectRootTypeIfNothingIsDetected) { - List sortedDetectors = new ArrayList(detectors); - Collections.sort(sortedDetectors, new Comparator() { - @Override - public int compare(final RootDetector o1, final RootDetector o2) { - return o1.getPresentableRootTypeName().compareToIgnoreCase(o2.getPresentableRootTypeName()); + if (result.isEmpty() && rootTypesAllowedToBeSelectedByUserIfNothingIsDetected.length > 0) { + Map> types = new HashMap>(); + for (OrderRootType type : rootTypesAllowedToBeSelectedByUserIfNothingIsDetected) { + for (boolean isDirectory : new boolean[]{false, true}) { + final String typeName = detector.getRootTypeName(type, isDirectory); + if (typeName != null) { + types.put(typeName, Pair.create(type, isDirectory)); + } } - }); - - List names = new ArrayList(); - for (RootDetector detector : sortedDetectors) { - names.add(detector.getPresentableRootTypeName()); } + LOG.assertTrue(!types.isEmpty(), "No allowed root types found for " + detector); + List sortedNames = new ArrayList(types.keySet()); + Collections.sort(sortedNames, String.CASE_INSENSITIVE_ORDER); final int i = Messages.showChooseDialog("Choose category for selected files:", "Attach Files", - ArrayUtil.toStringArray(names), names.get(0), null); + ArrayUtil.toStringArray(sortedNames), sortedNames.get(0), null); if (i != -1) { - final RootDetector detector = sortedDetectors.get(i); + final Pair pair = types.get(sortedNames.get(i)); for (VirtualFile candidate : rootCandidates) { - result.add(new OrderRoot(candidate, detector.getRootType(), detector.isJarDirectory())); + result.add(new OrderRoot(candidate, pair.getFirst(), pair.getSecond())); } } } + return result; } + + private static boolean allRootsEqualTo(Collection roots, VirtualFile candidate) { + for (OrderRoot root : roots) { + if (!root.getFile().equals(candidate)) { + return false; + } + } + return true; + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java index 826fc8df7dc5..8f99894fb36f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java @@ -15,32 +15,32 @@ */ package com.intellij.openapi.roots.libraries.ui.impl; -import com.intellij.openapi.roots.libraries.ui.RootDetector; +import com.intellij.openapi.roots.libraries.ui.OrderRoot; import com.intellij.openapi.vfs.VirtualFile; /** * @author nik */ class SuggestedChildRootInfo { - private RootDetector myDetector; - private VirtualFile myRootCandidate; - private VirtualFile mySuggestedRoot; + private final VirtualFile myRootCandidate; + private final OrderRoot mySuggestedRoot; + private final String myRootTypeName; - SuggestedChildRootInfo(RootDetector detector, VirtualFile rootCandidate, VirtualFile suggestedRoot) { - myDetector = detector; + SuggestedChildRootInfo(VirtualFile rootCandidate, OrderRoot suggestedRoot, String rootTypeName) { myRootCandidate = rootCandidate; mySuggestedRoot = suggestedRoot; - } - - public RootDetector getDetector() { - return myDetector; + myRootTypeName = rootTypeName; } public VirtualFile getRootCandidate() { return myRootCandidate; } - public VirtualFile getSuggestedRoot() { + public OrderRoot getSuggestedRoot() { return mySuggestedRoot; } + + public String getRootTypeName() { + return myRootTypeName; + } } From ce1c58e96c667db096924fe693a7e86db7c0ec3f Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 30 Mar 2012 15:37:54 +0400 Subject: [PATCH 10/20] IDEA-83671 fix names of android inspection and intention --- .../AndroidAddStringResourceAction/after.java.template | 1 + .../AndroidAddStringResourceAction/before.java.template | 1 + .../AndroidAddStringResourceAction/description.html | 5 +++++ plugins/android/src/META-INF/plugin.xml | 8 +++++--- .../intentions/AndroidAddStringResourceAction.java | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/after.java.template create mode 100644 plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/before.java.template create mode 100644 plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/description.html diff --git a/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/after.java.template b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/after.java.template new file mode 100644 index 000000000000..a319f4c5d3eb --- /dev/null +++ b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/after.java.template @@ -0,0 +1 @@ +String s = getString(R.string.hello); \ No newline at end of file diff --git a/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/before.java.template b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/before.java.template new file mode 100644 index 000000000000..21d91b33213f --- /dev/null +++ b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/before.java.template @@ -0,0 +1 @@ +String s = "Hello, world"; \ No newline at end of file diff --git a/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/description.html b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/description.html new file mode 100644 index 000000000000..b73d30820e92 --- /dev/null +++ b/plugins/android/resources/intentionDescriptions/AndroidAddStringResourceAction/description.html @@ -0,0 +1,5 @@ + + +This intention extracts existing Java or XML string to a resource + + \ No newline at end of file diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index bdb604995847..8787c3bc246b 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -152,6 +152,7 @@ org.jetbrains.android.intentions.AndroidAddStringResourceAction + Android - + diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index 990d166a93de..428c40d72d73 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -95,7 +95,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl @NotNull @Override public String getFamilyName() { - return AndroidBundle.message("intention.family"); + return getText(); } public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { From 4b47bd35946c63d00c1f83b5807ef02fceabefd2 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 30 Mar 2012 15:39:42 +0400 Subject: [PATCH 11/20] IDEA-83473 disable android lint validation for java files --- .../android/inspections/lint/AndroidLintExternalAnnotator.java | 2 +- .../android/inspections/lint/AndroidLintInspectionBase.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java index c08b144fe3f6..a5e85267ca5c 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java @@ -75,7 +75,7 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator Date: Fri, 30 Mar 2012 15:53:55 +0400 Subject: [PATCH 12/20] Add additional logining to understand cause of failing maven tests. --- .../dom/MavenExtensionCompletionAndResolutionTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java index 58800d25137b..17f4591a57b2 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java @@ -73,7 +73,10 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic List actual = getCompletionVariants(myProjectPom); - if (!new HashSet(actual).equals(new HashSet(Arrays.asList("maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin")))) { + try { + assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); + } + catch (Throwable t) { MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); System.out.println("GetArtifacts: " + new HashSet(instance.getArtifactIds("org.apache.maven.plugins"))); System.out.println("Indexes: " + instance.getIndices()); @@ -86,8 +89,6 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + " Indexes: " + instance.getIndices()); } - - assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); } public void testArtifactWithoutGroupCompletion() throws Exception { From 5865575d553a21d0998e381145dc0d846d005b2e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:04:46 +0400 Subject: [PATCH 13/20] GitCommand: remove unused commands --- plugins/git4idea/src/git4idea/commands/GitCommand.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index 808b0d66516d..cee0d21c4c42 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -29,12 +29,9 @@ public class GitCommand { public static final GitCommand CHECKOUT = write("checkout"); public static final GitCommand COMMIT = write("commit"); public static final GitCommand CONFIG = meta("config"); - public static final GitCommand CHECK_ATTR = read("check-attr"); public static final GitCommand CHERRY_PICK = write("cherry-pick"); public static final GitCommand CLONE = write("clone"); - public static final GitCommand DESCRIBE = meta("describe"); public static final GitCommand DIFF = read("diff"); - public static final GitCommand DIFF_INDEX = read("diff-index"); public static final GitCommand FETCH = write("fetch"); public static final GitCommand INIT = write("init"); public static final GitCommand LOG = meta("log"); @@ -54,8 +51,6 @@ public class GitCommand { public static final GitCommand STATUS = read("status"); public static final GitCommand TAG = meta("tag"); public static final GitCommand UPDATE_INDEX = write("update-index"); - public static final GitCommand VERSION = meta("version"); - public static final GitCommand GC = write("gc"); /** * Name of environment variable that specifies editor for the git From 25835275473d49f7613939c2061c6b8bebad5a18 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:06:56 +0400 Subject: [PATCH 14/20] GitCommand: remove unused threading policy --- .../src/git4idea/commands/GitCommand.java | 39 ++++--------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index cee0d21c4c42..a9a4ee1ecea3 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -59,19 +59,16 @@ public class GitCommand { @NotNull @NonNls private final String myName; // command name passed to git @NotNull private final LockingPolicy myLocking; // Locking policy for the command - @NotNull private final ThreadPolicy myThreading; // Thread policy for the command /** * The constructor * * @param name the command myName * @param locking the myLocking policy - * @param threading the thread policy */ - private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking, @NotNull ThreadPolicy threading) { - this.myLocking = locking; - this.myName = name; - this.myThreading = threading; + private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking) { + myLocking = locking; + myName = name; } /** @@ -81,7 +78,7 @@ public class GitCommand { * @return the created command object */ private static GitCommand meta(String name) { - return new GitCommand(name, LockingPolicy.META, ThreadPolicy.ANY); + return new GitCommand(name, LockingPolicy.META); } /** @@ -91,7 +88,7 @@ public class GitCommand { * @return the create command objects */ private static GitCommand read(String name) { - return new GitCommand(name, LockingPolicy.READ, ThreadPolicy.BACKGROUND_ONLY); + return new GitCommand(name, LockingPolicy.READ); } /** @@ -101,7 +98,7 @@ public class GitCommand { * @return the created command object */ private static GitCommand write(String name) { - return new GitCommand(name, LockingPolicy.WRITE, ThreadPolicy.BACKGROUND_ONLY); + return new GitCommand(name, LockingPolicy.WRITE); } /** @@ -111,7 +108,7 @@ public class GitCommand { * @return the created command object */ private static GitCommand writeSuspendable(String name) { - return new GitCommand(name, LockingPolicy.WRITE_SUSPENDABLE, ThreadPolicy.BACKGROUND_ONLY); + return new GitCommand(name, LockingPolicy.WRITE_SUSPENDABLE); } /** @@ -130,14 +127,6 @@ public class GitCommand { return myLocking; } - /** - * @return the locking policy for the command - */ - @NotNull - public ThreadPolicy threadingPolicy() { - return myThreading; - } - /** * The myLocking policy for the command */ @@ -159,18 +148,4 @@ public class GitCommand { */ META, } - - /** - * Thread policy for command - */ - enum ThreadPolicy { - /** - * Any thread could be used - */ - ANY, - /** - * Only background thread could be used - */ - BACKGROUND_ONLY - } } From c77987bfcb2758cb255dca86753898a7bc51fe8a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:24:33 +0400 Subject: [PATCH 15/20] GitCommand: javadoc --- .../git4idea/src/git4idea/commands/GitCommand.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index a9a4ee1ecea3..ee562004f88d 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -19,7 +19,18 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; /** - * The descriptor of git command. It contains policy information about myLocking and GUI thread policy. + *

+ * The descriptor of git command. + *

+ *

+ * It contains policy information about locking which is handled in {@link GitHandler#runInCurrentThread(java.lang.Runnable)} to prevent + * simultaneous Git commands conflict on the index.lock file. + * write-commands can't be executed simultaneously, but a write-command doesn't prevent read-commands to execute. + *

+ *

+ * A lock-policy can be different for a single command, for example, {@code git stash} may change the index (and thus should hold the + * write lock), which {@code git stash list} doesn't (and therefore no lock is needed). + *

*/ public class GitCommand { From 5a43999b5c4f00785e82a73adddf5d72bce9a417 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:25:26 +0400 Subject: [PATCH 16/20] GitCommand: no more "META" locking policy, since it is equal to "READ" --- .../src/git4idea/commands/GitCommand.java | 30 +++++-------------- .../src/git4idea/commands/GitHandler.java | 2 -- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index ee562004f88d..69ad8a8445fa 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -36,31 +36,31 @@ public class GitCommand { public static final GitCommand ADD = write("add"); public static final GitCommand ANNOTATE = read("annotate"); - public static final GitCommand BRANCH = meta("branch"); + public static final GitCommand BRANCH = read("branch"); public static final GitCommand CHECKOUT = write("checkout"); public static final GitCommand COMMIT = write("commit"); - public static final GitCommand CONFIG = meta("config"); + public static final GitCommand CONFIG = read("config"); public static final GitCommand CHERRY_PICK = write("cherry-pick"); public static final GitCommand CLONE = write("clone"); public static final GitCommand DIFF = read("diff"); public static final GitCommand FETCH = write("fetch"); public static final GitCommand INIT = write("init"); - public static final GitCommand LOG = meta("log"); + public static final GitCommand LOG = read("log"); public static final GitCommand LS_FILES = read("ls-files"); - public static final GitCommand LS_REMOTE = meta("ls-remote"); + public static final GitCommand LS_REMOTE = read("ls-remote"); public static final GitCommand MERGE = write("merge"); - public static final GitCommand MERGE_BASE = meta("merge-base"); + public static final GitCommand MERGE_BASE = read("merge-base"); public static final GitCommand PULL = write("pull"); public static final GitCommand PUSH = write("push"); public static final GitCommand REBASE = writeSuspendable("rebase"); - public static final GitCommand REMOTE = meta("remote"); + public static final GitCommand REMOTE = read("remote"); public static final GitCommand RESET = write("reset"); - public static final GitCommand REV_LIST = meta("rev-list"); + public static final GitCommand REV_LIST = read("rev-list"); public static final GitCommand RM = write("rm"); public static final GitCommand SHOW = write("show"); public static final GitCommand STASH = write("stash"); public static final GitCommand STATUS = read("status"); - public static final GitCommand TAG = meta("tag"); + public static final GitCommand TAG = read("tag"); public static final GitCommand UPDATE_INDEX = write("update-index"); /** @@ -82,16 +82,6 @@ public class GitCommand { myName = name; } - /** - * Create command descriptor that performs metadata operations only - * - * @param name the command myName - * @return the created command object - */ - private static GitCommand meta(String name) { - return new GitCommand(name, LockingPolicy.META); - } - /** * Create command descriptor that performs reads from index * @@ -154,9 +144,5 @@ public class GitCommand { * Write lock should be acquired for the command, and it could be acquired in several intervals */ WRITE_SUSPENDABLE, - /** - * Metadata read/write command - */ - META, } } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index a71aa65e5030..fbd6d581fa36 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -620,7 +620,6 @@ public abstract class GitHandler { boolean suspendable = false; switch (myCommand.lockingPolicy()) { - case META: case READ: // need to lock only write operations: reads can be performed even when a write operation is going on break; @@ -713,7 +712,6 @@ public abstract class GitHandler { } finally { switch (myCommand.lockingPolicy()) { - case META: case READ: break; case WRITE_SUSPENDABLE: From f5b720e417bd75f51323da7ae58f0fe373c2ee0a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:31:32 +0400 Subject: [PATCH 17/20] GitCommand: fetch and show are read-commands show is obviously a reading command fetch doesn't modify the index, so it is a read-command, since avoiding conflicts around the index.lock is the purpose of the locking policy. push is also a read-command, but let it be "write" as an additional protection against "commit during push" problem, when a commit may be unintentionally pushed. --- plugins/git4idea/src/git4idea/commands/GitCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index 69ad8a8445fa..cccf4ef8b14b 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -43,7 +43,7 @@ public class GitCommand { public static final GitCommand CHERRY_PICK = write("cherry-pick"); public static final GitCommand CLONE = write("clone"); public static final GitCommand DIFF = read("diff"); - public static final GitCommand FETCH = write("fetch"); + public static final GitCommand FETCH = read("fetch"); // fetch is a read-command, because it doesn't modify the index public static final GitCommand INIT = write("init"); public static final GitCommand LOG = read("log"); public static final GitCommand LS_FILES = read("ls-files"); @@ -57,7 +57,7 @@ public class GitCommand { public static final GitCommand RESET = write("reset"); public static final GitCommand REV_LIST = read("rev-list"); public static final GitCommand RM = write("rm"); - public static final GitCommand SHOW = write("show"); + public static final GitCommand SHOW = read("show"); public static final GitCommand STASH = write("stash"); public static final GitCommand STATUS = read("status"); public static final GitCommand TAG = read("tag"); From 27ae8a9a44f6f0f3617ab993edfbbecc0a63562e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 13:35:43 +0400 Subject: [PATCH 18/20] GitCommand cleanup --- .../src/git4idea/commands/GitCommand.java | 94 +++++++------------ 1 file changed, 34 insertions(+), 60 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index cccf4ef8b14b..26cd4da68ab2 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -68,66 +68,6 @@ public class GitCommand { */ public static final String GIT_EDITOR_ENV = "GIT_EDITOR"; - @NotNull @NonNls private final String myName; // command name passed to git - @NotNull private final LockingPolicy myLocking; // Locking policy for the command - - /** - * The constructor - * - * @param name the command myName - * @param locking the myLocking policy - */ - private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking) { - myLocking = locking; - myName = name; - } - - /** - * Create command descriptor that performs reads from index - * - * @param name the command myName - * @return the create command objects - */ - private static GitCommand read(String name) { - return new GitCommand(name, LockingPolicy.READ); - } - - /** - * Create command descriptor that performs write operations - * - * @param name the command myName - * @return the created command object - */ - private static GitCommand write(String name) { - return new GitCommand(name, LockingPolicy.WRITE); - } - - /** - * Create command descriptor that performs write operations - * - * @param name the command myName - * @return the created command object - */ - private static GitCommand writeSuspendable(String name) { - return new GitCommand(name, LockingPolicy.WRITE_SUSPENDABLE); - } - - /** - * @return the command name - */ - @NotNull - public String name() { - return myName; - } - - /** - * @return the locking policy for the command - */ - @NotNull - public LockingPolicy lockingPolicy() { - return myLocking; - } - /** * The myLocking policy for the command */ @@ -145,4 +85,38 @@ public class GitCommand { */ WRITE_SUSPENDABLE, } + + @NotNull @NonNls private final String myName; // command name passed to git + @NotNull private final LockingPolicy myLocking; // Locking policy for the command + + private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking) { + myLocking = locking; + myName = name; + } + + @NotNull + private static GitCommand read(@NotNull String name) { + return new GitCommand(name, LockingPolicy.READ); + } + + @NotNull + private static GitCommand write(@NotNull String name) { + return new GitCommand(name, LockingPolicy.WRITE); + } + + @NotNull + private static GitCommand writeSuspendable(@NotNull String name) { + return new GitCommand(name, LockingPolicy.WRITE_SUSPENDABLE); + } + + @NotNull + public String name() { + return myName; + } + + @NotNull + public LockingPolicy lockingPolicy() { + return myLocking; + } + } From 030279297c4aba201f34cd84a6f1073b378bfbc9 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 14:40:17 +0400 Subject: [PATCH 19/20] IDEA-83755 GitCommand locking made modifiable Some commands don't need write locks in certain cases: for example, git stash list. For them let create an instance of GitCommand with read lock instead of write lock. Apply this locking policy to 'git stash list' and 'git checkout -b ' --- .../src/git4idea/commands/GitCommand.java | 17 +++++++++++++++++ .../git4idea/src/git4idea/commands/GitImpl.java | 2 +- .../src/git4idea/history/GitHistoryUtils.java | 4 ++-- .../src/git4idea/stash/GitStashUtils.java | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index 26cd4da68ab2..302caeccc76b 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -89,6 +89,18 @@ public class GitCommand { @NotNull @NonNls private final String myName; // command name passed to git @NotNull private final LockingPolicy myLocking; // Locking policy for the command + /** + * Creates a git command with LockingPolicy different from the default one. + * Use this constructor with care: specifying read-policy on a write operation may result in a conflict during simultaneous + * modification of index. + * @param command Original command. + * @param lockingPolicy Locking policy overriding default locking policy of the original command. + */ + private GitCommand(@NotNull GitCommand command, @NotNull LockingPolicy lockingPolicy) { + myName = command.name(); + myLocking = lockingPolicy; + } + private GitCommand(@NonNls @NotNull String name, @NotNull LockingPolicy locking) { myLocking = locking; myName = name; @@ -119,4 +131,9 @@ public class GitCommand { return myLocking; } + @NotNull + public GitCommand readLockingCommand() { + return new GitCommand(this, LockingPolicy.READ); + } + } diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index f610113b1cbe..c70436c9f58f 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -182,7 +182,7 @@ public class GitImpl implements Git { @Override public GitCommandResult checkoutNewBranch(@NotNull GitRepository repository, @NotNull String branchName, @Nullable GitLineHandlerListener listener) { - final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.CHECKOUT); + final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.CHECKOUT.readLockingCommand()); h.setSilent(false); h.addParameters("-b"); h.addParameters(branchName); diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 3c79476025e1..49003575ee9a 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -728,7 +728,7 @@ public class GitHistoryUtils { @Nullable public static Pair getStashTop(@NotNull Project project, @NotNull VirtualFile root) throws VcsException { - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH); + GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand()); GitLogParser parser = new GitLogParser(project, SHORT_HASH, SHORT_PARENTS); h.setSilent(true); h.setNoSSH(true); @@ -776,7 +776,7 @@ public class GitHistoryUtils { @Nullable public static List> loadStashStackAsCommits(@NotNull Project project, @NotNull VirtualFile root, SymbolicRefsI refs, final String... parameters) throws VcsException { - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH); + GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand()); GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SHORT_REF_LOG_SELECTOR, SUBJECT, BODY, RAW_BODY); h.setSilent(true); diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java index b952f3455b85..a36a87ec0576 100644 --- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java @@ -64,7 +64,7 @@ public class GitStashUtils { public static void loadStashStack(@NotNull Project project, @NotNull VirtualFile root, final Charset charset, final Consumer consumer) { - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH); + GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand()); h.setSilent(true); h.setNoSSH(true); h.addParameters("list"); From abe770805f8890124d0094c9f5fef79fe7ccbb6d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 30 Mar 2012 16:12:50 +0400 Subject: [PATCH 20/20] IDEA-77303 File copying : "Overwriting" removes the file without creating new one Files for deletion are stored in myDeletedFiles with system dependent paths. (cherry picked from commit 178e08c) --- .../vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java index 2e92cd784037..2378efaec35f 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java @@ -23,6 +23,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; @@ -444,12 +445,12 @@ public abstract class VcsVFSListener implements Disposable { } for (Iterator iter = myDeletedFiles.iterator(); iter.hasNext(); ) { - if (copiedAddedMoved.contains(iter.next().getPath())) { + if (copiedAddedMoved.contains(FileUtil.toSystemIndependentName(iter.next().getPath()))) { iter.remove(); } } for (Iterator iter = myDeletedWithoutConfirmFiles.iterator(); iter.hasNext(); ) { - if (copiedAddedMoved.contains(iter.next().getPath())) { + if (copiedAddedMoved.contains(FileUtil.toSystemIndependentName(iter.next().getPath()))) { iter.remove(); } }