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/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/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/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(); 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/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/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; 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) { 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); } 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; + } } 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); } } } 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..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 @@ -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,10 +69,15 @@ 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) { + Set jarPathsSet = myHandlers.keySet(); + jarPathsCache = jarPathsSet.toArray(new String[jarPathsSet.size()]); + } + jarPaths = jarPathsCache; } for (String jarPath : jarPaths) { @@ -119,6 +125,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo final JarHandler handler; synchronized (LOCK) { handler = myHandlers.remove(path); + jarPathsCache = null; } if (handler != null) { @@ -193,6 +200,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; 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(); } } 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/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 + * 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 { 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 CHECK_ATTR = read("check-attr"); + 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 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 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 = 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 SHOW = read("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"); - public static final GitCommand VERSION = meta("version"); - public static final GitCommand GC = write("gc"); /** * Name of environment variable that specifies editor for the git */ 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 - @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; - } - - /** - * 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, ThreadPolicy.ANY); - } - - /** - * 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, ThreadPolicy.BACKGROUND_ONLY); - } - - /** - * 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, ThreadPolicy.BACKGROUND_ONLY); - } - - /** - * 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, ThreadPolicy.BACKGROUND_ONLY); - } - - /** - * @return the command name - */ - @NotNull - public String name() { - return myName; - } - - /** - * @return the locking policy for the command - */ - @NotNull - public LockingPolicy lockingPolicy() { - return myLocking; - } - - /** - * @return the locking policy for the command - */ - @NotNull - public ThreadPolicy threadingPolicy() { - return myThreading; - } - /** * The myLocking policy for the command */ @@ -159,23 +84,56 @@ 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, } + @NotNull @NonNls private final String myName; // command name passed to git + @NotNull private final LockingPolicy myLocking; // Locking policy for the command + /** - * Thread policy for 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. */ - enum ThreadPolicy { - /** - * Any thread could be used - */ - ANY, - /** - * Only background thread could be used - */ - BACKGROUND_ONLY + 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; + } + + @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; + } + + @NotNull + public GitCommand readLockingCommand() { + return new GitCommand(this, LockingPolicy.READ); + } + } 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: 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"); 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..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 @@ -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; @@ -72,14 +73,22 @@ 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")))) { - MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject); - System.out.println("GetArtifacts: " + 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()); + 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()); - assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin"); + 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()); + } } public void testArtifactWithoutGroupCompletion() throws Exception {