diff --git a/build/conf/mac/Contents/MacOS/idea b/build/conf/mac/Contents/MacOS/idea index 0699ef280f54..bd5a2a3f744d 100755 Binary files a/build/conf/mac/Contents/MacOS/idea and b/build/conf/mac/Contents/MacOS/idea differ diff --git a/build/order.txt b/build/order.txt index ff0a75037144..a6093ab8ce7e 100644 --- a/build/order.txt +++ b/build/order.txt @@ -1563,7 +1563,6 @@ com/intellij/openapi/project/impl/ProjectManagerImpl$1.class:/lib/idea.jar com/intellij/openapi/project/impl/ProjectManagerImpl$2.class:/lib/idea.jar com/intellij/openapi/project/impl/ProjectManagerImpl$6.class:/lib/idea.jar idea/IdeaApplicationInfo.xml:/lib/resources.jar -idea/PropertiesComponent.xml:/lib/resources.jar com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.class:/lib/idea.jar com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl$2.class:/lib/idea.jar com/intellij/ide/highlighter/custom/impl/ReadFileType.class:/lib/idea.jar diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java index 68c15d4e73c9..6649ff3516ac 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebuggerEvaluator.java @@ -25,12 +25,10 @@ import com.intellij.debugger.impl.EditorTextProvider; import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -39,7 +37,6 @@ import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.EvaluationMode; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; -import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -133,14 +130,11 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator { } @Override - public XExpression getEditorExpression(@NotNull Editor editor, @Nullable PsiFile psiFile) { - String text = editor.getSelectionModel().getSelectedText(); - if (psiFile == null || StringUtil.isEmpty(text)) { - return super.getEditorExpression(editor, psiFile); + public EvaluationMode getEvaluationMode(@NotNull String text, int startOffset, int endOffset, @Nullable PsiFile psiFile) { + if (psiFile != null) { + PsiElement[] range = CodeInsightUtil.findStatementsInRange(psiFile, startOffset, endOffset); + return range.length > 1 ? EvaluationMode.CODE_FRAGMENT : EvaluationMode.EXPRESSION; } - PsiElement[] range = CodeInsightUtil.findStatementsInRange(psiFile, editor.getSelectionModel().getSelectionStart(), - editor.getSelectionModel().getSelectionEnd()); - return new XExpressionImpl(formatTextForEvaluation(text), XDebuggerEditorBase.getFileTypeLanguage(psiFile.getFileType()), null, - range.length > 1 ? EvaluationMode.CODE_FRAGMENT : EvaluationMode.EXPRESSION); + return super.getEvaluationMode(text, startOffset, endOffset, null); } } diff --git a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java b/java/idea-ui/src/com/intellij/ide/RecentProjectsManagerImpl.java similarity index 83% rename from java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java rename to java/idea-ui/src/com/intellij/ide/RecentProjectsManagerImpl.java index e2f93bf16771..963b88e35ca3 100644 --- a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java +++ b/java/idea-ui/src/com/intellij/ide/RecentProjectsManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -24,13 +24,13 @@ import org.jetbrains.annotations.NotNull; @State( name = "RecentProjectsManager", storages = { - @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", roamingType = RoamingType.DISABLED), + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml"), @Storage(file = StoragePathMacros.APP_CONFIG + "/recentProjects.xml", roamingType = RoamingType.DISABLED) }, storageChooser = LastStorageChooserForWrite.class ) -public class RecentProjectsManager extends RecentProjectsManagerBase { - public RecentProjectsManager(MessageBus messageBus) { +public class RecentProjectsManagerImpl extends RecentProjectsManagerBase { + public RecentProjectsManagerImpl(MessageBus messageBus) { super(messageBus); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java index cad34394837e..d72269f41733 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java @@ -352,7 +352,7 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se public void reset() { // need this to ensure VFS operations will not block because of storage flushing // and other maintenance IO tasks run in background - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Resetting Project Structure"); try { myWasUiDisposed = false; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java index 14da43194fe7..6c045fa4270b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java @@ -15,11 +15,16 @@ */ package com.intellij.codeInspection.unusedSymbol; +import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInspection.BaseJavaLocalInspectionTool; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase; +import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool; +import org.intellij.lang.annotations.Pattern; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; -public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool { +public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool { @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME; @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME; @NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters"; @@ -30,4 +35,48 @@ public class UnusedSymbolLocalInspectionBase extends BaseJavaLocalInspectionTool public boolean CLASS = true; public boolean PARAMETER = true; public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true; + + + @Override + @NotNull + public String getGroupDisplayName() { + return GroupNames.DECLARATION_REDUNDANCY; + } + + @Override + @NotNull + public String getDisplayName() { + return DISPLAY_NAME; + } + + @Override + @NotNull + @NonNls + public String getShortName() { + return SHORT_NAME; + } + + @Override + @Pattern(VALID_ID_PATTERN) + @NotNull + @NonNls + public String getID() { + return "unused"; + } + + @Override + public String getAlternativeID() { + return UnusedDeclarationInspectionBase.ALTERNATIVE_ID; + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + @NotNull + @Override + public String getInspectionForBatchShortName() { + return UnusedDeclarationInspectionBase.SHORT_NAME; + } } diff --git a/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java index eaf2dbc121ff..5f409f835b73 100644 --- a/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java @@ -40,7 +40,7 @@ public class JavaCodeStyleSettingsProvider extends CodeStyleSettingsProvider { @Override public DisplayPriority getPriority() { - return PlatformUtils.isIdeaUltimate() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS; + return PlatformUtils.isIntelliJ() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS; } @Override diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java index f59f912b7d68..f422a4ca09b3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java @@ -16,12 +16,6 @@ package com.intellij.codeInspection.unusedSymbol; -import com.intellij.codeInsight.daemon.GroupNames; -import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; -import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool; -import org.intellij.lang.annotations.Pattern; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -32,7 +26,7 @@ import java.awt.event.ActionListener; * User: anna * Date: 17-Feb-2006 */ -public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase implements PairedUnfairLocalInspectionTool { +public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase { /** * use {@link com.intellij.codeInspection.deadCode.UnusedDeclarationInspection} instead @@ -41,49 +35,6 @@ public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase public UnusedSymbolLocalInspection() { } - @Override - @NotNull - public String getGroupDisplayName() { - return GroupNames.DECLARATION_REDUNDANCY; - } - - @Override - @NotNull - public String getDisplayName() { - return DISPLAY_NAME; - } - - @Override - @NotNull - @NonNls - public String getShortName() { - return SHORT_NAME; - } - - @Override - @Pattern(VALID_ID_PATTERN) - @NotNull - @NonNls - public String getID() { - return "unused"; - } - - @Override - public String getAlternativeID() { - return UnusedDeclarationInspection.ALTERNATIVE_ID; - } - - @Override - public boolean isEnabledByDefault() { - return true; - } - - @NotNull - @Override - public String getInspectionForBatchShortName() { - return UnusedDeclarationInspection.SHORT_NAME; - } - public class OptionsPanel { private JCheckBox myCheckLocalVariablesCheckBox; private JCheckBox myCheckClassesCheckBox; diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java index 1810832e75cc..f4ad6bf6e954 100644 --- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java @@ -184,7 +184,7 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett @Override public DisplayPriority getDisplayPriority() { - if (PlatformUtils.isIdeaUltimate()) return DisplayPriority.KEY_LANGUAGE_SETTINGS; + if (PlatformUtils.isIntelliJ()) return DisplayPriority.KEY_LANGUAGE_SETTINGS; return DisplayPriority.LANGUAGE_SETTINGS; } diff --git a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java index 5d1c5051ee2e..8811ebcfad89 100644 --- a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java @@ -16,13 +16,8 @@ package com.intellij.psi; import com.intellij.openapi.application.ex.PathManagerEx; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.testFramework.PsiTestCase; -public class OptimizeImportsTest extends PsiTestCase{ +public class OptimizeImportsTest extends OptimizeImportsTestCase { private static final String BASE_PATH = PathManagerEx.getTestDataPath() + "/psi/optimizeImports"; @Override @@ -44,37 +39,6 @@ public class OptimizeImportsTest extends PsiTestCase{ public void testNewImportListIsEmptyAndJavaDocWithInvalidCodePreserved() throws Exception { doTest(); } private void doTest() throws Exception { - final String extension = ".java"; - doTest(extension); - } - - private void doTest(final String extension) throws Exception { - CommandProcessor.getInstance().executeCommand( - getProject(), new Runnable() { - @Override - public void run() { - WriteCommandAction.runWriteCommandAction(null, new Runnable() { - @Override - public void run() { - String fileName = getTestName(false) + extension; - try { - String text = loadFile(fileName); - PsiFile file = createFile(fileName, text); - - JavaCodeStyleManager.getInstance(myProject).optimizeImports(file); - PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); - PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); - String textAfter = loadFile(getTestName(false) + "_after" + extension); - String fileText = file.getText(); - assertEquals(textAfter, fileText); - } - catch (Exception e) { - LOG.error(e); - } - } - }); - } - }, "", ""); - + doTest(".java"); } } diff --git a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTestCase.java b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTestCase.java new file mode 100644 index 000000000000..5c03989d6144 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTestCase.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2014 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.psi; + +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.testFramework.PsiTestCase; + +/** + * @author Dmitry Avdeev + */ +public abstract class OptimizeImportsTestCase extends PsiTestCase { + protected void doTest(final String extension) throws Exception { + CommandProcessor.getInstance().executeCommand( + getProject(), new Runnable() { + @Override + public void run() { + WriteCommandAction.runWriteCommandAction(null, new Runnable() { + @Override + public void run() { + String fileName = getTestName(false) + extension; + try { + String text = loadFile(fileName); + PsiFile file = createFile(fileName, text); + + JavaCodeStyleManager.getInstance(myProject).optimizeImports(file); + PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + String textAfter = loadFile(getTestName(false) + "_after" + extension); + String fileText = file.getText(); + assertEquals(textAfter, fileText); + } + catch (Exception e) { + LOG.error(e); + } + } + }); + } + }, "", ""); + + } +} diff --git a/native/MacLauncher/Launcher.m b/native/MacLauncher/Launcher.m index 7e899f9da040..35508a1f483a 100644 --- a/native/MacLauncher/Launcher.m +++ b/native/MacLauncher/Launcher.m @@ -67,7 +67,7 @@ static NSString *const JVMOptions = @"JVMOptions"; void appendBundle(NSString *path, NSMutableArray *sink) { - if ([path hasSuffix:@".jdk"] || [path hasSuffix:@".jre"]) { + if ([path hasSuffix:@"jdk"] || [path hasSuffix:@".jre"]) { NSBundle *bundle = [NSBundle bundleWithPath:path]; if (bundle != nil) { [sink addObject:bundle]; diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java index cbd26398f451..9a2213ce1634 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java @@ -43,7 +43,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.WeakStringInterner; +import com.intellij.util.containers.StringInterner; import com.intellij.util.graph.CachingSemiGraph; import com.intellij.util.graph.DFSTBuilder; import com.intellij.util.graph.GraphGenerator; @@ -267,15 +267,12 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel, ((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().readExternal(highlightElement); } - WeakStringInterner interner = new WeakStringInterner(); - for (final Object o : element.getChildren(INSPECTION_TOOL_TAG)) { + StringInterner interner = new StringInterner(); + for (Element toolElement : element.getChildren(INSPECTION_TOOL_TAG)) { // make clone to avoid retaining memory via o.parent pointers - Element toolElement = ((Element)o).clone(); + toolElement = toolElement.clone(); JDOMUtil.internElement(toolElement, interner); - - String toolClassName = toolElement.getAttributeValue(CLASS_TAG); - - myDeinstalledInspectionsSettings.put(toolClassName, toolElement); + myDeinstalledInspectionsSettings.put(toolElement.getAttributeValue(CLASS_TAG), toolElement); } } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileMoveEvent.java b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileMoveEvent.java index dd145f88bc69..886b18e68eb8 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileMoveEvent.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileMoveEvent.java @@ -96,4 +96,8 @@ public class VFileMoveEvent extends VFileEvent { result = 31 * result + myNewParent.hashCode(); return result; } + + public String getOldPath() { + return myOldParent.getPath() + "/" + myFile.getName(); + } } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java index 90d10a76d3a8..f0fa9160cc4f 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java @@ -139,4 +139,14 @@ public class VFilePropertyChangeEvent extends VFileEvent { return "VfsEvent[property(" + myPropertyName + ") changed for '" + myFile + "':" + " oldValue = " + myOldValue + ", newValue = " + myNewValue + "]"; } + + public String getOldPath() { + String path = getPath(); + if (VirtualFile.PROP_NAME.equals(myPropertyName) && myNewValue instanceof String && myOldValue instanceof String) { + String newName = (String)myNewValue; + int i = path.lastIndexOf(newName); + if (i != -1) path = new StringBuilder(path).replace(i, i + newName.length(), (String)myOldValue).toString(); + } + return path; + } } diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java index 0d8cdf7be6c1..de909940c0f5 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java @@ -31,6 +31,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.NullableLazyValue; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.SmartList; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.StringInterner; import com.intellij.util.containers.WeakStringInterner; @@ -120,19 +121,19 @@ public class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { } @Nullable - private static List copyElements(final Element[] elements, final WeakStringInterner interner) { - if (elements != null) { - List result = new ArrayList(); - for (Element extensionsRoot : elements) { - for (final Object o : extensionsRoot.getChildren()) { - Element element = (Element)o; - JDOMUtil.internElement(element, interner); - result.add(element); - } - } - return result; + private static List copyElements(@Nullable Element[] elements, StringInterner interner) { + if (elements == null || elements.length == 0) { + return null; } - return null; + + List result = new SmartList(); + for (Element extensionsRoot : elements) { + for (Element element : extensionsRoot.getChildren()) { + JDOMUtil.internElement(element, interner); + result.add(element); + } + } + return result; } @SuppressWarnings({"HardCodedStringLiteral"}) @@ -167,7 +168,7 @@ public class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { public void readExternal(@NotNull Document document, @NotNull URL url, boolean ignoreMissingInclude) throws InvalidDataException, FileNotFoundException { document = JDOMXIncluder.resolve(document, url.toExternalForm(), ignoreMissingInclude); Element rootElement = document.getRootElement(); - JDOMUtil.internElement(rootElement, new WeakStringInterner()); + JDOMUtil.internElement(rootElement, new StringInterner()); readExternal(document.getRootElement()); } @@ -267,7 +268,7 @@ public class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { if (myProjectComponents == null) myProjectComponents = ComponentConfig.EMPTY_ARRAY; if (myModuleComponents == null) myModuleComponents = ComponentConfig.EMPTY_ARRAY; - WeakStringInterner interner = new WeakStringInterner(); + StringInterner interner = new StringInterner(); List extensions = copyElements(pluginBean.extensions, interner); if (extensions != null) { myExtensions = new MultiMap(); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java index e0c4ea8dfca3..bd30a10362b3 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -38,7 +38,6 @@ import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.impl.status.StatusBarUtil; import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.storage.HeavyProcessLatch; import com.intellij.util.text.DateFormatUtil; import com.intellij.vcs.log.TimedVcsCommit; @@ -191,7 +190,7 @@ public class DvcsUtil { } public static void workingTreeChangeStarted(@NotNull Project project) { - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Changing DVCS working tree"); ApplicationManager.getApplication().getMessageBus().syncPublisher(BatchFileChangeListener.TOPIC).batchChangeStarted(project); } diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/Presentation.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/Presentation.java index f0667e67d8db..f01edcea731e 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/Presentation.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/Presentation.java @@ -214,6 +214,10 @@ public final class Presentation implements Cloneable { public void setIcon(@Nullable Icon icon) { Icon oldIcon = myIcon; + if (oldIcon == icon) { + return; + } + myIcon = icon; myChangeSupport.firePropertyChange(PROP_ICON, oldIcon, myIcon); } diff --git a/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java b/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java index b42cd249ca8e..af28f681420b 100644 --- a/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java +++ b/platform/lang-api/src/com/intellij/execution/configuration/RunConfigurationExtensionsManager.java @@ -65,7 +65,7 @@ public class RunConfigurationExtensionsManager copy = new ArrayList(children.size()); for (Element child : children) { - Element clone = (Element)child.clone(); + Element clone = child.clone(); JDOMUtil.internElement(clone, myInterner); copy.add(clone); } @@ -87,8 +87,7 @@ public class RunConfigurationExtensionsManager elements = configuration.getCopyableUserData(RUN_EXTENSIONS); if (elements != null) { for (Element el : elements) { - final String name = el.getAttributeValue(getIdAttrName()); - map.put(name, (Element)el.clone()); + map.put(el.getAttributeValue(getIdAttrName()), el.clone()); } } 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 6f23ac69f745..74619373c3d6 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 @@ -15,8 +15,8 @@ */ package com.intellij.ide.util.projectWizard; -import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; +import com.intellij.ide.RecentProjectsManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.project.Project; @@ -93,7 +93,7 @@ public class WizardContext extends UserDataHolderBase { if (myProjectFileDirectory != null) { return myProjectFileDirectory; } - final String lastProjectLocation = GeneralSettings.getInstance().getLastProjectCreationLocation(); + final String lastProjectLocation = RecentProjectsManager.getInstance().getLastProjectCreationLocation(); if (lastProjectLocation != null) { return lastProjectLocation.replace('/', File.separatorChar); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index 95f733e56ebd..9b8bb18ff196 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -597,7 +597,9 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea for (final CustomCodeStyleSettings settings : customSettings) { final CustomCodeStyleSettings parentCustomSettings = parentSettings.getCustomSettings(settings.getClass()); - assert parentCustomSettings != null : "Custom settings are null for " + settings.getClass(); + if (parentCustomSettings == null) { + throw new WriteExternalException("Custom settings are null for " + settings.getClass()); + } settings.writeExternal(element, parentCustomSettings); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java index 2e6d88ababd4..da69c0db290a 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java @@ -23,7 +23,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionException; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.WeakStringInterner; +import com.intellij.util.SmartList; +import com.intellij.util.containers.StringInterner; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -229,7 +230,7 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C myConfiguration.readExternal(element); List runners = element.getChildren(RUNNER_ELEMENT); myUnloadedRunnerSettings = null; - WeakStringInterner interner = new WeakStringInterner(); + StringInterner interner = new StringInterner(); for (final Element runnerElement : runners) { String id = runnerElement.getAttributeValue(RUNNER_ID); ProgramRunner runner = RunnerRegistry.getInstance().findRunnerById(id); @@ -241,7 +242,7 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C myRunnerSettings.put(runner, settings); } else { - if (myUnloadedRunnerSettings == null) myUnloadedRunnerSettings = new ArrayList(1); + if (myUnloadedRunnerSettings == null) myUnloadedRunnerSettings = new SmartList(); JDOMUtil.internElement(runnerElement, interner); myUnloadedRunnerSettings.add(runnerElement); } diff --git a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java index 54ae97d446b5..e804c063d0be 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java +++ b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java @@ -463,7 +463,7 @@ public class MemberChooser extends DialogWrapper implemen ShowContainersAction showContainersAction = getShowContainersAction(); showContainersAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.ALT_MASK)), myTree); - setShowClasses(PropertiesComponent.getInstance().isTrueValue(PROP_SHOWCLASSES)); + setShowClasses(PropertiesComponent.getInstance().getBoolean(PROP_SHOWCLASSES, true)); group.add(showContainersAction); } } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 5b46d5bfb186..cc005b1929ad 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -1521,8 +1521,9 @@ public abstract class ChooseByNameBase { ApplicationAdapter listener = new ApplicationAdapter() { @Override public void beforeWriteActionStart(Object action) { - cancel(); - scheduleRestart(); + if (cancel()) { + scheduleRestart(); //don't restart if already canceled explicitly + } ApplicationManager.getApplication().removeApplicationListener(this); } }; diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java index cecfc4497d50..2c1880fd8f31 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java @@ -57,7 +57,7 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler { private static boolean isPrimaryModule(Module[] modules) { if (!ProjectAttachProcessor.canAttachToProject()) { - return !PlatformUtils.isIdeaUltimate(); + return !PlatformUtils.isIntelliJ(); } for (Module module : modules) { final File moduleFile = new File(module.getModuleFilePath()); diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 046f0db57912..28118dd382d9 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -86,6 +86,8 @@ import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.IOException; import java.io.StringReader; import java.util.*; @@ -902,8 +904,15 @@ public class SingleInspectionProfilePanel extends JPanel { } }); - - final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable).disableUpDownActions(); + final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable).disableUpDownActions().setRemoveActionUpdater( + new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + final int selectedRow = scopesAndScopesAndSeveritiesTable.getSelectedRow(); + final int rowCount = scopesAndScopesAndSeveritiesTable.getRowCount(); + return rowCount - 1 != selectedRow; + } + }); final JPanel panel = wrappedTable.createPanel(); panel.setMinimumSize(new Dimension(getMinimumSize().width, 3 * scopesAndScopesAndSeveritiesTable.getRowHeight())); severityPanel.add(new JBLabel("Severity by Scope"), @@ -961,7 +970,20 @@ public class SingleInspectionProfilePanel extends JPanel { configPanelAnchor.removeAll(); final JComponent additionalConfigPanel = state.getAdditionalConfigPanel(); if (additionalConfigPanel != null) { - configPanelAnchor.add(ScrollPaneFactory.createScrollPane(additionalConfigPanel, SideBorder.NONE)); + final JScrollPane pane = ScrollPaneFactory.createScrollPane(additionalConfigPanel, SideBorder.NONE); + FocusManager.getCurrentManager().addPropertyChangeListener("focusOwner", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!(evt.getNewValue() instanceof JComponent)) { + return; + } + final JComponent component = (JComponent)evt.getNewValue(); + if (component.isAncestorOf(pane)) { + pane.scrollRectToVisible(component.getBounds()); + } + } + }); + configPanelAnchor.add(pane); } UIUtil.setEnabled(configPanelAnchor, state.isEnabled(), true); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java index 72a93cfac537..a79e85e91f4d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java @@ -19,7 +19,6 @@ package com.intellij.psi.impl.include; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VfsUtilCore; @@ -33,7 +32,10 @@ import com.intellij.psi.PsiManager; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.*; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.ParameterizedCachedValue; +import com.intellij.psi.util.ParameterizedCachedValueProvider; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; @@ -74,6 +76,7 @@ public class FileIncludeManagerImpl extends FileIncludeManager { return VfsUtilCore.toVirtualFileArray(files); } }; + private final Map myProviderMap; public void processIncludes(PsiFile file, Processor processor) { GlobalSearchScope scope = GlobalSearchScope.allScope(myProject); @@ -127,9 +130,9 @@ public class FileIncludeManagerImpl extends FileIncludeManager { myPsiFileFactory = psiFileFactory; FileIncludeProvider[] providers = Extensions.getExtensions(FileIncludeProvider.EP_NAME); - Map providerMap = new HashMap(providers.length); + myProviderMap = new HashMap(providers.length); for (FileIncludeProvider provider : providers) { - FileIncludeProvider old = providerMap.put(provider.getId(), provider); + FileIncludeProvider old = myProviderMap.put(provider.getId(), provider); assert old == null; } myCachedValuesManager = cachedValuesManager; @@ -163,14 +166,8 @@ public class FileIncludeManagerImpl extends FileIncludeManager { @Nullable private PsiFileSystemItem doResolve(@NotNull final FileIncludeInfo info, @NotNull final PsiFile context) { if (info instanceof FileIncludeInfoImpl) { - final FileIncludeProvider provider = - ContainerUtil.find(FileIncludeProvider.EP_NAME.getExtensions(), new Condition() { - @Override - public boolean value(final FileIncludeProvider provider) { - return provider.getId().equals(((FileIncludeInfoImpl)info).providerId); - } - }); - + String id = ((FileIncludeInfoImpl)info).providerId; + FileIncludeProvider provider = id == null ? null : myProviderMap.get(id); final PsiFileSystemItem resolvedByProvider = provider == null ? null : provider.resolveIncludedFile(info, context); if (resolvedByProvider != null) { return resolvedByProvider; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java index 8735d9eaa769..3afbee098ac6 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java @@ -151,7 +151,7 @@ public class PsiElementRenameHandler implements RenameHandler { rename(element, project, nameSuggestionContext, editor, null); } - private static void rename(PsiElement element, final Project project, PsiElement nameSuggestionContext, Editor editor, String defaultName) { + public static void rename(PsiElement element, final Project project, PsiElement nameSuggestionContext, Editor editor, String defaultName) { RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element); PsiElement substituted = processor.substituteElementToRename(element, editor); if (substituted == null || !canRename(project, editor, substituted)) return; diff --git a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java index f60ec2cd6bf1..fb18109fd7bf 100644 --- a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java +++ b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java @@ -48,7 +48,6 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli private final PropertyChangeSupport myPropertyChangeSupport; private boolean myUseDefaultBrowser = true; private boolean myConfirmExtractFiles = true; - private String myLastProjectLocation; private boolean mySearchInBackground; private boolean myConfirmExit = true; private int myConfirmOpenNewProject = OPEN_PROJECT_ASK; @@ -73,7 +72,6 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli @NonNls private static final String OPTION_CONFIRM_EXIT = "confirmExit"; @NonNls private static final String OPTION_CONFIRM_OPEN_NEW_PROJECT = "confirmOpenNewProject2"; @NonNls private static final String OPTION_CYCLIC_BUFFER_SIZE = "cyclicBufferSize"; - @NonNls private static final String OPTION_LAST_PROJECT_LOCATION = "lastProjectLocation"; public static GeneralSettings getInstance(){ return ApplicationManager.getApplication().getComponent(GeneralSettings.class); @@ -103,15 +101,21 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli return myBrowserPath; } + @SuppressWarnings("unused") + @Deprecated /** - * @return a path pointing to a directory where the last project was created or null if not available + * Use RecentProjectsManagerBase */ public String getLastProjectCreationLocation() { - return myLastProjectLocation; + return null; } + @SuppressWarnings("unused") + @Deprecated + /** + * Use RecentProjectsManagerBase + */ public void setLastProjectCreationLocation(String lastProjectLocation) { - myLastProjectLocation = lastProjectLocation; } public void setBrowserPath(String browserPath) { @@ -323,15 +327,6 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli myConfirmOpenNewProject = OPEN_PROJECT_ASK; } } - - if (OPTION_LAST_PROJECT_LOCATION.equals(name)) { - try { - myLastProjectLocation = value; - } - catch (Exception ex) { - myLastProjectLocation = null; - } - } } if (!safeWriteSettingRead && "true".equals(System.getProperty("idea.no.safe.write"))) { @@ -417,13 +412,6 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli optionElement.setAttribute(ATTRIBUTE_NAME, OPTION_CONFIRM_OPEN_NEW_PROJECT); optionElement.setAttribute(ATTRIBUTE_VALUE, Integer.toString(myConfirmOpenNewProject)); parentNode.addContent(optionElement); - - if (myLastProjectLocation != null) { - optionElement = new Element(ELEMENT_OPTION); - optionElement.setAttribute(ATTRIBUTE_NAME, OPTION_LAST_PROJECT_LOCATION); - optionElement.setAttribute(ATTRIBUTE_VALUE, myLastProjectLocation); - parentNode.addContent(optionElement); - } } @Override diff --git a/platform/platform-api/src/com/intellij/ide/RecentProjectsManager.java b/platform/platform-api/src/com/intellij/ide/RecentProjectsManager.java new file mode 100644 index 000000000000..69e89f6b2383 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ide/RecentProjectsManager.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.components.ServiceManager; +import org.jetbrains.annotations.Nullable; + +public abstract class RecentProjectsManager { + public static RecentProjectsManager getInstance() { + return ServiceManager.getService(RecentProjectsManager.class); + } + + @Nullable + public abstract String getLastProjectCreationLocation(); + + public abstract void setLastProjectCreationLocation(@Nullable String lastProjectLocation); + + public abstract void clearNameCache(); + + public abstract void updateLastProjectPath(); + + public abstract String getLastProjectPath(); + + public abstract void removePath(@Nullable String path); + + /** + * @param addClearListItem whether the "Clear List" action should be added to the end of the list. + */ + public abstract AnAction[] getRecentProjectsActions(boolean addClearListItem); +} \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java index 59f99ad46a05..c9a8dab429f4 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java @@ -19,6 +19,7 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; +import com.intellij.ui.RelativeFont; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.NonOpaquePanel; @@ -133,14 +134,13 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{ myText.removeAll(); for (int i = 0; i < text.length; i++) { final JLabel eachLabel = new JLabel(text[i], SwingConstants.CENTER); - final int gap = eachLabel.getIconTextGap(); - eachLabel.setBorder(new EmptyBorder(0, 0, 0, gap)); - eachLabel.setVerticalTextPosition(SwingConstants.TOP); - eachLabel.setFont(eachLabel.getFont().deriveFont(Font.BOLD, eachLabel.getFont().getSize())); + eachLabel.setBorder(new EmptyBorder(0, 0, 0, 5)); + eachLabel.setFont(RelativeFont.BOLD.derive(eachLabel.getFont())); myText.add(eachLabel); if (i < text.length - 1) { - final JLabel eachIcon = new JLabel(AllIcons.General.ComboArrowRight, SwingConstants.CENTER); - eachIcon.setBorder(new EmptyBorder(0, 0, 0, gap)); + final JLabel eachIcon = new JLabel("\u203A", SwingConstants.CENTER); + eachIcon.setFont(RelativeFont.HUGE.derive(eachIcon.getFont())); + eachIcon.setBorder(new EmptyBorder(0, 0, 0, 5)); myText.add(eachIcon); } } diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java index ca5c77e8cd0a..427786101d12 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/ArchiveFileSystem.java @@ -74,7 +74,7 @@ public abstract class ArchiveFileSystem extends NewVirtualFileSystem { protected abstract String extractLocalPath(@NotNull String rootPath); @NotNull - protected abstract String convertLocalPathToRootPath(@NotNull String localPath); + protected abstract String convertLocalToRootPath(@NotNull String localPath); @NotNull protected abstract ArchiveHandler getHandler(@NotNull VirtualFile entryFile); diff --git a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java index 0416008d1d57..cf6d4ef6af1f 100644 --- a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -56,6 +56,7 @@ public class LinkLabel extends JLabel { private boolean myClickIsBeingProcessed; private boolean myPaintDefaultIcon; protected static final int DEFAULT_ICON_GAP = 2; + protected boolean myPaintUnderline = true; public LinkLabel() { this("", AllIcons.Ide.Link); @@ -141,7 +142,7 @@ public class LinkLabel extends JLabel { int x = myIconWidth; int y = getTextBaseLine(); - if (myUnderline) { + if (myUnderline && myPaintUnderline) { int k = 1; if (getFont().getSize() > 11) { k += (getFont().getSize() - 11); @@ -181,6 +182,9 @@ public class LinkLabel extends JLabel { return size; } + public void setPaintUnderline(boolean paintUnderline) { + myPaintUnderline = paintUnderline; + } public void removeNotify() { super.removeNotify(); diff --git a/platform/platform-api/src/com/intellij/ui/components/panels/HorizontalLayout.java b/platform/platform-api/src/com/intellij/ui/components/panels/HorizontalLayout.java index 63f982b806f3..9652562b6d2a 100644 --- a/platform/platform-api/src/com/intellij/ui/components/panels/HorizontalLayout.java +++ b/platform/platform-api/src/com/intellij/ui/components/panels/HorizontalLayout.java @@ -20,13 +20,20 @@ import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; -import java.awt.LayoutManager; +import java.awt.LayoutManager2; import java.util.ArrayList; /** + * This class is intended to lay out added components horizontally. + * It allows to add them into the LEFT, CENTER, or RIGHT group, which are aligned separately. + * Every group can contain any amount of components. The specified gap is added between components, + * and the double gap is added between groups of components. + *

NB!: this class must be modified together with the VerticalLayout class accordingly

+ * * @author Sergey.Malenkov + * @see VerticalLayout */ -public final class HorizontalLayout implements LayoutManager { +public final class HorizontalLayout implements LayoutManager2 { public static final String LEFT = "LEFT"; public static final String RIGHT = "RIGHT"; public static final String CENTER = "CENTER"; @@ -73,6 +80,35 @@ public final class HorizontalLayout implements LayoutManager { } } + @Override + public void addLayoutComponent(Component component, Object constraints) { + if ((constraints == null) || (constraints instanceof String)) { + addLayoutComponent((String)constraints, component); + } + else { + throw new IllegalArgumentException("unsupported constraints: " + constraints); + } + } + + @Override + public Dimension maximumLayoutSize(Container target) { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Override + public float getLayoutAlignmentX(Container target) { + return .5f; + } + + @Override + public float getLayoutAlignmentY(Container target) { + return .5f; + } + + @Override + public void invalidateLayout(Container target) { + } + @Override public void addLayoutComponent(String name, Component component) { synchronized (component.getTreeLock()) { @@ -154,19 +190,21 @@ public final class HorizontalLayout implements LayoutManager { private int layout(ArrayList list, int x, int height, Insets insets) { for (Component component : list) { - Dimension size = component.getPreferredSize(); - int y = 0; - if (myAlignment == -1) { - size.height = height; - } - else if (myAlignment != SwingConstants.TOP) { - y = height - size.height; - if (myAlignment == SwingConstants.CENTER) { - y /= 2; + if (component.isVisible()) { + Dimension size = component.getPreferredSize(); + int y = 0; + if (myAlignment == -1) { + size.height = height; } + else if (myAlignment != SwingConstants.TOP) { + y = height - size.height; + if (myAlignment == SwingConstants.CENTER) { + y /= 2; + } + } + component.setBounds(x + insets.left, y + insets.top, size.width, size.height); + x += size.width + myGap; } - component.setBounds(x + insets.left, y + insets.top, size.width, size.height); - x += size.width + myGap; } return x; } @@ -188,7 +226,9 @@ public final class HorizontalLayout implements LayoutManager { private Dimension getPreferredSize(ArrayList list) { Dimension result = null; for (Component component : list) { - result = join(result, myGap, component.getPreferredSize()); + if (component.isVisible()) { + result = join(result, myGap, component.getPreferredSize()); + } } return result; } diff --git a/platform/platform-api/src/com/intellij/ui/components/panels/VerticalLayout.java b/platform/platform-api/src/com/intellij/ui/components/panels/VerticalLayout.java new file mode 100644 index 000000000000..7b9fdd0242ba --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/panels/VerticalLayout.java @@ -0,0 +1,256 @@ +/* + * Copyright 2000-2014 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.ui.components.panels; + +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager2; +import java.util.ArrayList; + +/** + * This class is intended to lay out added components vertically. + * It allows to add them into the TOP, CENTER, or BOTTOM group, which are aligned separately. + * Every group can contain any amount of components. The specified gap is added between components, + * and the double gap is added between groups of components. + *

NB!: this class must be modified together with the HorizontalLayout class accordingly

+ * + * @author Sergey.Malenkov + * @see HorizontalLayout + */ +public final class VerticalLayout implements LayoutManager2 { + public static final String TOP = "TOP"; + public static final String BOTTOM = "BOTTOM"; + public static final String CENTER = "CENTER"; + + private final ArrayList myTop = new ArrayList(); + private final ArrayList myBottom = new ArrayList(); + private final ArrayList myCenter = new ArrayList(); + private final int myAlignment; + private final int myGap; + + /** + * Creates a layout with the specified gap. + * All components will have preferred widths, + * but their widths will be set according to the container. + * + * @param gap vertical gap between components + */ + public VerticalLayout(int gap) { + myGap = gap; + myAlignment = -1; + } + + /** + * Creates a layout with the specified gap and vertical alignment. + * All components will have preferred sizes. + * + * @param gap vertical gap between components + * @param alignment horizontal alignment for components + * + * @see SwingConstants#LEFT + * @see SwingConstants#RIGHT + * @see SwingConstants#CENTER + */ + public VerticalLayout(int gap, int alignment) { + myGap = gap; + switch (alignment) { + case SwingConstants.LEFT: + case SwingConstants.RIGHT: + case SwingConstants.CENTER: + myAlignment = alignment; + break; + default: + throw new IllegalArgumentException("unsupported alignment: " + alignment); + } + } + + @Override + public void addLayoutComponent(Component component, Object constraints) { + if ((constraints == null) || (constraints instanceof String)) { + addLayoutComponent((String)constraints, component); + } + else { + throw new IllegalArgumentException("unsupported constraints: " + constraints); + } + } + + @Override + public Dimension maximumLayoutSize(Container target) { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Override + public float getLayoutAlignmentX(Container target) { + return .5f; + } + + @Override + public float getLayoutAlignmentY(Container target) { + return .5f; + } + + @Override + public void invalidateLayout(Container target) { + } + + @Override + public void addLayoutComponent(String name, Component component) { + synchronized (component.getTreeLock()) { + if (name == null || CENTER.equalsIgnoreCase(name)) { + myCenter.add(component); + } + else if (TOP.equalsIgnoreCase(name)) { + myTop.add(component); + } + else if (BOTTOM.equalsIgnoreCase(name)) { + myBottom.add(component); + } + else { + throw new IllegalArgumentException("unsupported name: " + name); + } + } + } + + @Override + public void removeLayoutComponent(Component component) { + myTop.remove(component); + myBottom.remove(component); + myCenter.remove(component); + } + + @Override + public Dimension preferredLayoutSize(Container container) { + return getPreferredSize(container, true); + } + + @Override + public Dimension minimumLayoutSize(Container container) { + return getPreferredSize(container, false); + } + + @Override + public void layoutContainer(Container container) { + synchronized (container.getTreeLock()) { + Dimension top = getPreferredSize(myTop); + Dimension bottom = getPreferredSize(myBottom); + Dimension center = getPreferredSize(myCenter); + + Insets insets = container.getInsets(); + int width = container.getWidth() - insets.left - insets.right; + int height = container.getHeight() - insets.top - insets.bottom; + + int topY = 0; + if (top != null) { + topY = myGap + layout(myTop, 0, width, insets); + } + int bottomY = height; + if (bottom != null) { + bottomY -= bottom.height; + } + if (bottomY < topY) { + bottomY = topY; + } + if (center != null) { + int centerY = (height - center.height) / 2; + if (centerY > topY) { + int centerBottomY = centerY + center.height + myGap + myGap; + if (centerBottomY > bottomY) { + centerY = bottomY - center.height - myGap - myGap; + } + } + if (centerY < topY) { + centerY = topY; + } + centerY = myGap + layout(myCenter, centerY, width, insets); + if (bottomY < centerY) { + bottomY = centerY; + } + } + if (bottom != null) { + layout(myBottom, bottomY, width, insets); + } + } + } + + private int layout(ArrayList list, int y, int width, Insets insets) { + for (Component component : list) { + if (component.isVisible()) { + Dimension size = component.getPreferredSize(); + int x = 0; + if (myAlignment == -1) { + size.width = width; + } + else if (myAlignment != SwingConstants.LEFT) { + x = width - size.width; + if (myAlignment == SwingConstants.CENTER) { + x /= 2; + } + } + component.setBounds(x + insets.left, y + insets.top, size.width, size.height); + y += size.height + myGap; + } + } + return y; + } + + private static Dimension join(Dimension result, int gap, Dimension size) { + if (size == null) { + return result; + } + if (result == null) { + return new Dimension(size); + } + result.height += gap + size.height; + if (result.width < size.width) { + result.width = size.width; + } + return result; + } + + private Dimension getPreferredSize(ArrayList list) { + Dimension result = null; + for (Component component : list) { + if (component.isVisible()) { + result = join(result, myGap, component.getPreferredSize()); + } + } + return result; + } + + private Dimension getPreferredSize(Container container, boolean aligned) { + synchronized (container.getTreeLock()) { + Dimension top = getPreferredSize(myTop); + Dimension bottom = getPreferredSize(myBottom); + Dimension center = getPreferredSize(myCenter); + Dimension result = join(join(join(null, myGap + myGap, top), myGap + myGap, center), myGap + myGap, bottom); + if (result == null) { + result = new Dimension(); + } + else if (aligned) { + int topHeight = top == null ? 0 : top.height; + int bottomHeight = bottom == null ? 0 : bottom.height; + result.width += Math.abs(topHeight - bottomHeight); + } + Insets insets = container.getInsets(); + result.width += insets.left + insets.right; + result.height += insets.top + insets.bottom; + return result; + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java index 7991c3af0104..299d44f6c0bd 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java +++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java @@ -20,7 +20,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; @@ -34,7 +33,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.impl.SystemDock; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; -import com.intellij.util.ArrayUtil; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; @@ -46,17 +45,19 @@ import java.util.*; /** * @author yole */ -public abstract class RecentProjectsManagerBase implements ProjectManagerListener, PersistentStateComponent { - public static RecentProjectsManagerBase getInstance() { - return ServiceManager.getService(RecentProjectsManagerBase.class); +public abstract class RecentProjectsManagerBase extends RecentProjectsManager implements ProjectManagerListener, PersistentStateComponent { + public static RecentProjectsManagerBase getInstanceEx() { + return (RecentProjectsManagerBase)RecentProjectsManager.getInstance(); } public static class State { - public List recentPaths = ContainerUtil.newArrayList(); - public List openPaths = ContainerUtil.newArrayList(); + public List recentPaths = new SmartList(); + public List openPaths = new SmartList(); public Map names = ContainerUtil.newLinkedHashMap(); public String lastPath; + public String lastProjectLocation; + void validateRecentProjects() { //noinspection StatementWithEmptyBody while (recentPaths.remove(null)) ; @@ -70,11 +71,6 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene recentPaths.remove(index); } } - - void removePath(String path) { - recentPaths.remove(path); - names.remove(path); - } } private final Object myStateLock = new Object(); @@ -96,52 +92,69 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene @Override public void loadState(final State state) { - synchronized (myStateLock) { - myState = state; - if (myState.lastPath != null && !new File(myState.lastPath).exists()) { - myState.lastPath = null; - } - if (myState.lastPath != null) { - File lastFile = new File(myState.lastPath); - if (lastFile.isDirectory() && !new File(lastFile, Project.DIRECTORY_STORE_FOLDER).exists()) { - myState.lastPath = null; - } + if (state.lastPath != null && !new File(state.lastPath).exists()) { + state.lastPath = null; + } + if (state.lastPath != null) { + File lastFile = new File(state.lastPath); + if (lastFile.isDirectory() && !new File(lastFile, Project.DIRECTORY_STORE_FOLDER).exists()) { + state.lastPath = null; } } + myState = state; } - public void removePath(final String path) { - if (path == null) return; + @Override + public void removePath(@Nullable String path) { + if (path == null) { + return; + } + synchronized (myStateLock) { if (SystemInfo.isFileSystemCaseSensitive) { - myState.removePath(path); + myState.recentPaths.remove(path); + myState.names.remove(path); } else { - for (String p : ArrayUtil.toStringArray(myState.recentPaths)) { - if (path.equalsIgnoreCase(p)) { - myState.removePath(path); + for (Iterator iterator = myState.recentPaths.iterator(); iterator.hasNext(); ) { + if (path.equalsIgnoreCase(iterator.next())) { + iterator.remove(); + myState.names.remove(path); } } } } } - public String getLastProjectPath() { - synchronized (myStateLock) { - return myState.lastPath; - } + /** + * @return a path pointing to a directory where the last project was created or null if not available + */ + @Override + @Nullable + public String getLastProjectCreationLocation() { + return myState.lastProjectLocation; } + @Override + public void setLastProjectCreationLocation(@Nullable String lastProjectLocation) { + myState.lastProjectLocation = StringUtil.nullize(lastProjectLocation, true); + } + + @Override + public String getLastProjectPath() { + return myState.lastPath; + } + + @Override public void updateLastProjectPath() { final Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); synchronized (myStateLock) { + myState.openPaths.clear(); if (openProjects.length == 0) { myState.lastPath = null; - myState.openPaths = Collections.emptyList(); } else { myState.lastPath = getProjectPath(openProjects[openProjects.length - 1]); - myState.openPaths = ContainerUtil.newArrayList(); for (Project openProject : openProjects) { String path = getProjectPath(openProject); if (path != null) { @@ -169,9 +182,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene return duplicates; } - /** - * @param addClearListItem whether the "Clear List" action should be added to the end of the list. - */ + @Override public AnAction[] getRecentProjectsActions(boolean addClearListItem) { final Set paths; synchronized (myStateLock) { @@ -187,7 +198,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene paths.remove(null); paths.removeAll(openedPaths); - List actions = new ArrayList(); + List actions = new SmartList(); Set duplicates = getDuplicateProjectNames(openedPaths, paths); for (final String path : paths) { String projectName = getProjectName(path); @@ -295,6 +306,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene return result; } + @Override public void clearNameCache() { myNameCache.clear(); } diff --git a/platform/platform-impl/src/com/intellij/ide/ReopenProjectAction.java b/platform/platform-impl/src/com/intellij/ide/ReopenProjectAction.java index 7a0146807d45..2ece095ce65a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ReopenProjectAction.java +++ b/platform/platform-impl/src/com/intellij/ide/ReopenProjectAction.java @@ -18,7 +18,6 @@ package com.intellij.ide; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; @@ -46,6 +45,7 @@ public class ReopenProjectAction extends AnAction implements DumbAware { } + @Override public void actionPerformed(AnActionEvent e) { final int modifiers = e.getModifiers(); final boolean forceOpenInNewFrame = (modifiers & InputEvent.CTRL_MASK) != 0 || (modifiers & InputEvent.SHIFT_MASK) != 0; @@ -54,11 +54,11 @@ public class ReopenProjectAction extends AnAction implements DumbAware { if (Messages.showDialog(project, "The path " + FileUtil.toSystemDependentName(myProjectPath) + " does not exist.\n" + "If it is on a removable or network drive, please make sure that the drive is connected.", "Reopen Project", new String[]{"OK", "&Remove From List"}, 0, Messages.getErrorIcon()) == 1) { - RecentProjectsManagerBase.getInstance().removePath(myProjectPath); + RecentProjectsManager.getInstance().removePath(myProjectPath); } return; } - RecentProjectsManagerBase.getInstance().doOpenProject(myProjectPath, project, forceOpenInNewFrame); + RecentProjectsManagerBase.getInstanceEx().doOpenProject(myProjectPath, project, forceOpenInNewFrame); } public String getProjectPath() { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CloseProjectAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CloseProjectAction.java index 01015897fd39..00f62e8f9640 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/CloseProjectAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/CloseProjectAction.java @@ -15,12 +15,11 @@ */ package com.intellij.ide.actions; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.DumbAware; @@ -29,15 +28,17 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; import com.intellij.projectImport.ProjectAttachProcessor; public class CloseProjectAction extends AnAction implements DumbAware { + @Override public void actionPerformed(AnActionEvent e) { Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); assert project != null; ProjectUtil.closeAndDispose(project); - RecentProjectsManagerBase.getInstance().updateLastProjectPath(); + RecentProjectsManager.getInstance().updateLastProjectPath(); WelcomeFrame.showIfNoProjectOpened(); } + @Override public void update(AnActionEvent event){ Presentation presentation = event.getPresentation(); Project project = event.getData(CommonDataKeys.PROJECT); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RecentProjectsGroup.java b/platform/platform-impl/src/com/intellij/ide/actions/RecentProjectsGroup.java index 0a2ac7fe1c52..cdeea26c8356 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RecentProjectsGroup.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RecentProjectsGroup.java @@ -15,7 +15,7 @@ */ package com.intellij.ide.actions; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.AnAction; @@ -32,13 +32,15 @@ public class RecentProjectsGroup extends ActionGroup implements DumbAware { presentation.setText(ActionsBundle.message(SystemInfo.isMac ? "group.reopen.mac.text": "group.reopen.win.text")); } + @Override @NotNull public AnAction[] getChildren(@Nullable AnActionEvent e) { - return RecentProjectsManagerBase.getInstance().getRecentProjectsActions(true); + return RecentProjectsManager.getInstance().getRecentProjectsActions(true); } + @Override public void update(AnActionEvent event) { Presentation presentation = event.getPresentation(); - presentation.setEnabled(RecentProjectsManagerBase.getInstance().getRecentProjectsActions(true).length > 0); + presentation.setEnabled(RecentProjectsManager.getInstance().getRecentProjectsActions(true).length > 0); } } diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index 492a2c513477..7e96ba6ec706 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -18,6 +18,7 @@ package com.intellij.ide.impl; import com.intellij.CommonBundle; import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; @@ -75,7 +76,7 @@ public class ProjectUtil { LOG.info(e); return; } - GeneralSettings.getInstance().setLastProjectCreationLocation(path.replace(File.separatorChar, '/')); + RecentProjectsManager.getInstance().setLastProjectCreationLocation(path.replace(File.separatorChar, '/')); } /** @@ -275,7 +276,7 @@ public class ProjectUtil { } public static String getBaseDir() { - final String lastProjectLocation = GeneralSettings.getInstance().getLastProjectCreationLocation(); + final String lastProjectLocation = RecentProjectsManager.getInstance().getLastProjectCreationLocation(); if (lastProjectLocation != null) { return lastProjectLocation.replace('/', File.separatorChar); } diff --git a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java index 64b7dfa9c93d..b4128553a480 100644 --- a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -110,9 +110,10 @@ public class StartupManagerImpl extends StartupManagerEx { public void runStartupActivities() { ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override @SuppressWarnings("SynchronizeOnThis") public void run() { - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Running Startup Activities"); try { runActivities(myPreStartupActivities); @@ -141,6 +142,7 @@ public class StartupManagerImpl extends StartupManagerEx { public void runPostStartupActivitiesFromExtensions() { for (final StartupActivity extension : Extensions.getExtensions(StartupActivity.POST_STARTUP_ACTIVITY)) { final Runnable runnable = new Runnable() { + @Override public void run() { if (!myProject.isDisposed()) { extension.runActivity(myProject); @@ -173,6 +175,7 @@ public class StartupManagerImpl extends StartupManagerEx { runActivities(myDumbAwarePostStartupActivities); DumbService.getInstance(myProject).runWhenSmart(new Runnable() { + @Override public void run() { //noinspection SynchronizeOnThis synchronized (StartupManagerImpl.this) { @@ -199,6 +202,7 @@ public class StartupManagerImpl extends StartupManagerEx { public void scheduleInitialVfsRefresh() { UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override public void run() { if (myProject.isDisposed()) return; @@ -318,6 +322,7 @@ public class StartupManagerImpl extends StartupManagerEx { final Runnable runnable; if (DumbService.isDumbAware(action)) { runnable = new DumbAwareRunnable() { + @Override public void run() { action.run(); } @@ -325,6 +330,7 @@ public class StartupManagerImpl extends StartupManagerEx { } else { runnable = new Runnable() { + @Override public void run() { action.run(); } @@ -335,6 +341,7 @@ public class StartupManagerImpl extends StartupManagerEx { // in tests which simulate project opening, post-startup activities could have been run already. // Then we should act as if the project was initialized UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override public void run() { if (!myProject.isDisposed()) { runnable.run(); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index cf87cd8c24d6..7194dbddaecb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -502,7 +502,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App myIsFiringLoadingEvent = false; } - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Loading application components"); try { store.load(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index b7e2ccb011ad..aca587e966cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -184,7 +184,7 @@ public class ServiceManagerImpl implements BaseComponent { @Override public Object compute() { // prevent storages from flushing and blocking FS - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Creating component '" + myDescriptor.getImplementation()+"'"); try { synchronized (MyComponentAdapter.this) { Object instance = myInitializedComponentInstance; diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/Banner.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/Banner.java index e40730582b89..465f16ddd42a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/Banner.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/Banner.java @@ -21,10 +21,9 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.JBColor; import com.intellij.ui.RelativeFont; import com.intellij.ui.components.labels.SwingActionLink; +import com.intellij.ui.components.panels.HorizontalLayout; import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import java.awt.BorderLayout; @@ -39,7 +38,7 @@ final class Banner extends JPanel { Banner(Action action) { super(new BorderLayout(10, 0)); - myLeftPanel.setLayout(new BoxLayout(myLeftPanel, BoxLayout.X_AXIS)); + myLeftPanel.setLayout(new HorizontalLayout(5)); myProjectIcon.setIcon(AllIcons.General.ProjectConfigurableBanner); myProjectIcon.setForeground(JBColor.GRAY); myProjectIcon.setVisible(false); @@ -48,27 +47,31 @@ final class Banner extends JPanel { add(BorderLayout.EAST, RelativeFont.BOLD.install(new SwingActionLink(action))); } - void setText(String... text) { + void setText(String... names) { Component[] components = myLeftPanel.getComponents(); - int length = text == null ? 0 : text.length; - for (int i = 0; i < length; i++) { - if (i < components.length) { - components[i].setVisible(true); - if (components[i] instanceof JLabel) { - ((JLabel)components[i]).setText(text[i]); - } - } - else { - JLabel label = new JLabel(text[i]); - label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); - if (i > 0) { - label.setIcon(AllIcons.General.Divider); - } - myLeftPanel.add(RelativeFont.BOLD.install(label)); - } + for (Component component : components) { + component.setVisible(false); } - while (length < components.length) { - components[length++].setVisible(false); + if (names != null) { + int i = 0; + for (String name : names) { + if (i < components.length) { + if (i > 0) { + components[i - 1].setVisible(true); + } + components[i].setVisible(true); + if (components[i] instanceof JLabel) { + ((JLabel)components[i]).setText(name); + } + } + else { + if (i > 0) { + myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.HUGE.install(new JLabel("\u203A"))); + } + myLeftPanel.add(HorizontalLayout.LEFT, RelativeFont.BOLD.install(new JLabel(name))); + } + i += 2; + } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 137216540874..7860d4364f9d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -153,7 +153,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { indicator.pushState(); } try { - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Performing indexing task"); task.performInDumbMode(indicator != null ? indicator : new EmptyProgressIndicator()); } finally { @@ -309,6 +309,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { return wrapper; } + @Override public void smartInvokeLater(@NotNull final Runnable runnable) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override @@ -318,6 +319,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { }, myProject.getDisposed()); } + @Override public void smartInvokeLater(@NotNull final Runnable runnable, @NotNull ModalityState modalityState) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override @@ -335,7 +337,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { final ShutDownTracker shutdownTracker = ShutDownTracker.getInstance(); final Thread self = Thread.currentThread(); try { - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Performing indexing tasks"); shutdownTracker.registerStopperThread(self); if (visibleIndicator instanceof ProgressIndicatorEx) { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 6cf160349afd..6bbc24c93d32 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -16,7 +16,7 @@ package com.intellij.openapi.project.impl; import com.intellij.diagnostic.PluginException; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.startup.StartupManagerEx; @@ -349,7 +349,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project catch (IOException e) { LOG.info("Unable to store project name to: " + nameFile.getPath()); } - RecentProjectsManagerBase.getInstance().clearNameCache(); + RecentProjectsManager.getInstance().clearNameCache(); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 0cb3872aa745..ef58d0f4f445 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -19,7 +19,7 @@ import com.intellij.CommonBundle; import com.intellij.conversion.ConversionResult; import com.intellij.conversion.ConversionService; import com.intellij.ide.AppLifecycleListener; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.impl.ProjectUtil; import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.startup.impl.StartupManagerImpl; @@ -29,8 +29,11 @@ import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.components.*; -import com.intellij.openapi.components.impl.stores.*; +import com.intellij.openapi.components.impl.stores.ComponentStoreImpl; import com.intellij.openapi.components.impl.stores.ComponentStoreImpl.ReloadComponentStoreStatus; +import com.intellij.openapi.components.impl.stores.FileBasedStorage; +import com.intellij.openapi.components.impl.stores.StateStorageManager; +import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -124,7 +127,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt /** @noinspection UnusedParameters*/ public ProjectManagerImpl(@NotNull VirtualFileManager virtualFileManager, - RecentProjectsManagerBase recentProjectsManager, + RecentProjectsManager recentProjectsManager, ProgressManager progressManager) { myProgressManager = progressManager; Application app = ApplicationManager.getApplication(); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/ProjectPlaybackCall.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/ProjectPlaybackCall.java index 7257cfc35825..c7fe9d23fefa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/ProjectPlaybackCall.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/util/ProjectPlaybackCall.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.ui.playback.util; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.openapi.project.*; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.playback.PlaybackContext; @@ -44,7 +44,7 @@ public class ProjectPlaybackCall { } public static AsyncResult openLastProject(final PlaybackContext context) { - return openProject(context, RecentProjectsManagerBase.getInstance().getLastProjectPath()); + return openProject(context, RecentProjectsManager.getInstance().getLastProjectPath()); } public static AsyncResult openProject(final PlaybackContext context, final String path) { 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 9852485f1b8f..4329da96fa90 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 @@ -105,7 +105,7 @@ public class JarFileSystemImpl extends JarFileSystem { @NotNull @Override - protected String convertLocalPathToRootPath(@NotNull String localPath) { + protected String convertLocalToRootPath(@NotNull String localPath) { return localPath + JAR_SEPARATOR; } @@ -123,7 +123,7 @@ public class JarFileSystemImpl extends JarFileSystem { @Nullable @Override public VirtualFile getRootByLocal(@NotNull VirtualFile file) { - return findFileByPath(convertLocalPathToRootPath(file.getPath())); + return findFileByPath(convertLocalToRootPath(file.getPath())); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java index f2c9bf472a6b..8c777e75d21e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java @@ -74,7 +74,7 @@ public class RefreshQueueImpl extends RefreshQueue { public void run() { try { myRefreshIndicator.start(); - HeavyProcessLatch.INSTANCE.processStarted(); + HeavyProcessLatch.INSTANCE.processStarted("Doing file refresh. "+session.toString()); try { doScan(session); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java index f7ad09abf223..220d86b09162 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshSessionImpl.java @@ -31,10 +31,7 @@ import com.intellij.util.concurrency.Semaphore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.*; import java.util.concurrent.atomic.AtomicLong; /** @@ -207,7 +204,7 @@ public class RefreshSessionImpl extends RefreshSession { } private List mergeEventsAndReset() { - LinkedHashSet mergedEvents = new LinkedHashSet(myEvents); + Set mergedEvents = new LinkedHashSet(myEvents); List events = new ArrayList(mergedEvents); myEvents = new ArrayList(); return events; @@ -217,4 +214,9 @@ public class RefreshSessionImpl extends RefreshSession { public ModalityState getModalityState() { return myModalityState; } + + @Override + public String toString() { + return myWorkQueue.size() <= 1 ? "" : myWorkQueue.size() + " roots in queue."; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java index 60f5c1a9d68e..97d3f92bf25c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/VfsImplUtil.java @@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.impl.ArchiveHandler; import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.openapi.vfs.newvfs.events.VFileMoveEvent; import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; import com.intellij.util.Function; import com.intellij.util.Processor; @@ -243,7 +244,7 @@ public class VfsImplUtil { bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { @Override public void after(@NotNull List events) { - Map rootsToRefresh = null; + InvalidationState state = null; synchronized (ourLock) { for (VFileEvent event : events) { @@ -252,56 +253,75 @@ public class VfsImplUtil { if (event instanceof VFileCreateEvent) continue; // created file should not invalidate + getFile is costly if (event instanceof VFilePropertyChangeEvent && - VirtualFile.PROP_HIDDEN.equals(((VFilePropertyChangeEvent)event).getPropertyName())) { + !VirtualFile.PROP_NAME.equals(((VFilePropertyChangeEvent)event).getPropertyName())) { continue; } VirtualFile file = event.getFile(); - String path = event.getPath(); // todo: this path is new file path for moved / renamed file and invalidation doesn't take place + String path = event.getPath(); + if (event instanceof VFilePropertyChangeEvent) { + path = ((VFilePropertyChangeEvent)event).getOldPath(); + } else if (event instanceof VFileMoveEvent) { + path = ((VFileMoveEvent)event).getOldPath(); + } if (file == null || !file.isDirectory()) { - rootsToRefresh = invalidateHandlerForPath(path, rootsToRefresh); + if (state == null) state = new InvalidationState(); + state.invalidateHandlerForPath(path); } else { Collection affectedPaths = ourDominatorsMap.get(path); if (affectedPaths != null) { affectedPaths = new ArrayList(affectedPaths); // defensive copying, we will modify original during invalidate - for (String affectedPath : affectedPaths) rootsToRefresh = invalidateHandlerForPath(affectedPath, rootsToRefresh); + if (state == null) state = new InvalidationState(); + for (String affectedPath : affectedPaths) state.invalidateHandlerForPath(affectedPath); } } } } - if (rootsToRefresh != null) { - ZipFileCache.reset(rootsToRefresh.keySet()); - boolean async = !ApplicationManager.getApplication().isUnitTestMode(); - RefreshQueue.getInstance().refresh(async, true, null, rootsToRefresh.values()); - } + if (state != null) state.scheduleRefresh(); } }); } - private static Map invalidateHandlerForPath(final String path, Map rootsToRefresh) { - Pair handlerPair = ourHandlers.remove(path); - if (handlerPair != null) { - String rootPath = handlerPair.first.convertLocalPathToRootPath(path); + private static class InvalidationState { + private Map rootsToRefresh; + + boolean invalidateHandlerForPath(final String path) { + Pair handlerPair = ourHandlers.remove(path); + if (handlerPair != null) { + forEachDirectoryComponent(path, new Processor() { + @Override + public boolean process(String containingDirectoryPath) { + Set handlers = ourDominatorsMap.get(containingDirectoryPath); + if (handlers != null) { + if(handlers.remove(path) && handlers.size() == 0) { + ourDominatorsMap.remove(containingDirectoryPath); + } + } + return true; + } + }); + registerPathToRefresh(handlerPair, path); + } + return handlerPair != null; + } + + private void registerPathToRefresh(Pair handlerPair, String path) { + String rootPath = handlerPair.first.convertLocalToRootPath(path); NewVirtualFile root = ManagingFS.getInstance().findRoot(rootPath, handlerPair.first); if (root != null) { root.markDirtyRecursively(); if (rootsToRefresh == null) rootsToRefresh = ContainerUtil.newHashMap(); rootsToRefresh.put(rootPath, root); } - forEachDirectoryComponent(path, new Processor() { - @Override - public boolean process(String containingDirectoryPath) { - Set handlers = ourDominatorsMap.get(containingDirectoryPath); - if (handlers != null) { - if(handlers.remove(path) && handlers.size() == 0) { - ourDominatorsMap.remove(containingDirectoryPath); - } - } - return true; - } - }); } - return rootsToRefresh; + + void scheduleRefresh() { + if (rootsToRefresh != null) { + ZipFileCache.reset(rootsToRefresh.keySet()); + boolean async = !ApplicationManager.getApplication().isUnitTestMode(); + RefreshQueue.getInstance().refresh(async, true, null, rootsToRefresh.values()); + } + } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java new file mode 100644 index 000000000000..aabe7e640a7f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/FlatWelcomeFrame.java @@ -0,0 +1,357 @@ +/* + * Copyright 2000-2014 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.wm.impl.welcomeScreen; + +import com.intellij.ide.DataManager; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.MnemonicHelper; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.ex.ApplicationInfoEx; +import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbAwareRunnable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ProjectManagerAdapter; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.wm.*; +import com.intellij.openapi.wm.impl.IdeGlassPaneImpl; +import com.intellij.ui.*; +import com.intellij.ui.components.labels.ActionLink; +import com.intellij.ui.components.panels.NonOpaquePanel; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.InputStream; +import java.net.URL; + +/** + * @author Konstantin Bulenkov + */ +public class FlatWelcomeFrame extends JFrame implements WelcomeFrameProvider, IdeFrame { + private final BalloonLayout myBalloonLayout; + private final FlatWelcomeScreen myScreen; + + public FlatWelcomeFrame() { + JRootPane rootPane = getRootPane(); + myScreen = new FlatWelcomeScreen(); + + final IdeGlassPaneImpl glassPane = new IdeGlassPaneImpl(rootPane); + setGlassPane(glassPane); + glassPane.setVisible(false); + setUndecorated(true); + setContentPane(myScreen.getWelcomePanel()); + setTitle(ApplicationNamesInfo.getInstance().getFullProductName()); + AppUIUtil.updateWindowIcon(this); + Rectangle bounds = ScreenUtil.getMainScreenBounds(); + setSize(666, 450); + int x = bounds.x + (bounds.width - getWidth()) / 2; + int y = bounds.y + (bounds.height - getHeight()) / 2; + setLocation(x, y); + ProjectManager.getInstance().addProjectManagerListener(new ProjectManagerAdapter() { + @Override + public void projectOpened(Project project) { + dispose(); + } + }); + + myBalloonLayout = new BalloonLayoutImpl(rootPane, new Insets(8, 8, 8, 8)); + + setupCloseAction(); + new MnemonicHelper().register(this); + Disposer.register(ApplicationManager.getApplication(), new Disposable() { + @Override + public void dispose() { + FlatWelcomeFrame.this.dispose(); + } + }); + } + + @Override + public void dispose() { + Disposer.dispose(myScreen); + super.dispose(); + WelcomeFrame.resetInstance(); + } + + private static void saveLocation(Rectangle location) { + Point middle = new Point(location.x + location.width / 2, location.y = location.height / 2); + //DimensionService.getInstance().setLocation(DIMENSION_KEY, middle, null); + } + + private void setupCloseAction() { + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + addWindowListener( + new WindowAdapter() { + public void windowClosing(final WindowEvent e) { + dispose(); + + final Application app = ApplicationManager.getApplication(); + app.invokeLater(new DumbAwareRunnable() { + public void run() { + if (app.isDisposed()) { + ApplicationManagerEx.getApplicationEx().exit(); + return; + } + + final Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + if (openProjects.length == 0) { + ApplicationManagerEx.getApplicationEx().exit(); + } + } + }, ModalityState.NON_MODAL); + } + } + ); + } + + @Override + public StatusBar getStatusBar() { + return null; + } + + public static Color getMainBackground() { + return Color.WHITE; + } + + public static Color getProjectsBackGround() { + return Gray._245; + } + + @Override + public IdeFrame createFrame() { + return Registry.is("ide.new.welcome.screen") ? this : null; + } + + private static class FlatWelcomeScreen extends JPanel implements WelcomeScreen { + public FlatWelcomeScreen() { + super(new BorderLayout()); + setBackground(getMainBackground()); + add(createRecentProjects(), BorderLayout.WEST); + add(createBody(), BorderLayout.CENTER); + } + + @Override + public JComponent getWelcomePanel() { + return this; + } + + private JComponent createBody() { + NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout()); + panel.add(createLogo(), BorderLayout.NORTH); + panel.add(createActionPanel(), BorderLayout.CENTER); + //panel.add(createSettingsAndDocs(), BorderLayout.SOUTH); + return panel; + } + + private JComponent createSettingsAndDocs() { + return null; + } + + private JComponent createActionPanel() { + JPanel actions = new JPanel(); + actions.setOpaque(false); + actions.setLayout(new BoxLayout(actions, BoxLayout.Y_AXIS)); + ActionManager actionManager = ActionManager.getInstance(); + ActionGroup quickStart = (ActionGroup)actionManager.getAction(IdeActions.GROUP_WELCOME_SCREEN_QUICKSTART); + DefaultActionGroup group = new DefaultActionGroup(); + for (AnAction action : quickStart.getChildren(null)) { + if (action instanceof ActionGroup) { + group.addAll((ActionGroup)action); + } else { + group.add(action); + } + } + + // so, we sure this is the last action + final AnAction register = actionManager.getAction("WelcomeScreen.Register"); + if (register != null) { + group.add(register); + } + + for (AnAction action : group.getChildren(null)) { + JPanel button = new JPanel(new BorderLayout()) { + @Override + public Dimension getPreferredSize() { + return new Dimension(250, super.getPreferredSize().height); + } + }; + button.setOpaque(false); + button.setBorder(new EmptyBorder(4, 30, 0, 30)); + Presentation presentation = action.getTemplatePresentation(); + action.update(new AnActionEvent(null, DataManager.getInstance().getDataContext(this), + ActionPlaces.WELCOME_SCREEN, presentation, ActionManager.getInstance(), 0)); + if (presentation.isVisible()) { + ActionLink link = new ActionLink(presentation.getText(), presentation.getIcon(), action); + link.setBorder(new EmptyBorder(2, 5, 2, 5)); + installFocusable(link, action); + button.add(link); + actions.add(button); + } + + } + + actions.setBorder(new EmptyBorder(0, 0, 0, 0)); + JPanel panel = new NonOpaquePanel(new BorderLayout()); + panel.add(actions, BorderLayout.NORTH); + return panel; + } + + private JComponent createLogo() { + NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout()); + JLabel logo = new JLabel(IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getWelcomeScreenLogoUrl())); + logo.setBorder(new EmptyBorder(20, 0, 0, 30)); + logo.setHorizontalAlignment(SwingConstants.CENTER); + panel.add(logo, BorderLayout.NORTH); + JLabel appName = new JLabel(ApplicationNamesInfo.getInstance().getFullProductName()); + Font font = getProductFont(); + appName.setFont(font.deriveFont(36f).deriveFont(Font.PLAIN)); + appName.setForeground(Gray._0); + appName.setHorizontalAlignment(SwingConstants.CENTER); + JLabel version = new JLabel("Version " + ApplicationInfoEx.getInstanceEx().getFullVersion()); + version.setFont(font.deriveFont(16f).deriveFont(Font.PLAIN)); + version.setHorizontalAlignment(SwingConstants.CENTER); + version.setForeground(Gray._128); + + panel.add(appName); + panel.add(version, BorderLayout.SOUTH); + return panel; + } + + private static Font getProductFont() { + String name = "/fonts/Roboto-Light.ttf"; + URL url = AppUIUtil.class.getResource(name); + if (url == null) { + Logger.getInstance(AppUIUtil.class).warn("Resource missing: " + name); + } else { + + try { + InputStream is = url.openStream(); + try { + return Font.createFont(Font.TRUETYPE_FONT, is); + } + finally { + is.close(); + } + } + catch (Throwable t) { + Logger.getInstance(AppUIUtil.class).warn("Cannot load font: " + url, t); + } + } + return UIUtil.getLabelFont(); + } + + private JComponent createRecentProjects() { + JPanel panel = new JPanel(new BorderLayout()); + panel.add(new NewRecentProjectPanel(this), BorderLayout.NORTH); + panel.setBackground(getProjectsBackGround()); + return panel; + } + + private void installFocusable(final JComponent comp, final AnAction action) { + comp.setBorder(new EmptyBorder(2, 2, 2, 2)); + comp.setFocusable(true); + comp.setFocusTraversalKeysEnabled(true); + comp.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + action.actionPerformed(new AnActionEvent(e, + DataManager.getInstance().getDataContext(), + ActionPlaces.WELCOME_SCREEN, + action.getTemplatePresentation().clone(), + ActionManager.getInstance(), + 0)); + } + } + }); + comp.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + comp.setBorder(new CompoundBorder(new DottedBorder(new Insets(1, 1, 1, 1), Gray._128), new EmptyBorder(1,1,1,1))); + } + + @Override + public void focusLost(FocusEvent e) { + comp.setBorder(new EmptyBorder(2, 2, 2, 2)); + } + }); + + } + + @Override + public void setupFrame(JFrame frame) { + + } + + @Override + public void dispose() { + + } + } + + @Override + public BalloonLayout getBalloonLayout() { + return myBalloonLayout; + } + + @Override + public Rectangle suggestChildFrameBounds() { + return getBounds(); + } + + @Nullable + @Override + public Project getProject() { + return ProjectManager.getInstance().getDefaultProject(); + } + + @Override + public void setFrameTitle(String title) { + setTitle(title); + } + + @Override + public void setFileTitle(String fileTitle, File ioFile) { + setTitle(fileTitle); + } + + @Override + public IdeRootPaneNorthExtension getNorthExtension(String key) { + return null; + } + + @Override + public JComponent getComponent() { + return getRootPane(); + } + + public static void notifyFrameClosed(JFrame frame) { + saveLocation(frame.getBounds()); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java new file mode 100644 index 000000000000..ef48ddf02911 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewRecentProjectPanel.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2014 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.wm.impl.welcomeScreen; + +import com.intellij.ide.ReopenProjectAction; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.util.io.UniqueNameBuilder; +import com.intellij.openapi.wm.WelcomeScreen; +import com.intellij.ui.components.JBList; +import com.intellij.ui.speedSearch.ListWithFilter; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class NewRecentProjectPanel extends RecentProjectPanel { + public NewRecentProjectPanel(WelcomeScreen screen) { + super(screen); + setBorder(null); + setBackground(FlatWelcomeFrame.getProjectsBackGround()); + JScrollPane scrollPane = UIUtil.findComponentOfType(this, JScrollPane.class); + if (scrollPane != null) { + scrollPane.setBackground(FlatWelcomeFrame.getProjectsBackGround()); + } + ListWithFilter panel = UIUtil.findComponentOfType(this, ListWithFilter.class); + if (panel != null) { + panel.setBackground(FlatWelcomeFrame.getProjectsBackGround()); + } + } + + protected Dimension getPreferredScrollableViewportSize() { + return new Dimension(250, 420); + } + + @Override + protected void addMouseMotionListener() { + } + + @Override + protected JBList createList(AnAction[] recentProjectActions, Dimension size) { + JBList list = super.createList(recentProjectActions, size); + list.setBackground(FlatWelcomeFrame.getProjectsBackGround()); + return list; + } + + @Override + protected ListCellRenderer createRenderer(UniqueNameBuilder pathShortener) { + return new RecentProjectItemRenderer(myPathShortener) { + { + setBorder(new EmptyBorder(0, 10, 0, 0)); + } + @Override + protected Color getListBackground(boolean isSelected, boolean hasFocus) { + return isSelected && hasFocus ? new Color(0x2484fd) : FlatWelcomeFrame.getProjectsBackGround(); + } + + @Override + protected Color getListForeground(boolean isSelected, boolean hasFocus) { + return UIUtil.getListForeground(isSelected && hasFocus); + } + }; + } + + + + @Nullable + @Override + protected JPanel createTitle() { + return null; + } + + +} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java index eee05f4522a2..32461f8277be 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java @@ -19,6 +19,7 @@ */ package com.intellij.openapi.wm.impl.welcomeScreen; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.RecentProjectsManagerBase; import com.intellij.ide.ReopenProjectAction; import com.intellij.openapi.actionSystem.ActionPlaces; @@ -40,6 +41,7 @@ import com.intellij.util.Function; import com.intellij.util.SystemProperties; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.LineBorder; @@ -48,13 +50,13 @@ import java.awt.event.*; import java.io.File; public class RecentProjectPanel extends JPanel { - private final JBList myList; - private final UniqueNameBuilder myPathShortener; + protected final JBList myList; + protected final UniqueNameBuilder myPathShortener; public RecentProjectPanel(WelcomeScreen screen) { super(new BorderLayout()); - final AnAction[] recentProjectActions = RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false); + final AnAction[] recentProjectActions = RecentProjectsManager.getInstance().getRecentProjectsActions(false); myPathShortener = new UniqueNameBuilder(SystemProperties.getUserHome(), File.separator, 40); for (AnAction action : recentProjectActions) { @@ -62,8 +64,8 @@ public class RecentProjectPanel extends JPanel { myPathShortener.addPath(item, item.getProjectPath()); } - myList = new MyList(recentProjectActions); - myList.setCellRenderer(new RecentProjectItemRenderer()); + myList = createList(recentProjectActions, getPreferredScrollableViewportSize()); + myList.setCellRenderer(createRenderer(myPathShortener)); new ClickListener(){ @Override @@ -112,7 +114,7 @@ public class RecentProjectPanel extends JPanel { "Remove Recent Project", Messages.getQuestionIcon()); if (rc == Messages.OK) { - final RecentProjectsManagerBase manager = RecentProjectsManagerBase.getInstance(); + RecentProjectsManager manager = RecentProjectsManagerBase.getInstance(); for (Object projectAction : selection) { manager.removePath(((ReopenProjectAction)projectAction).getProjectPath()); } @@ -127,27 +129,7 @@ public class RecentProjectPanel extends JPanel { } }.registerCustomShortcutSet(CustomShortcutSet.fromString("DELETE", "BACK_SPACE"), myList, screen); - myList.addMouseMotionListener(new MouseMotionAdapter() { - boolean myIsEngaged = false; - public void mouseMoved(MouseEvent e) { - if (myIsEngaged && !UIUtil.isSelectionButtonDown(e)) { - Point point = e.getPoint(); - int index = myList.locationToIndex(point); - myList.setSelectedIndex(index); - - final Rectangle bounds = myList.getCellBounds(index, index); - if (bounds != null && bounds.contains(point)) { - myList.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } - else { - myList.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - else { - myIsEngaged = true; - } - } - }); + addMouseMotionListener(); myList.setSelectedIndex(0); @@ -170,6 +152,53 @@ public class RecentProjectPanel extends JPanel { }); add(list, BorderLayout.CENTER); + JPanel title = createTitle(); + + if (title != null) { + add(title, BorderLayout.NORTH); + } + + setBorder(new LineBorder(WelcomeScreenColors.BORDER_COLOR)); + } + + protected Dimension getPreferredScrollableViewportSize() { + return new Dimension(250, 400); + } + + protected void addMouseMotionListener() { + myList.addMouseMotionListener(new MouseMotionAdapter() { + boolean myIsEngaged = false; + public void mouseMoved(MouseEvent e) { + if (myIsEngaged && !UIUtil.isSelectionButtonDown(e)) { + Point point = e.getPoint(); + int index = myList.locationToIndex(point); + myList.setSelectedIndex(index); + + final Rectangle bounds = myList.getCellBounds(index, index); + if (bounds != null && bounds.contains(point)) { + myList.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + else { + myList.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + else { + myIsEngaged = true; + } + } + }); + } + + protected JBList createList(AnAction[] recentProjectActions, Dimension size) { + return new MyList(size, recentProjectActions); + } + + protected ListCellRenderer createRenderer(UniqueNameBuilder pathShortener) { + return new RecentProjectItemRenderer(pathShortener); + } + + @Nullable + protected JPanel createTitle() { JPanel title = new JPanel() { @Override public Dimension getPreferredSize() { @@ -183,57 +212,53 @@ public class RecentProjectPanel extends JPanel { titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setForeground(WelcomeScreenColors.CAPTION_FOREGROUND); title.setBackground(WelcomeScreenColors.CAPTION_BACKGROUND); - - add(title, BorderLayout.NORTH); - - setBorder(new LineBorder(WelcomeScreenColors.BORDER_COLOR)); - } - - private String getTitle2Text(ReopenProjectAction action, JComponent pathLabel) { - String fullText = action.getProjectPath(); - if (fullText == null || fullText.length() == 0) return " "; - - fullText = FileUtil.getLocationRelativeToUserHome(fullText, false); - - int labelWidth = pathLabel.getWidth(); - if (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { - return myPathShortener.getShortPath(action); - } - - return fullText; + return title; } private static class MyList extends JBList { - private MyList(@NotNull Object... listData) { + private final Dimension mySize; + + private MyList(Dimension size, @NotNull Object... listData) { super(listData); + mySize = size; setEmptyText(" No Project Open Yet "); setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); } @Override public Dimension getPreferredScrollableViewportSize() { - return new Dimension(250, 400); + return mySize; } } - private class RecentProjectItemRenderer extends JPanel implements ListCellRenderer { - private final JLabel myName = new JLabel(); - private final JLabel myPath = new JLabel(); + protected static class RecentProjectItemRenderer extends JPanel implements ListCellRenderer { + protected final JLabel myName = new JLabel(); + protected final JLabel myPath = new JLabel(); + private final UniqueNameBuilder myShortener; - private RecentProjectItemRenderer() { + protected RecentProjectItemRenderer(UniqueNameBuilder pathShortener) { super(new VerticalFlowLayout()); + myShortener = pathShortener; setFocusable(true); myPath.setFont(myPath.getFont().deriveFont((float)10)); add(myName); add(myPath); } + + protected Color getListBackground(boolean isSelected, boolean hasFocus) { + return UIUtil.getListBackground(isSelected); + } + + protected Color getListForeground(boolean isSelected, boolean hasFocus) { + return UIUtil.getListForeground(isSelected); + } @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { ReopenProjectAction item = (ReopenProjectAction)value; - Color fore = UIUtil.getListForeground(isSelected); - Color back = UIUtil.getListBackground(isSelected); + Color fore = getListForeground(isSelected, cellHasFocus); + Color back = getListBackground(isSelected, cellHasFocus); myName.setForeground(fore); myPath.setForeground(isSelected ? fore : UIUtil.getInactiveTextColor()); @@ -246,6 +271,19 @@ public class RecentProjectPanel extends JPanel { return this; } + private String getTitle2Text(ReopenProjectAction action, JComponent pathLabel) { + String fullText = action.getProjectPath(); + if (fullText == null || fullText.length() == 0) return " "; + + fullText = FileUtil.getLocationRelativeToUserHome(fullText, false); + + int labelWidth = pathLabel.getWidth(); + if (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) { + return myShortener.getShortPath(action); + } + + return fullText; + } @Override public Dimension getPreferredSize() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectsAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectsAction.java index 614516eda96b..c2d3f8c09cc2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -15,7 +15,7 @@ */ package com.intellij.openapi.wm.impl.welcomeScreen; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; @@ -27,22 +27,22 @@ import javax.swing.*; /** * This action is not visible in the UI but we keep it available to let users invoke it from keyboard. - * - * @author pti - * Date: Mar 2, 2005 */ public class RecentProjectsAction extends WelcomePopupAction { + @Override protected void fillActions(final DefaultActionGroup group) { - final AnAction[] recentProjectActions = RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false); + final AnAction[] recentProjectActions = RecentProjectsManager.getInstance().getRecentProjectsActions(false); for (AnAction action : recentProjectActions) { group.add(action); } } + @Override protected String getTextForEmpty() { return UIBundle.message("welcome.screen.recent.projects.action.no.recent.projects.to.display.action.name"); } + @Override protected String getCaption() { return ""; } @@ -54,7 +54,7 @@ public class RecentProjectsAction extends WelcomePopupAction { @Override public void update(final AnActionEvent e) { - e.getPresentation().setVisible(RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false).length > 0); + e.getPresentation().setVisible(RecentProjectsManager.getInstance().getRecentProjectsActions(false).length > 0); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java index 43fdfa7f9ac1..73bd0010ea36 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeFrame.java @@ -158,11 +158,21 @@ public class WelcomeFrame extends JFrame implements IdeFrame { } return screen; } - + + public static void resetInstance() { + ourInstance = null; + } public static void showNow() { if (ourInstance == null) { - IdeFrame frame = EP.getExtensions().length == 0 ? new WelcomeFrame() : EP.getExtensions()[0].createFrame(); + IdeFrame frame = null; + for (WelcomeFrameProvider provider : EP.getExtensions()) { + frame = provider.createFrame(); + if (frame != null) break; + } + if (frame == null) { + frame = new WelcomeFrame(); + } IdeMenuBar.installAppMenuIfNeeded((JFrame)frame); ((JFrame)frame).setVisible(true); ourInstance = frame; diff --git a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java index ee55679bdea6..541f9a8194be 100644 --- a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java +++ b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java @@ -15,7 +15,7 @@ */ package com.intellij.platform; -import com.intellij.ide.GeneralSettings; +import com.intellij.ide.RecentProjectsManager; import com.intellij.idea.ActionsBundle; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; @@ -96,7 +96,7 @@ public class NewDirectoryProjectAction extends AnAction implements DumbAware { return null; } } - GeneralSettings.getInstance().setLastProjectCreationLocation(location.getParent()); + RecentProjectsManager.getInstance().setLastProjectCreationLocation(location.getParent()); final Object finalSettings = settings; return PlatformProjectOpenProcessor.doOpenProject(baseDir, null, false, -1, new ProjectOpenedCallback() { @Override diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacDockDelegate.java b/platform/platform-impl/src/com/intellij/ui/mac/MacDockDelegate.java index dfd42bb4b604..f3d6ace40c81 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacDockDelegate.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacDockDelegate.java @@ -16,7 +16,7 @@ package com.intellij.ui.mac; import com.intellij.ide.DataManager; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.ReopenProjectAction; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; @@ -35,7 +35,6 @@ import java.lang.reflect.Method; * @author Denis Fokin */ public class MacDockDelegate implements SystemDock.Delegate { - private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.MacDockDelegate"); private static boolean initialized = false; @@ -57,8 +56,9 @@ public class MacDockDelegate implements SystemDock.Delegate { } } + @Override public void updateRecentProjectsMenu () { - final AnAction[] recentProjectActions = RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false); + final AnAction[] recentProjectActions = RecentProjectsManager.getInstance().getRecentProjectsActions(false); recentProjectsMenu.removeAll(); for (final AnAction action : recentProjectActions) { diff --git a/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java b/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java index 999b43e87ece..c9497464dd3e 100644 --- a/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java +++ b/platform/platform-impl/src/com/intellij/ui/win/WinDockDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -15,19 +15,19 @@ */ package com.intellij.ui.win; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.ReopenProjectAction; import com.intellij.idea.StartupUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.wm.impl.SystemDock; + import java.io.File; /** * @author Denis Fokin */ public class WinDockDelegate implements SystemDock.Delegate { - private static final String javaExe = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar + "javaw.exe"; private static final String argsToExecute = " -classpath \"" + PathManager.getJarPathForClass(SocketControlHelper.class) + @@ -40,8 +40,9 @@ public class WinDockDelegate implements SystemDock.Delegate { private WinDockDelegate() {} + @Override public void updateRecentProjectsMenu () { - final AnAction[] recentProjectActions = RecentProjectsManagerBase.getInstance().getRecentProjectsActions(false); + final AnAction[] recentProjectActions = RecentProjectsManager.getInstance().getRecentProjectsActions(false); RecentTasks.clear(); Task[] tasks = new Task[recentProjectActions.length]; for (int i = 0; i < recentProjectActions.length; i ++) { diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 8da8ea937b1a..258527b5a982 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -207,6 +207,8 @@ + + - - events) { - for (VFileEvent event : events) { - //if (event instanceof VFileContentChangeEvent && entry.equals(event.getFile())) { - // updated.set(true); - // break; - //} - } - } + @Override + protected void run() throws Throwable { + PsiTestUtil.addContentRoot(myModule, vFile.getParent()); } - ); + }.execute(); - assertTrue(jar.renameTo(new File(jar.getParentFile(), jar.getName() + ".jar"))); + VirtualFile jarRoot = findByPath(jar.getPath() + JarFileSystem.JAR_SEPARATOR); + final PsiFile file = getPsiManager().findFile(vFile); + final String newName = vFile.getName() + ".jar"; + rename(file, newName); + + assertFalse(jarRoot.isValid()); + + checkMove(jar, vFile, file); } + + private void checkMove(File jar, VirtualFile vFile, final PsiFile file) { + VirtualFile jarRoot; + File libDir = new File(jar.getParent(), "lib"); + assertTrue(libDir.mkdir()); + final VirtualFile vLibDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(libDir); + assertNotNull(vLibDir); + + jarRoot = findByPath(vFile.getPath() + JarFileSystem.JAR_SEPARATOR); + assertTrue(jarRoot.isValid()); + PsiDirectory directory = getPsiManager().findDirectory(vLibDir); + final DataContext + psiDataContext = SimpleDataContext.getSimpleContext(LangDataKeys.TARGET_PSI_ELEMENT.getName(), directory); + new WriteCommandAction.Simple(myProject) { + + @Override + protected void run() throws Throwable { + new MoveHandler().invoke(myProject, new PsiElement[] {file}, psiDataContext); + } + }.execute(); + assertFalse(jarRoot.isValid()); + + jarRoot = findByPath(vFile.getPath() + JarFileSystem.JAR_SEPARATOR); + assertTrue(jarRoot.isValid()); + rename(directory, "lib2"); + assertFalse(jarRoot.isValid()); + } + + private static void rename(final PsiNamedElement file, final String newName) { + final DataContext psiDataContext = SimpleDataContext.getSimpleContext(CommonDataKeys.PSI_ELEMENT.getName(), file); + final RenameHandler renameHandler = + RenameHandlerRegistry.getInstance().getRenameHandler(psiDataContext); + assertNotNull(renameHandler); + + new WriteCommandAction.Simple(file.getProject()) { + @Override + public void run() { + PsiElementRenameHandler.rename(file, file.getProject(), file, null, newName); + } + }.execute(); + } + public void testJarRefresh() throws IOException { File jar = IoTestUtil.createTestJar(); assertTrue(jar.setLastModified(jar.lastModified() - 1000)); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java index 063c7bab7b30..9d2da8b2e002 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SmartList; +import com.intellij.util.containers.StringInterner; import gnu.trove.THashMap; import gnu.trove.TObjectObjectProcedure; import org.jdom.Element; @@ -71,6 +72,7 @@ public class DirectoryStorageData extends StorageDataBase { return; } + StringInterner interner = new StringInterner(); for (VirtualFile file : dir.getChildren()) { if (!isStorageFile(file)) { continue; @@ -94,6 +96,7 @@ public class DirectoryStorageData extends StorageDataBase { } Element state = (Element)elementChildren.get(0).detach(); + JDOMUtil.internElement(state, interner); if (pathMacroSubstitutor != null) { pathMacroSubstitutor.expandPaths(state); pathMacroSubstitutor.addUnknownMacros(name, PathMacrosCollector.getMacroNames(state)); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java index 65a1877fb102..1178d1ea26a9 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/StorageData.java @@ -26,7 +26,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.SmartHashSet; -import com.intellij.util.containers.WeakStringInterner; +import com.intellij.util.containers.StringInterner; import org.jdom.Attribute; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -67,8 +67,7 @@ public class StorageData extends StorageDataBase { pathMacroSubstitutor.expandPaths(rootElement); } - WeakStringInterner interner = intern ? new WeakStringInterner() : null; - + StringInterner interner = intern ? new StringInterner() : null; for (Iterator iterator = rootElement.getChildren(COMPONENT).iterator(); iterator.hasNext(); ) { Element element = iterator.next(); String name = getComponentNameIfValid(element); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 9af4b642ac16..57502412093f 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -456,3 +456,4 @@ editor.disable.rtl.description=Disables RTL support in editor (which is broken n decompiler.use.line.table=false ide.transparency.mode.for.windows=false ide.transparency.mode.for.windows.description=Allow to add transparency to floating windows +ide.new.welcome.screen=false diff --git a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java index e7d6d06b8111..7735054fa3ea 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java @@ -132,7 +132,12 @@ public class JDOMUtil { return i * 31 + s.hashCode(); } + @SuppressWarnings("unused") @NotNull + @Deprecated + /** + * to remove in IDEA 15 + */ public static Object[] getChildNodesWithAttrs(@NotNull Element e) { ArrayList result = new ArrayList(); result.addAll(e.getContent()); diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index d61dc2424be3..74784b2dbd4d 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -1227,6 +1227,14 @@ public class ContainerUtil extends ContainerUtilRt { if (list1.isEmpty() && list2.isEmpty()) { return Collections.emptyList(); } + else if (list1.isEmpty()) { + //noinspection unchecked + return (List)list2; + } + else if (list2.isEmpty()) { + //noinspection unchecked + return (List)list1; + } final int size1 = list1.size(); final int size = size1 + list2.size(); diff --git a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java index 0f14dcb8511b..29e77633c756 100644 --- a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java +++ b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java @@ -24,31 +24,46 @@ import com.intellij.util.EventDispatcher; import org.jetbrains.annotations.NotNull; import java.util.EventListener; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.Stack; public class HeavyProcessLatch { public static final HeavyProcessLatch INSTANCE = new HeavyProcessLatch(); - private final AtomicInteger myHeavyProcessCounter = new AtomicInteger(); + private final Stack myHeavyProcesses = new Stack(); private final EventDispatcher myEventDispatcher = EventDispatcher.create(HeavyProcessListener.class); private HeavyProcessLatch() { } + /** + * @deprecated use {@link #processStarted(java.lang.String)} instead + */ + @Deprecated public void processStarted() { - myHeavyProcessCounter.incrementAndGet(); + processStarted(""); + } + + public void processStarted(@NotNull String operationName) { + myHeavyProcesses.push(operationName); myEventDispatcher.getMulticaster().processStarted(); } public void processFinished() { - myHeavyProcessCounter.decrementAndGet(); + myHeavyProcesses.pop(); myEventDispatcher.getMulticaster().processFinished(); } public boolean isRunning() { - return myHeavyProcessCounter.get() != 0; + return !myHeavyProcesses.isEmpty(); } + public String getRunningOperationName() { + synchronized (myHeavyProcesses) { + return myHeavyProcesses.isEmpty() ? null : myHeavyProcesses.peek(); + } + } + + public interface HeavyProcessListener extends EventListener { public void processStarted(); diff --git a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java index ddd13a968137..e3a0b7a2579b 100644 --- a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -19,12 +19,15 @@ package com.intellij.util.xmlb; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.AbstractCollection; +import gnu.trove.THashMap; import org.jdom.Content; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; abstract class AbstractCollectionBinding implements Binding { private Map myElementBindings; @@ -67,14 +70,11 @@ abstract class AbstractCollectionBinding implements Binding { private synchronized Map getElementBindings() { if (myElementBindings == null) { - myElementBindings = new HashMap(); - + myElementBindings = new THashMap(); myElementBindings.put(myElementType, getBinding(myElementType)); - if (myAnnotation != null) { for (Class aClass : myAnnotation.elementTypes()) { myElementBindings.put(aClass, getBinding(aClass)); - } } } @@ -145,34 +145,41 @@ abstract class AbstractCollectionBinding implements Binding { @Override public Object deserialize(Object o, @NotNull Object... nodes) { Collection result; - if (getTagName(o) != null) { - assert nodes.length == 1; - Element e = (Element)nodes[0]; - result = createCollection(e.getName()); - List content = e.getContent(); - //noinspection ForLoopReplaceableByForEach - for (int i = 0, size = content.size(); i < size; i++) { - Content child = content.get(i); - if (!XmlSerializerImpl.isIgnoredNode(child)) { - //noinspection unchecked - result.add(getElementBinding(child).deserialize(o, child)); - } + if (getTagName(o) == null) { + if (o instanceof Collection) { + result = (Collection)o; + result.clear(); + } + else { + result = new SmartList(); } - } - else { - result = new SmartList(); for (Object node : nodes) { if (!XmlSerializerImpl.isIgnoredNode(node)) { //noinspection unchecked result.add(getElementBinding(node).deserialize(o, node)); } } + + if (result == o) { + return result; + } + } + else { + assert nodes.length == 1; + Element e = (Element)nodes[0]; + result = createCollection(e.getName()); + for (Content child : e.getContent()) { + if (!XmlSerializerImpl.isIgnoredNode(child)) { + //noinspection unchecked + result.add(getElementBinding(child).deserialize(o, child)); + } + } } return processResult(result, o); } - protected Collection createCollection(final String tagName) { - return new ArrayList(); + protected Collection createCollection(@NotNull String tagName) { + return new SmartList(); } @Override diff --git a/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java b/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java index e288fbe43e79..e071b6b915ec 100644 --- a/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java +++ b/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import org.jetbrains.annotations.NotNull; @@ -23,7 +22,7 @@ class AccessorBindingWrapper implements Binding { private final Accessor myAccessor; private final Binding myBinding; - public AccessorBindingWrapper(final Accessor accessor, final Binding binding) { + public AccessorBindingWrapper(@NotNull Accessor accessor, @NotNull Binding binding) { myAccessor = accessor; myBinding = binding; } @@ -41,7 +40,11 @@ class AccessorBindingWrapper implements Binding { @Override @Nullable public Object deserialize(Object context, @NotNull Object... nodes) { - myAccessor.write(context, myBinding.deserialize(myAccessor.read(context), nodes)); + Object currentValue = myAccessor.read(context); + Object deserializedValue = myBinding.deserialize(currentValue, nodes); + if (currentValue != deserializedValue) { + myAccessor.write(context, deserializedValue); + } return context; } diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index 478462769023..8c5bce232288 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import com.intellij.openapi.diagnostic.Logger; @@ -22,12 +21,13 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ConcurrentSoftValueHashMap; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.xmlb.annotations.*; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,23 +36,20 @@ import java.beans.Introspector; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; import java.util.List; +import java.util.Map; +import java.util.Set; class BeanBinding implements Binding { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.xmlb.BeanBinding"); + private static final Logger LOG = Logger.getInstance(BeanBinding.class); private static final Map> ourAccessorCache = new ConcurrentSoftValueHashMap>(); private final String myTagName; - private final Map myPropertyBindings = new HashMap(); - private final List myPropertyBindingsList = new ArrayList(); + private final LinkedHashMap myPropertyBindings = new LinkedHashMap(); private final Class myBeanClass; - @NonNls private static final String CLASS_PROPERTY = "class"; - private final Accessor myAccessor; - public BeanBinding(Class beanClass, @Nullable Accessor accessor) { - myAccessor = accessor; + public BeanBinding(Class beanClass) { assert !beanClass.isArray() : "Bean is an array: " + beanClass; assert !beanClass.isPrimitive() : "Bean is primitive type: " + beanClass; myBeanClass = beanClass; @@ -67,9 +64,7 @@ class BeanBinding implements Binding { private synchronized void initPropertyBindings(Class beanClass) { for (Accessor accessor : getAccessors(beanClass)) { - final Binding binding = createBindingByAccessor(accessor); - myPropertyBindingsList.add(binding); - myPropertyBindings.put(binding, accessor); + myPropertyBindings.put(createBindingByAccessor(accessor), accessor); } } @@ -82,20 +77,21 @@ class BeanBinding implements Binding { } public void serializeInto(@NotNull Object o, @NotNull Element element, @NotNull SerializationFilter filter) { - for (Binding binding : myPropertyBindingsList) { + for (Binding binding : myPropertyBindings.keySet()) { Accessor accessor = myPropertyBindings.get(binding); - if (!filter.accepts(accessor, o)) continue; + if (!filter.accepts(accessor, o)) { + continue; + } //todo: optimize. Cache it. - final Property property = XmlSerializerImpl.findAnnotation(accessor.getAnnotations(), Property.class); - if (property != null) { + Property property = XmlSerializerImpl.findAnnotation(accessor.getAnnotations(), Property.class); + if (property != null && property.filter() != SerializationFilter.class) { try { - if (!property.filter().newInstance().accepts(accessor, o)) continue; + if (!ReflectionUtil.newInstance(property.filter()).accepts(accessor, o)) { + continue; + } } - catch (InstantiationException e) { - throw new XmlSerializationException(e); - } - catch (IllegalAccessException e) { + catch (RuntimeException e) { throw new XmlSerializationException(e); } } @@ -112,39 +108,30 @@ class BeanBinding implements Binding { } } - public void deserializeInto(final Object bean, @NotNull Element element) { - _deserializeInto(bean, element); - } - @Override public Object deserialize(Object o, @NotNull Object... nodes) { - return _deserializeInto(instantiateBean(), nodes); + Element element = null; + for (Object aNode : nodes) { + if (!XmlSerializerImpl.isIgnoredNode(aNode)) { + element = (Element)aNode; + break; + } + } + + if (element == null) { + return o; + } + return deserializeInto(XmlSerializerImpl.newInstance(myBeanClass), element); } - private Object _deserializeInto(final Object result, @NotNull Object... aNodes) { - List nodes = new ArrayList(); - for (Object aNode : aNodes) { - if (XmlSerializerImpl.isIgnoredNode(aNode)) continue; - nodes.add(aNode); - } - - if (nodes.size() != 1) { - if (nodes.isEmpty()) { - return result; - } - throw new XmlSerializationException("Wrong set of nodes: " + nodes + " for bean" + myBeanClass + " in " + myAccessor); - } - assert nodes.get(0) instanceof Element : "Wrong node: " + nodes; - Element e = (Element)nodes.get(0); - - ArrayList bindings = new ArrayList(myPropertyBindings.keySet()); - - MultiMap data = new MultiMap(); - - final Object[] children = JDOMUtil.getChildNodesWithAttrs(e); + public Object deserializeInto(@NotNull Object result, @NotNull Element element) { + Set bindings = myPropertyBindings.keySet(); + MultiMap data = MultiMap.createSmartList(); nextNode: - for (Object child : children) { - if (XmlSerializerImpl.isIgnoredNode(child)) continue; + for (Object child : ContainerUtil.concat(element.getContent(), element.getAttributes())) { + if (XmlSerializerImpl.isIgnoredNode(child)) { + continue; + } for (Binding binding : bindings) { if (binding.isBoundTo(child)) { @@ -153,27 +140,19 @@ class BeanBinding implements Binding { } } - { - final String message = "Format error: no binding for " + child + " inside " + this; - LOG.debug(message); - Logger.getInstance(myBeanClass.getName()).debug(message); - Logger.getInstance("#" + myBeanClass.getName()).debug(message); - } + final String message = "Format error: no binding for " + child + " inside " + this; + LOG.debug(message); + Logger.getInstance(myBeanClass.getName()).debug(message); + Logger.getInstance("#" + myBeanClass.getName()).debug(message); } - for (Object o1 : data.keySet()) { - Binding binding = (Binding)o1; - Collection nn = data.get(binding); - binding.deserialize(result, ArrayUtil.toObjectArray(nn)); + for (Binding binding : data.keySet()) { + binding.deserialize(result, ArrayUtil.toObjectArray(data.get(binding))); } return result; } - private Object instantiateBean() { - return XmlSerializerImpl.newInstance(myBeanClass); - } - @Override public boolean isBoundTo(Object node) { return node instanceof Element && ((Element)node).getName().equals(myTagName); @@ -224,7 +203,7 @@ class BeanBinding implements Binding { for (Method method : aClass.getMethods()) { if (!Modifier.isPublic(method.getModifiers())) continue; final Pair propertyData = getPropertyData(method.getName()); // (name,isSetter) - if (propertyData == null || propertyData.first.equals(CLASS_PROPERTY)) continue; + if (propertyData == null || propertyData.first.equals("class")) continue; if (method.getParameterTypes().length != (propertyData.second ? 1 : 0)) continue; Couple candidate = candidates.get(propertyData.first); @@ -276,7 +255,7 @@ class BeanBinding implements Binding { return "BeanBinding[" + myBeanClass.getName() + ", tagName=" + myTagName + "]"; } - private static Binding createBindingByAccessor(final Accessor accessor) { + private static Binding createBindingByAccessor(@NotNull Accessor accessor) { final Binding binding = _createBinding(accessor); binding.init(); return binding; diff --git a/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java index ceceb2d26e24..622616bdb7fe 100644 --- a/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/CollectionBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import org.jetbrains.annotations.NotNull; @@ -35,10 +34,11 @@ class CollectionBinding extends AbstractCollectionBinding { return (Class)arg; } - @Override Object processResult(Collection result, Object target) { - if (myAccessor == null) return result; + if (myAccessor == null) { + return result; + } assert target != null: "Null target in " + myAccessor; assert target instanceof Collection : "Wrong target: " + target.getClass() + " in " + myAccessor; @@ -69,9 +69,7 @@ class CollectionBinding extends AbstractCollectionBinding { } @Override - protected Collection createCollection(final String tagName) { - if (tagName.equals(Constants.SET)) return new HashSet(); - if (tagName.equals(Constants.LIST)) return new ArrayList(); - return super.createCollection(tagName); + protected Collection createCollection(@NotNull String tagName) { + return tagName.equals(Constants.SET) ? new HashSet() : super.createCollection(tagName); } } diff --git a/platform/util/src/com/intellij/util/xmlb/DefaultSerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/DefaultSerializationFilter.java deleted file mode 100644 index 9eef128d3b60..000000000000 --- a/platform/util/src/com/intellij/util/xmlb/DefaultSerializationFilter.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2000-2013 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.util.xmlb; - -public class DefaultSerializationFilter implements SerializationFilter { - @Override - public boolean accepts(Accessor accessor, Object bean) { - return true; - } -} diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java index 1ddc5bc3ef1d..e47f41c9dd2e 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java @@ -97,10 +97,7 @@ public class XmlSerializer { public static void deserializeInto(@NotNull Object bean, @NotNull Element element) { try { - final Binding binding = XmlSerializerImpl.getBinding(bean.getClass()); - assert binding instanceof BeanBinding; - - ((BeanBinding)binding).deserializeInto(bean, element); + ((BeanBinding)XmlSerializerImpl.getBinding(bean.getClass())).deserializeInto(bean, element); } catch (XmlSerializationException e) { throw e; diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index 9cf513164872..80e24725f3a7 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -123,7 +123,7 @@ class XmlSerializerImpl { if (Date.class.isAssignableFrom(aClass)) return new DateBinding(); if (aClass.isEnum()) return new PrimitiveValueBinding(aClass); - return new BeanBinding(aClass, accessor); + return new BeanBinding(aClass); } @Nullable diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/Property.java b/platform/util/src/com/intellij/util/xmlb/annotations/Property.java index 48eb578f4c62..0dad892f0a64 100644 --- a/platform/util/src/com/intellij/util/xmlb/annotations/Property.java +++ b/platform/util/src/com/intellij/util/xmlb/annotations/Property.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -13,10 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb.annotations; -import com.intellij.util.xmlb.DefaultSerializationFilter; import com.intellij.util.xmlb.SerializationFilter; import java.lang.annotation.ElementType; @@ -31,5 +29,6 @@ import java.lang.annotation.Target; @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) public @interface Property { boolean surroundWithTag() default true; - Class filter() default DefaultSerializationFilter.class; + + Class filter() default SerializationFilter.class; } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java index b477e160d558..4094b47c27a3 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java @@ -33,4 +33,7 @@ public interface VcsLogUi { void setBranchesPanelVisible(boolean visible); + boolean isMultipleRoots(); + boolean isShowRootNames(); + void setShowRootNames(boolean showRootNames); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java index ff67c98fae5a..e68084e56e7d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java @@ -70,7 +70,7 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction { @NotNull @Override public AnAction[] getChildren(@Nullable AnActionEvent e) { - return new AnAction[]{new ShowBranchesPanelAction()}; + return new AnAction[]{new ShowBranchesPanelAction(), new ShowRootsColumnAction()}; } private class ShowBranchesPanelAction extends ToggleAction implements DumbAware { @@ -89,5 +89,31 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction { myUi.setBranchesPanelVisible(state); } } + + private class ShowRootsColumnAction extends ToggleAction implements DumbAware { + + public ShowRootsColumnAction() { + super("Show Root Names"); + } + + @Override + public void update(AnActionEvent e) { + super.update(e); + + boolean visible = myUi.isMultipleRoots(); + e.getPresentation().setVisible(visible); + e.getPresentation().setEnabled(visible); + } + + @Override + public boolean isSelected(AnActionEvent e) { + return myUi.isShowRootNames(); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + myUi.setShowRootNames(state); + } + } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 96f9be8bbb37..7be1211ec70c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -190,6 +190,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { public void setShowRootNames(boolean isShowRootNames) { myUiProperties.setShowRootNames(isShowRootNames); + myMainFrame.getGraphTable().rootColumnUpdated(); } public boolean isShowRootNames() { @@ -286,6 +287,11 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { } } + @Override + public boolean isMultipleRoots() { + return myColorManager.isMultipleRoots(); // somewhy color manager knows about this + } + @NotNull public VcsLogColorManager getColorManager() { return myColorManager; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index 52e4412ea277..e3b7a8b9c766 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.ui.frame; +import com.intellij.icons.AllIcons; import com.intellij.ide.CopyProvider; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.ide.CopyPasteManager; @@ -74,7 +75,9 @@ import static com.intellij.vcs.log.printer.idea.PrintParameters.HEIGHT_CELL; public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, CopyProvider { - private static final int ROOT_INDICATOR_WIDTH = 5; + private static final int ROOT_INDICATOR_COLORED_WIDTH = 8; + private static final int ROOT_INDICATOR_WHITE_WIDTH = 5; + private static final int ROOT_INDICATOR_WIDTH = ROOT_INDICATOR_WHITE_WIDTH + ROOT_INDICATOR_COLORED_WIDTH; private static final int ROOT_NAME_MAX_WIDTH = 200; private static final int MAX_DEFAULT_AUTHOR_COLUMN_WIDTH = 200; private static final int MAX_ROWS_TO_CALC_WIDTH = 1000; @@ -103,8 +106,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C myUI = UI; myLogDataHolder = logDataHolder; myDataPack = initialDataPack; - myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myGraphCellPainter, - myDataPack.getVisibleGraph(), this); + myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myGraphCellPainter, myDataPack.getVisibleGraph(), this); setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI)); setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRender); @@ -117,6 +119,9 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C MouseAdapter mouseAdapter = new MyMouseAdapter(); addMouseMotionListener(mouseAdapter); addMouseListener(mouseAdapter); + MyHeaderMouseAdapter headerAdapter = new MyHeaderMouseAdapter(); + getTableHeader().addMouseListener(headerAdapter); + getTableHeader().addMouseMotionListener(headerAdapter); getTableHeader().setReorderingAllowed(false); @@ -132,6 +137,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C myColumnsSizeInitialized = true; setColumnPreferredSize(); setAutoCreateColumnsFromModel(false); // otherwise sizes are recalculated after each TableColumn re-initialization + + getColumnModel().getColumn(GraphTableModel.ROOT_COLUMN).setHeaderRenderer(new RootHeaderRenderer()); } } @@ -164,7 +171,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private void setRootColumnSize(TableColumn column) { int rootWidth; - if (!myUI.getColorManager().isMultipleRoots()) { + if (!myUI.isMultipleRoots()) { rootWidth = 0; } else if (!myUI.isShowRootNames()) { @@ -209,7 +216,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C if (column == GraphTableModel.ROOT_COLUMN) { Object at = getValueAt(row, column); if (at instanceof VirtualFile) { - return "" + ((VirtualFile)at).getPresentableUrl() + "
Double-click to " + (myUI.isShowRootNames() ? "collapse" : "expand") + ""; + return "" + ((VirtualFile)at).getPresentableUrl() + "
Click to " + (myUI.isShowRootNames() ? "collapse" : "expand") + ""; } } return null; @@ -338,6 +345,52 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C }); } + private boolean expandOrCollapseRoots(MouseEvent e) { + TableColumn column = getRootColumnOrNull(e); + if (column != null) { + myUI.setShowRootNames(!myUI.isShowRootNames()); + return true; + } + return false; + } + + public void rootColumnUpdated() { + setColumnPreferredSize(); + setRootColumnSize(getColumnModel().getColumn(GraphTableModel.ROOT_COLUMN)); + } + + @Nullable + private TableColumn getRootColumnOrNull(MouseEvent e) { + if (!myLogDataHolder.isMultiRoot()) return null; + int column = convertColumnIndexToModel(columnAtPoint(e.getPoint())); + if (column == GraphTableModel.ROOT_COLUMN) { + return getColumnModel().getColumn(column); + } + return null; + } + + private class MyHeaderMouseAdapter extends MouseAdapter { + @Override + public void mouseMoved(MouseEvent e) { + Component component = e.getComponent(); + if (component != null) { + if (getRootColumnOrNull(e) != null) { + component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + else { + component.setCursor(null); + } + } + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 1) { + expandOrCollapseRoots(e); + } + } + } + private class MyMouseAdapter extends MouseAdapter { private final TableLinkMouseListener myLinkListener; @@ -351,16 +404,15 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C return; } - if (e.getClickCount() > 1) { - expandOrCollapseRoots(e); - } else if (e.getClickCount() == 1) { + if (e.getClickCount() == 1) { + if (expandOrCollapseRoots(e)) return; performAction(e, MyGraphMouseAction.Type.CLICK); } } @Override public void mouseMoved(MouseEvent e) { - if (isAboveLink(e)) { + if (isAboveLink(e) || isAboveRoots(e)) { setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else { @@ -368,17 +420,6 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C } } - private boolean expandOrCollapseRoots(MouseEvent e) { - int column = convertColumnIndexToModel(columnAtPoint(e.getPoint())); - if (column == GraphTableModel.ROOT_COLUMN && myLogDataHolder.isMultiRoot()) { - myUI.setShowRootNames(!myUI.isShowRootNames()); - setColumnPreferredSize(); - setRootColumnSize(getColumnModel().getColumn(column)); - return true; - } - return false; - } - private void performAction(@NotNull MouseEvent e, @NotNull final MyGraphMouseAction.Type actionType) { int row = PositionUtil.getRowIndex(e.getPoint()); if (row > getRowCount() - 1) { @@ -397,6 +438,12 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C return myLinkListener.getTagAt(e) != null; } + private boolean isAboveRoots(MouseEvent e) { + TableColumn column = getRootColumnOrNull(e); + int row = rowAtPoint(e.getPoint()); + return column != null && (row >= 0 && row < getRowCount()); + } + @Override public void mouseEntered(MouseEvent e) { // Do nothing @@ -443,7 +490,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private static class RootCellRenderer extends JBLabel implements TableCellRenderer { @NotNull private final VcsLogUiImpl myUi; @NotNull private Color myColor = UIUtil.getTableBackground(); - private boolean myHasBorder; + @NotNull private Color myBorderColor = UIUtil.getTableBackground(); + private boolean isNarrow = true; RootCellRenderer(@NotNull VcsLogUiImpl ui) { super("", CENTER); @@ -456,13 +504,14 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C int width = getWidth(); - if (myHasBorder) { - g.fillRect(0, 0, width - 1, HEIGHT_CELL); - UIUtil.drawLine((Graphics2D)g, width - 1, 0, width - 1, HEIGHT_CELL, null, myUi.getColorManager().getRootIndicatorBorder()); - } - else { + if (isNarrow) { + g.fillRect(0, 0, width - ROOT_INDICATOR_WHITE_WIDTH, HEIGHT_CELL); + g.setColor(myBorderColor); + g.fillRect(width - ROOT_INDICATOR_WHITE_WIDTH, 0, ROOT_INDICATOR_WHITE_WIDTH, HEIGHT_CELL); + } else { g.fillRect(0, 0, width, HEIGHT_CELL); } + super.paintComponent(g); } @@ -488,28 +537,20 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C color = UIUtil.getTableBackground(isSelected); } - if (myUi.isShowRootNames()) { - // pale colors, honors selection, does not have border - if (isSelected) { - myColor = UIUtil.getTableBackground(isSelected); - } - else { - //we create JBColor later - //noinspection UseJBColor - Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 50); - myColor = new JBColor(transparentColor, transparentColor); - } + //we create JBColor later + //noinspection UseJBColor + Color transparentColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 50); + myColor = new JBColor(transparentColor, transparentColor); + myBorderColor = UIUtil.getTableBackground(isSelected); + setForeground(UIUtil.getTableForeground(false)); - setForeground(UIUtil.getTableForeground(isSelected)); + if (myUi.isShowRootNames()) { setText(text); - myHasBorder = false; + isNarrow = false; } else { - // bright colors, does not know about the selection, has border - setForeground(UIUtil.getTableForeground(false)); - myColor = color; setText(""); - myHasBorder = true; + isNarrow = true; } return this; @@ -528,4 +569,18 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C } } + + private class RootHeaderRenderer implements TableCellRenderer { + private final JLabel myRightArrow = new JLabel(AllIcons.General.ComboArrowRight); + private final JLabel myDownArrow = new JLabel("Root", SwingConstants.CENTER); + + @NotNull + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (myUI.isShowRootNames()) { + return myDownArrow; + } + return myRightArrow; + } + } } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java index d06459244216..e008252ecf85 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java @@ -174,27 +174,10 @@ public abstract class XDebuggerEvaluator { } /** - * Returns expression that is selected or under the cursor in the Editor + * Returns mode which should be used to evaluate the text */ - public XExpression getEditorExpression(@NotNull Editor editor, @Nullable PsiFile psiFile) { - String text = editor.getSelectionModel().getSelectedText(); - if (text != null) { - text = formatTextForEvaluation(text); - } - else if (editor.getProject() != null) { - Document document = editor.getDocument(); - ExpressionInfo info = getExpressionInfoAtOffset(editor.getProject(), document, editor.getCaretModel().getOffset(), true); - if (info != null) { - text = info.getExpressionText(); - if (text == null) { - text = document.getText(info.getTextRange()); - } - } - } - if (!StringUtil.isEmpty(text)) { - return XDebuggerUtil.getInstance().createExpression(text, null, null, text.contains("\n") ? EvaluationMode.CODE_FRAGMENT : EvaluationMode.EXPRESSION); - } - return null; + public EvaluationMode getEvaluationMode(@NotNull String text, int startOffset, int endOffset, @Nullable PsiFile psiFile) { + return text.contains("\n") ? EvaluationMode.CODE_FRAGMENT : EvaluationMode.EXPRESSION; } @Deprecated diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XInstanceEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XInstanceEvaluator.java index 98fb827b646f..433304f335c5 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XInstanceEvaluator.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XInstanceEvaluator.java @@ -19,8 +19,14 @@ import com.intellij.xdebugger.frame.XStackFrame; import org.jetbrains.annotations.NotNull; /** -* @author egor -*/ + * Subclass to allow to recalculate instance value in a different context + * + * @author egor + */ public interface XInstanceEvaluator { + /** + * Recalculates instance value in the context of the provided stack frame + * @see XDebuggerEvaluator + */ void evaluate(@NotNull XDebuggerEvaluator.XEvaluationCallback callback, @NotNull XStackFrame frame); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java index ca06ab25a13f..b6875bec0664 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java @@ -21,12 +21,12 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; +import com.intellij.xdebugger.evaluation.EvaluationMode; import com.intellij.xdebugger.evaluation.ExpressionInfo; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; @@ -54,34 +54,28 @@ public class XDebuggerEvaluateActionHandler extends XDebuggerActionHandler { Editor editor = CommonDataKeys.EDITOR.getData(dataContext); - XExpression expression = null; - if (editor != null) { - expression = evaluator.getEditorExpression(editor, CommonDataKeys.PSI_FILE.getData(dataContext)); + EvaluationMode mode = EvaluationMode.EXPRESSION; + String selectedText = editor != null ? editor.getSelectionModel().getSelectedText() : null; + if (selectedText != null) { + selectedText = evaluator.formatTextForEvaluation(selectedText); + mode = evaluator.getEvaluationMode(selectedText, + editor.getSelectionModel().getSelectionStart(), + editor.getSelectionModel().getSelectionEnd(), + CommonDataKeys.PSI_FILE.getData(dataContext)); + } + String text = selectedText; + + if (text == null && editor != null) { + text = getExpressionText(evaluator, CommonDataKeys.PROJECT.getData(dataContext), editor); } - Language language = calcLanguage(stackFrame, dataContext); - - if (expression != null && !Comparing.equal(language, expression.getLanguage())) { // may need to change language - expression = new XExpressionImpl(expression.getExpression(), language, expression.getCustomInfo(), expression.getMode()); - } - - if (expression == null) { + if (text == null) { XValue value = XDebuggerTreeActionBase.getSelectedValue(dataContext); if (value != null) { - String text = value.getEvaluationExpression(); - if (!StringUtil.isEmpty(text)) { - expression = new XExpressionImpl(text, language, null); - } + text = value.getEvaluationExpression(); } } - if (expression == null) { - expression = new XExpressionImpl("", language, null); - } - new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, expression, stackFrame == null ? null : stackFrame.getSourcePosition()).show(); - } - - private static Language calcLanguage(XStackFrame stackFrame, DataContext dataContext) { Language language = null; if (stackFrame != null) { XSourcePosition position = stackFrame.getSourcePosition(); @@ -95,7 +89,8 @@ public class XDebuggerEvaluateActionHandler extends XDebuggerActionHandler { language = XDebuggerEditorBase.getFileTypeLanguage(file.getFileType()); } } - return language; + XExpression expression = new XExpressionImpl(StringUtil.notNullize(text), language, null, mode); + new XDebuggerEvaluationDialog(session, editorsProvider, evaluator, expression, stackFrame == null ? null : stackFrame.getSourcePosition()).show(); } @Nullable diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index 1bd7e09b20c5..5c8e829b7be0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -323,6 +323,10 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { } } + public void evaluationDone() { + mySession.rebuildViews(); + } + @Override public JComponent getPreferredFocusedComponent() { return getInputEditor().getPreferredFocusedComponent(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java index fb052a410e08..c0a13c07fd54 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java @@ -22,6 +22,7 @@ import com.intellij.ui.AppUIUtil; import com.intellij.ui.SimpleColoredComponent; import com.intellij.xdebugger.frame.XValueModifier; import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.XDebuggerUtilImpl; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; @@ -82,6 +83,7 @@ public class SetValueInplaceEditor extends XDebuggerTreeInplaceEditor { myTree.rebuildAndRestore(treeState); } }); + XDebuggerUtilImpl.rebuildAllSessionsViews(getProject()); } @Override @@ -100,6 +102,7 @@ public class SetValueInplaceEditor extends XDebuggerTreeInplaceEditor { } } }); + XDebuggerUtilImpl.rebuildAllSessionsViews(getProject()); } }); super.doOKAction(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java index b6269228a393..5de988cf3497 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java @@ -49,7 +49,7 @@ public class XInspectDialog extends DialogWrapper { @NotNull String name, @NotNull XValue value, XValueMarkers markers, - XDebugSession session, + @NotNull XDebugSession session, boolean rebuildOnSessionEvents) { super(project, false); myRebuildOnSessionEvents = rebuildOnSessionEvents; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java index 4884748d5ba7..648a018eb6d4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/ShowReferringObjectsAction.java @@ -18,6 +18,7 @@ package com.intellij.xdebugger.impl.ui.tree.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.frame.XReferrersProvider; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.XInspectDialog; @@ -39,15 +40,17 @@ public class ShowReferringObjectsAction extends XDebuggerTreeActionBase { XReferrersProvider referrersProvider = node.getValueContainer().getReferrersProvider(); if (referrersProvider != null) { XDebuggerTree tree = node.getTree(); - XDebugSession session = e.getData(XDebugSession.DATA_KEY); - XInspectDialog dialog = new XInspectDialog(tree.getProject(), - tree.getEditorsProvider(), - tree.getSourcePosition(), - nodeName, - referrersProvider.getReferringObjectsValue(), - tree.getValueMarkers(), session, false); - dialog.setTitle(XDebuggerBundle.message("showReferring.dialog.title", nodeName)); - dialog.show(); + XDebugSession session = XDebuggerManager.getInstance(tree.getProject()).getCurrentSession(); + if (session != null) { + XInspectDialog dialog = new XInspectDialog(tree.getProject(), + tree.getEditorsProvider(), + tree.getSourcePosition(), + nodeName, + referrersProvider.getReferringObjectsValue(), + tree.getValueMarkers(), session, false); + dialog.setTitle(XDebuggerBundle.message("showReferring.dialog.title", nodeName)); + dialog.show(); + } } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java index 0b04da39d1a1..eb82e5e4a75f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java @@ -17,6 +17,7 @@ package com.intellij.xdebugger.impl.ui.tree.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.XInspectDialog; @@ -29,11 +30,13 @@ import org.jetbrains.annotations.NotNull; public class XInspectAction extends XDebuggerTreeActionBase { @Override protected void perform(XValueNodeImpl node, @NotNull final String nodeName, AnActionEvent e) { - XDebugSession session = e.getData(XDebugSession.DATA_KEY); XDebuggerTree tree = node.getTree(); XValue value = node.getValueContainer(); - XInspectDialog dialog = new XInspectDialog(tree.getProject(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value, - tree.getValueMarkers(), session, true); - dialog.show(); + XDebugSession session = XDebuggerManager.getInstance(tree.getProject()).getCurrentSession(); + if (session != null) { + XInspectDialog dialog = new XInspectDialog(tree.getProject(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value, + tree.getValueMarkers(), session, true); + dialog.show(); + } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java index 381bef8be9a4..2482717d7017 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/EvaluatingExpressionRootNode.java @@ -53,11 +53,13 @@ public class EvaluatingExpressionRootNode extends XValueContainerNode - diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index cef6f049d95e..9997be05884c 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2121,6 +2121,7 @@ return.of.inner.class.display.name=Return of instance of anonymous, local or inn return.of.anonymous.class.problem.descriptor=Return of instance of anonymous class #loc return.of.local.class.problem.descriptor=Return of instance of local class {0} #loc return.of.inner.class.problem.descriptor=Return of instance of non-static inner class {0} #loc +return.of.inner.class.ignore.non.public.option=Ignore returns from non-public methods parameter.type.prevents.overriding.display.name=Parameter type prevents overriding parameter.type.prevents.overriding.problem.descriptor=Parameter type #ref is located in ''{0}'' while super method parameter type is located in ''{1}'' preventing overriding parameter.type.prevents.overriding.quickfix=Change type of parameter to ''{0}'' diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/memory/ReturnOfInnerClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/memory/ReturnOfInnerClassInspection.java index f8d9f8e17226..72e59e1eb4a6 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/memory/ReturnOfInnerClassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/memory/ReturnOfInnerClassInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.memory; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -24,12 +25,17 @@ import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.ParenthesesUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; /** * @author Bas Leijdekkers */ public class ReturnOfInnerClassInspection extends BaseInspection { + @SuppressWarnings("PublicField") public boolean ignoreNonPublic = false; + private enum ClassType { ANONYMOUS_CLASS, LOCAL_CLASS, INNER_CLASS } @Nls @@ -58,12 +64,19 @@ public class ReturnOfInnerClassInspection extends BaseInspection { } } + @Nullable + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("return.of.inner.class.ignore.non.public.option"), + this, "ignoreNonPublic"); + } + @Override public BaseInspectionVisitor buildVisitor() { return new ReturnOfInnerClassVisitor(); } - private static class ReturnOfInnerClassVisitor extends BaseInspectionVisitor { + private class ReturnOfInnerClassVisitor extends BaseInspectionVisitor { @Override public void visitReturnStatement(PsiReturnStatement statement) { @@ -76,6 +89,10 @@ public class ReturnOfInnerClassInspection extends BaseInspection { if (method == null || method.hasModifierProperty(PsiModifier.PRIVATE)) { return; } + else if (ignoreNonPublic && + (method.hasModifierProperty(PsiModifier.PROTECTED) || method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL))) { + return; + } if (expression instanceof PsiNewExpression) { final PsiNewExpression newExpression = (PsiNewExpression)expression; final PsiAnonymousClass anonymousClass = newExpression.getAnonymousClass(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java index 92fbe8c0d6d0..0d2b13db4d16 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java @@ -207,7 +207,10 @@ public class UnclearBinaryExpressionInspection extends BaseInspection { private static boolean isSimpleAssignment(PsiAssignmentExpression assignmentExpression, PsiElement parent) { final IElementType parentTokenType; - if (parent instanceof PsiAssignmentExpression) { + if (parent instanceof PsiExpressionStatement) { + return true; + } + else if (parent instanceof PsiAssignmentExpression) { final PsiAssignmentExpression parentAssignmentExpression = (PsiAssignmentExpression)parent; parentTokenType = parentAssignmentExpression.getOperationTokenType(); } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnOfInnerClass.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnOfInnerClass.html index ab13400bf18d..89cdfed9fd1f 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnOfInnerClass.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnOfInnerClass.html @@ -5,6 +5,9 @@ Such instances keep an implicit reference to the outer instance. Which means the instance can prevent the outer instance from being garbage collected. Any caller of a method which returns such an instance might cause a memory leak by holding on to the instance returned.

+Use the checkbox below to ignore returns from protected or package-local methods. +Returns from private methods are always ignored. +

New in 14 \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.after.java new file mode 100644 index 000000000000..247b0942ab14 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.after.java @@ -0,0 +1,10 @@ +class SimpleAssignment { + + public void baz() { + int a = 2; + int b = 3; + int c = 4; + int d; + d = (a / b) * c; + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.java new file mode 100644 index 000000000000..c64c0c0079f8 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unclear_binary_expression/SimpleAssignment.java @@ -0,0 +1,10 @@ +class SimpleAssignment { + + public void baz() { + int a = 2; + int b = 3; + int c = 4; + int d; + d = a / b * c; + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnclearBinaryExpressionFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnclearBinaryExpressionFixTest.java new file mode 100644 index 000000000000..bb2e5a9422f3 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnclearBinaryExpressionFixTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 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.siyeh.ig.fixes.style; + +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.IGQuickFixesTestCase; +import com.siyeh.ig.style.UnclearBinaryExpressionInspection; + +/** + * @author Bas Leijdekkers + */ +public class UnclearBinaryExpressionFixTest extends IGQuickFixesTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new UnclearBinaryExpressionInspection()); + myRelativePath = "style/unclear_binary_expression"; + myDefaultHint = InspectionGadgetsBundle.message("unclear.binary.expression.quickfix"); + } + + public void testSimpleAssignment() { doTest(); } +} diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java index 7ee3e0f45bbe..0b353fafd97b 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.*; -import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; @@ -36,7 +35,7 @@ public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention { } @Override - public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { + public void processIntention(@NotNull PsiElement element) { final PsiForeachStatement statement = (PsiForeachStatement)element.getParent(); if (statement == null) { return; @@ -134,6 +133,7 @@ public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention { newStatement.append("{ "); } + @Nullable private static String getVariableName(PsiExpression expression) { if (expression instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = @@ -165,7 +165,8 @@ public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention { (PsiArrayAccessExpression)expression; final PsiExpression arrayExpression = arrayAccessExpression.getArrayExpression(); - return StringUtil.unpluralize(getVariableName(arrayExpression)); + final String name = getVariableName(arrayExpression); + return (name == null) ? null : StringUtil.unpluralize(name); } else if (expression instanceof PsiParenthesizedExpression) { final PsiParenthesizedExpression parenthesizedExpression = diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE.java new file mode 100644 index 000000000000..226489b33ba0 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE.java @@ -0,0 +1,8 @@ +class NoNPE { + + void m(String[][] ss) { + for (String s : (ss = new String[][]{})[0]) { + + } + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE_after.java new file mode 100644 index 000000000000..12e0f3b05331 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/forloop/indexed/NoNPE_after.java @@ -0,0 +1,10 @@ +class NoNPE { + + void m(String[][] ss) { + String[] strings = (ss = new String[][]{})[0]; + for (int i = 0, stringsLength = strings.length; i < stringsLength; i++) { + String s = strings[i]; + + } + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntentionTest.java index 5dfae35f349c..ff3f9ed80317 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntentionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -23,6 +23,7 @@ public class ReplaceForEachLoopWithIndexedForLoopIntentionTest extends IPPTestCa public void testNormalForeachLoop() { doTest(); } public void testThisExpr() { doTest(); } public void testNewArray() { doTest(); } + public void testNoNPE() { doTest(); } @Override protected String getIntentionName() { diff --git a/plugins/devkit/src/DevKitUseScopeEnlarger.java b/plugins/devkit/src/DevKitUseScopeEnlarger.java index 6b55133eb251..e66043fa5d7e 100644 --- a/plugins/devkit/src/DevKitUseScopeEnlarger.java +++ b/plugins/devkit/src/DevKitUseScopeEnlarger.java @@ -18,7 +18,9 @@ package org.jetbrains.idea.devkit; import com.intellij.ide.highlighter.XmlFileType; import com.intellij.pom.PomTarget; import com.intellij.pom.PomTargetPsiElement; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiModifier; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.UseScopeEnlarger; @@ -26,11 +28,13 @@ import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomTarget; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.devkit.dom.ExtensionPoint; +import org.jetbrains.idea.devkit.util.PsiUtil; /** * @author peter */ public class DevKitUseScopeEnlarger extends UseScopeEnlarger { + @Override public SearchScope getAdditionalUseScope(@NotNull PsiElement element) { if (element instanceof PomTargetPsiElement) { @@ -38,11 +42,21 @@ public class DevKitUseScopeEnlarger extends UseScopeEnlarger { if (target instanceof DomTarget) { DomElement domElement = ((DomTarget)target).getDomElement(); if (domElement instanceof ExtensionPoint) { - return GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(element.getProject()), - XmlFileType.INSTANCE); + return createProjectXmlFilesScope(element); } } } + + if (element instanceof PsiClass && + PsiUtil.isIdeaProject(element.getProject()) && + ((PsiClass)element).hasModifierProperty(PsiModifier.PUBLIC)) { + return createProjectXmlFilesScope(element); + } return null; } + + private static SearchScope createProjectXmlFilesScope(PsiElement element) { + return GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(element.getProject()), + XmlFileType.INSTANCE); + } } diff --git a/plugins/java-decompiler/engine/build.xml b/plugins/java-decompiler/engine/build.xml index 8dde32e6adda..6ed39f0a45cc 100644 --- a/plugins/java-decompiler/engine/build.xml +++ b/plugins/java-decompiler/engine/build.xml @@ -46,13 +46,14 @@ - + + diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index feb80939035b..9fcf4bb3493f 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -43,10 +43,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.generics.*; import org.jetbrains.java.decompiler.util.InterpreterUtil; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class ClassWriter { @@ -160,11 +157,11 @@ public class ClassWriter { DecompilerContext.getLogger().endWriteClass(); } - public void classToJava(ClassNode node, TextBuffer buffer, int indent) { + public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) { ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); - int total_offset_lines = 0; + final int startLine = tracer != null ? tracer.getCurrentSourceLine() : 0; BytecodeMappingTracer dummy_tracer = new BytecodeMappingTracer(); try { @@ -176,14 +173,12 @@ public class ClassWriter { DecompilerContext.getLogger().startWriteClass(cl.qualifiedName); - String lineSeparator = DecompilerContext.getNewLineSeparator(); - // write class definition int start_class_def = buffer.length(); writeClassDefinition(node, buffer, indent); // // count lines in class definition the easiest way -// total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1; +// startLine = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1; boolean hasContent = false; @@ -199,14 +194,14 @@ public class ClassWriter { if (isEnum) { if (enumFields) { buffer.append(','); - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } enumFields = true; } else if (enumFields) { buffer.append(';'); - buffer.append(lineSeparator); - buffer.append(lineSeparator); + buffer.appendLineSeparator(); + buffer.appendLineSeparator(); enumFields = false; } @@ -217,11 +212,11 @@ public class ClassWriter { if (enumFields) { buffer.append(';'); - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } // FIXME: fields don't matter at the moment - total_offset_lines = buffer.count(lineSeparator, start_class_def); + //startLine = buffer.countLines(start_class_def); // methods for (StructMethod mt : cl.getMethods()) { @@ -232,15 +227,15 @@ public class ClassWriter { int position = buffer.length(); if (hasContent) { - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } - BytecodeMappingTracer method_tracer = new BytecodeMappingTracer(total_offset_lines); + BytecodeMappingTracer method_tracer = new BytecodeMappingTracer(buffer.countLines() + startLine); boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1, method_tracer); if (!methodSkipped) { hasContent = true; DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); - total_offset_lines = (method_tracer.getCurrentSourceLine() + 1); // zero-based line index + //startLine = (method_tracer.getCurrentSourceLine() + 1); // zero-based line index } else { buffer.setLength(position); @@ -257,9 +252,9 @@ public class ClassWriter { if (hide) continue; if (hasContent) { - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } - classToJava(inner, buffer, indent + 1); + classToJava(inner, buffer, indent + 1, tracer); hasContent = true; } @@ -268,7 +263,7 @@ public class ClassWriter { buffer.appendIndent(indent).append('}'); if (node.type != ClassNode.CLASS_ANONYMOUS) { - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } } finally { @@ -794,7 +789,7 @@ public class ClassWriter { } buffer.append(';'); - buffer.append(lineSeparator); + buffer.appendLineSeparator(); } else { if (!clinit && !dinit) { @@ -811,7 +806,7 @@ public class ClassWriter { if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence try { - tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method)); + tracer.incrementCurrentSourceLine(buffer.countLines(start_index_method)); int startLine = tracer.getCurrentSourceLine(); TextBuffer code = root.toJava(indent + 1, tracer); @@ -845,31 +840,36 @@ public class ClassWriter { // save total lines // TODO: optimize - tracer.setCurrentSourceLine(buffer.count(lineSeparator, start_index_method)); + tracer.setCurrentSourceLine(buffer.countLines(start_index_method)); return !hideMethod; } private void mapLines(TextBuffer code, StructLineNumberTableAttribute table, BytecodeMappingTracer tracer, int startLine) { // build line start offsets map - HashMap lineStartOffsets = new HashMap(); + HashMap> lineStartOffsets = new HashMap>(); for (Map.Entry entry : tracer.getMapping().entrySet()) { Integer lineNumber = entry.getValue() - startLine; - Integer curr = lineStartOffsets.get(lineNumber); - if (curr == null || curr > entry.getKey()) { - lineStartOffsets.put(lineNumber, entry.getKey()); + Set curr = lineStartOffsets.get(lineNumber); + if (curr == null) { + curr = new TreeSet(); // requires natural sorting! } + curr.add(entry.getKey()); + lineStartOffsets.put(lineNumber, curr); } String lineSeparator = DecompilerContext.getNewLineSeparator(); StringBuilder text = code.getOriginalText(); int pos = text.indexOf(lineSeparator); int lineNumber = 0; while (pos != -1) { - Integer startOffset = lineStartOffsets.get(lineNumber); - if (startOffset != null) { - int number = table.findLineNumber(startOffset); - if (number >= 0) { - code.setLineMapping(number, pos); + Set startOffsets = lineStartOffsets.get(lineNumber); + if (startOffsets != null) { + for (Integer offset : startOffsets) { + int number = table.findLineNumber(offset); + if (number >= 0) { + code.setLineMapping(number, pos); + break; + } } } pos = text.indexOf(lineSeparator, pos+1); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 262b825fd9e6..3fe0e0125547 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -256,7 +256,7 @@ public class ClassesProcessor { new NestedMemberAccess().propagateMemberAccess(root); TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE); - new ClassWriter().classToJava(root, classBuffer, 0); + new ClassWriter().classToJava(root, classBuffer, 0, null); String lineSeparator = DecompilerContext.getNewLineSeparator(); int total_offset_lines = 0; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java index e631a51a92e8..b952811653e7 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/TextBuffer.java @@ -115,7 +115,7 @@ public class TextBuffer { while (currentLine < srcLines.length) { String line = srcLines[currentLine]; int lineEnd = currentLineStartOffset + line.length() + myLineSeparator.length(); - if (markOffset >= currentLineStartOffset && markOffset <= lineEnd) { + if (markOffset <= lineEnd) { int requiredLine = markLine - 1; int linesToAdd = requiredLine - dumpedLines; dumpedLines = requiredLine; @@ -223,6 +223,14 @@ public class TextBuffer { return this; } + public int countLines() { + return countLines(0); + } + + public int countLines(int from) { + return count(myLineSeparator, from); + } + public int count(String substring, int from) { int count = 0, length = substring.length(), p = from; while ((p = myStringBuilder.indexOf(substring, p)) > 0) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java index 6cbaa839eb4f..0f1bb4da0267 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java @@ -1,9 +1,6 @@ package org.jetbrains.java.decompiler.main.collectors; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.Map.Entry; import org.jetbrains.java.decompiler.main.DecompilerContext; @@ -14,13 +11,13 @@ public class BytecodeSourceMapper { private int offset_total; // class, method, bytecode offset, source line - private HashMap>> mapping = new HashMap>>(); + private final HashMap>> mapping = new LinkedHashMap>>(); // need to preserve order public void addMapping(String classname, String methodname, int bytecode_offset, int source_line) { HashMap> class_mapping = mapping.get(classname); if(class_mapping == null) { - mapping.put(classname, class_mapping = new HashMap>()); + mapping.put(classname, class_mapping = new LinkedHashMap>()); // need to preserve order } HashMap method_mapping = class_mapping.get(methodname); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java index 6178ee46862d..a810a215bec5 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java @@ -270,9 +270,11 @@ public class NewExprent extends Exprent { } Exprent methodObject = constructor == null ? null : constructor.getInstance(); new ClassWriter().classLambdaToJava(child, buf, methodObject, indent); + tracer.incrementCurrentSourceLine(buf.countLines()); } else { - new ClassWriter().classToJava(child, buf, indent); + new ClassWriter().classToJava(child, buf, indent, tracer); + tracer.incrementCurrentSourceLine(buf.countLines()); } } else if (directArrayInit) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index 60a4efa15523..191046438908 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -17,7 +17,6 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import java.util.ArrayList; import java.util.List; -import java.util.Set; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassWriter; @@ -92,7 +91,7 @@ public class VarExprent extends Exprent { if (classdef) { ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(vartype.value); - new ClassWriter().classToJava(child, buffer, indent); + new ClassWriter().classToJava(child, buffer, indent, tracer); } else { String name = null; diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping$1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping$1.class new file mode 100644 index 000000000000..93a9cb210c09 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping$1.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping.class index 1313994dfa06..4e4f8fbe16f8 100644 Binary files a/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping.class and b/plugins/java-decompiler/engine/testData/classes/pkg/TestClassSimpleBytecodeMapping.class differ diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec index 51adb532c8de..3742f9658b58 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec @@ -3,6 +3,11 @@ package pkg; public class TestClassSimpleBytecodeMapping { public int test() { System.out.println("before"); + this.run(new Runnable() { + public void run() { + System.out.println("Runnable"); + } + }); if(Math.random() > 0.0D) { System.out.println("0"); return 0; @@ -11,26 +16,42 @@ public class TestClassSimpleBytecodeMapping { return 1; } } + + void run(Runnable var1) { + var1.run(); + } } +class pkg/TestClassSimpleBytecodeMapping$1{ + method run ()V{ + 0 7 + 3 7 + 5 7 + } +} class pkg/TestClassSimpleBytecodeMapping{ method test ()I{ 0 4 3 4 5 4 - 8 5 - b 5 - c 5 - d 5 - 10 6 - 13 6 - 15 6 - 18 7 - 19 7 - 1a 9 - 1d 9 - 1f 9 - 22 10 - 23 10 + 11 5 + 14 10 + 17 10 + 18 10 + 19 10 + 1c 11 + 1f 11 + 21 11 + 24 12 + 25 12 + 26 14 + 29 14 + 2b 14 + 2e 15 + 2f 15 + } + + method run (Ljava/lang/Runnable;)V{ + 1 20 } } diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestClassSimpleBytecodeMapping.java b/plugins/java-decompiler/engine/testData/src/pkg/TestClassSimpleBytecodeMapping.java index 8233fa95154b..0e9ecc2d3201 100644 --- a/plugins/java-decompiler/engine/testData/src/pkg/TestClassSimpleBytecodeMapping.java +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestClassSimpleBytecodeMapping.java @@ -1,5 +1,8 @@ package pkg; +import java.lang.Override; +import java.lang.Runnable; + public class TestClassSimpleBytecodeMapping { public TestClassSimpleBytecodeMapping() {} @@ -7,7 +10,14 @@ public class TestClassSimpleBytecodeMapping { public int test() { System.out.println("before"); - + + run(new Runnable() { + @Override + public void run() { + System.out.println("Runnable"); + } + }); + if(Math.random() > 0) { System.out.println("0"); return 0; @@ -17,4 +27,7 @@ public class TestClassSimpleBytecodeMapping { } } + void run(Runnable r) { + r.run(); + } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index b63072340d5a..7f2a6dd4cd48 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 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. @@ -25,7 +25,6 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.rmi.RemoteProcessSupport; import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; @@ -38,9 +37,10 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Alarm; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xmlb.Converter; +import com.intellij.util.xmlb.annotations.Attribute; import gnu.trove.THashMap; import org.apache.lucene.search.Query; -import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,9 +65,9 @@ import java.util.Map; @State( name = "MavenVersion", - storages = {@Storage( - file = StoragePathMacros.APP_CONFIG + "/mavenVersion.xml")}) -public class MavenServerManager extends RemoteObjectWrapper implements PersistentStateComponent { + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/mavenVersion.xml") +) +public class MavenServerManager extends RemoteObjectWrapper implements PersistentStateComponent { @NonNls private static final String MAIN_CLASS = "org.jetbrains.idea.maven.server.RemoteMavenServer"; private static final String DEFAULT_VM_OPTIONS = "-Xmx512m"; @@ -81,9 +81,16 @@ public class MavenServerManager extends RemoteObjectWrapper impleme private final Alarm myShutdownAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); - private boolean useMaven2 = false; - private String mavenEmbedderVMOptions = DEFAULT_VM_OPTIONS; - private String embedderJdk = MavenRunnerSettings.USE_INTERNAL_JAVA; + private State myState = new State(); + + static class State { + @Attribute(value = "version", converter = UseMavenConverter.class) + public boolean useMaven2; + @Attribute + public String vmOptions = DEFAULT_VM_OPTIONS; + @Attribute + public String embedderJdk = MavenRunnerSettings.USE_INTERNAL_JAVA; + } public static MavenServerManager getInstance() { return ServiceManager.getService(MavenServerManager.class); @@ -103,18 +110,21 @@ public class MavenServerManager extends RemoteObjectWrapper impleme } @Override - protected RunProfileState getRunProfileState(Object target, Object configuration, Executor executor) throws ExecutionException { + protected RunProfileState getRunProfileState(Object target, Object configuration, Executor executor) { return createRunProfileState(); } }; ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { + @Override public void run() { shutdown(false); } }); } + @SuppressWarnings("ConstantConditions") + @Override @NotNull protected synchronized MavenServer create() throws RemoteException { MavenServer result; @@ -141,6 +151,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme cleanup(); } + @Override protected synchronized void cleanup() { super.cleanup(); @@ -168,7 +179,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme @NotNull private Sdk getJdk() { - if (embedderJdk.equals(MavenRunnerSettings.USE_JAVA_HOME)) { + if (myState.embedderJdk.equals(MavenRunnerSettings.USE_JAVA_HOME)) { final String javaHome = System.getenv("JAVA_HOME"); if (!StringUtil.isEmptyOrSpaces(javaHome)) { Sdk jdk = JavaSdk.getInstance().createJdk("", javaHome); @@ -179,7 +190,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme } for (Sdk projectJdk : ProjectJdkTable.getInstance().getAllJdks()) { - if (projectJdk.getName().equals(embedderJdk)) { + if (projectJdk.getName().equals(myState.embedderJdk)) { return projectJdk; } } @@ -190,7 +201,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme private RunProfileState createRunProfileState() { return new CommandLineState(null) { - private SimpleJavaParameters createJavaParameters() throws ExecutionException { + private SimpleJavaParameters createJavaParameters() { final SimpleJavaParameters params = new SimpleJavaParameters(); params.setJdk(getJdk()); @@ -233,9 +244,9 @@ public class MavenServerManager extends RemoteObjectWrapper impleme boolean xmxSet = false; - if (mavenEmbedderVMOptions != null) { + if (myState.vmOptions != null) { ParametersList mavenOptsList = new ParametersList(); - mavenOptsList.addParametersString(mavenEmbedderVMOptions); + mavenOptsList.addParametersString(myState.vmOptions); for (String param : mavenOptsList.getParameters()) { if (param.startsWith("-Xmx")) { @@ -269,12 +280,14 @@ public class MavenServerManager extends RemoteObjectWrapper impleme return params; } + @NotNull @Override public ExecutionResult execute(@NotNull Executor executor, @NotNull ProgramRunner runner) throws ExecutionException { ProcessHandler processHandler = startProcess(); return new DefaultExecutionResult(null, processHandler, AnAction.EMPTY_ARRAY); } + @Override @NotNull protected OSProcessHandler startProcess() throws ExecutionException { SimpleJavaParameters params = createJavaParameters(); @@ -315,7 +328,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); - if (useMaven2) { + if (myState.useMaven2) { classpath.add(new File(root, "maven2-server-impl")); addDir(classpath, new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven2-server-impl/lib")); } @@ -335,7 +348,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme else { classpath.add(new File(root, "maven-server-api.jar")); - if (useMaven2) { + if (myState.useMaven2) { classpath.add(new File(root, "maven2-server-impl.jar")); addDir(classpath, new File(root, "maven2")); @@ -469,76 +482,89 @@ public class MavenServerManager extends RemoteObjectWrapper impleme } } + private static class UseMavenConverter extends Converter { + @Nullable + @Override + public Boolean fromString(@NotNull String value) { + return "2.x".equals(value); + } + + @NotNull + @Override + public String toString(@NotNull Boolean value) { + return value ? "2.x" : "3.x"; + } + } + public boolean isUseMaven2() { - return useMaven2; + return myState.useMaven2; } public void setUseMaven2(boolean useMaven2) { - if (this.useMaven2 != useMaven2) { - this.useMaven2 = useMaven2; + if (myState.useMaven2 != useMaven2) { + myState.useMaven2 = useMaven2; shutdown(false); } } @NotNull public String getMavenEmbedderVMOptions() { - return mavenEmbedderVMOptions; + return myState.vmOptions; } public void setMavenEmbedderVMOptions(@NotNull String mavenEmbedderVMOptions) { - if (!mavenEmbedderVMOptions.trim().equals(this.mavenEmbedderVMOptions.trim())) { - this.mavenEmbedderVMOptions = mavenEmbedderVMOptions; + if (!mavenEmbedderVMOptions.trim().equals(myState.vmOptions.trim())) { + myState.vmOptions = mavenEmbedderVMOptions; shutdown(false); } } @NotNull public String getEmbedderJdk() { - return embedderJdk; + return myState.embedderJdk; } public void setEmbedderJdk(@NotNull String embedderJdk) { - if (!this.embedderJdk.equals(embedderJdk)) { - this.embedderJdk = embedderJdk; + if (!myState.embedderJdk.equals(embedderJdk)) { + myState.embedderJdk = embedderJdk; shutdown(false); } } @Nullable @Override - public Element getState() { - final Element element = new Element("maven-version"); - element.setAttribute("version", useMaven2 ? "2.x" : "3.x"); - element.setAttribute("vmOptions", mavenEmbedderVMOptions); - element.setAttribute("embedderJdk", embedderJdk); - return element; + public State getState() { + return myState; } @Override - public void loadState(Element state) { - String version = state.getAttributeValue("version"); - useMaven2 = "2.x".equals(version); - - String vmOptions = state.getAttributeValue("vmOptions"); - mavenEmbedderVMOptions = vmOptions == null ? DEFAULT_VM_OPTIONS : vmOptions; - - String embedderJdk = state.getAttributeValue("embedderJdk"); - this.embedderJdk = embedderJdk == null ? MavenRunnerSettings.USE_INTERNAL_JAVA : embedderJdk; + public void loadState(State state) { + if (state.vmOptions == null) { + state.vmOptions = DEFAULT_VM_OPTIONS; + } + if (state.embedderJdk == null) { + state.vmOptions = MavenRunnerSettings.USE_INTERNAL_JAVA; + } + myState = state; } private static class RemoteMavenServerLogger extends MavenRemoteObject implements MavenServerLogger { + @Override public void info(Throwable e) { MavenLog.LOG.info(e); } + @Override public void warn(Throwable e) { MavenLog.LOG.warn(e); } + @Override public void error(Throwable e) { MavenLog.LOG.error(e); } + @Override public void print(String s) { //noinspection UseOfSystemOutOrSystemErr System.out.println(s); @@ -548,6 +574,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme private static class RemoteMavenServerDownloadListener extends MavenRemoteObject implements MavenServerDownloadListener { private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); + @Override public void artifactDownloaded(File file, String relativePath) throws RemoteException { for (MavenServerDownloadListener each : myListeners) { each.artifactDownloaded(file, relativePath); @@ -562,22 +589,27 @@ public class MavenServerManager extends RemoteObjectWrapper impleme myProcess = process; } + @Override public void setText(String text) { myProcess.setText(text); } + @Override public void setText2(String text) { myProcess.setText2(text); } + @Override public boolean isCanceled() { return myProcess.isCanceled(); } + @Override public void setIndeterminate(boolean value) { myProcess.getIndicator().setIndeterminate(value); } + @Override public void setFraction(double fraction) { myProcess.setFraction(fraction); } @@ -590,6 +622,7 @@ public class MavenServerManager extends RemoteObjectWrapper impleme myConsole = console; } + @Override public void printMessage(int level, String message, Throwable throwable) { myConsole.printMessage(level, message, throwable); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/MavenRepositoryServicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/MavenRepositoryServicesManager.java index e43789b85dd8..ca5296fc0b7a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/MavenRepositoryServicesManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/services/MavenRepositoryServicesManager.java @@ -69,8 +69,10 @@ public class MavenRepositoryServicesManager implements PersistentStateComponent< } public void setUrls(@NotNull List urls) { - myUrls.clear(); - myUrls.addAll(urls); + if (myUrls != urls) { + myUrls.clear(); + myUrls.addAll(urls); + } } @Override diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index 27deebbff2af..eb62cd2fb6c9 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -383,7 +383,6 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit writeEditorPropertyValue(editor, propertiesFile, null); } }); - editor.getDocument().putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE); gc.gridx = 0; gc.gridy = y++; gc.gridheight = 1; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties index 12364be04841..e6f36b2b2fb7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties @@ -201,6 +201,10 @@ dialog.edit.http.proxies.settings.test.connection.succes.title=Connection test s confirmation.text.delete.stored.authentication.information=You are about to delete all stored Subversion authentication information.\nWould you like to proceed with deletion? confirmation.title.clear.authentication.cache=Clear Authentication Cache +command.line.interactive.mode.title=Interactive mode +command.line.interactive.mode.description=Emulates behaviour as if Subversion commands were executed directly from terminal (in interactive mode).
\ + Primarily intended to be used for handling password/passphrase prompts for svn+ssh repositories and trusting invalid server certificates for https repositories. + ssh.settings.title=SSH Settings ssh.settings.executable.label=SSH executable\: ssh.settings.browse.executable.dialog.title=SSH executable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form index f1e61767844b..822ca320c43b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form @@ -18,7 +18,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -87,7 +87,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -123,12 +123,12 @@ - + - + @@ -162,7 +162,15 @@ - + + + + + + + + + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java index cadd6088eb76..f35cefb83efd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java @@ -153,7 +153,7 @@ public class AuthenticationService { public String requestSshCredentials(@NotNull final String realm, @NotNull final SimpleCredentialsDialog.Mode mode, @NotNull final String key) { - return requestCredentials(realm, ISVNAuthenticationManager.SSH, new Getter() { + return requestCredentials(realm, StringUtil.toLowerCase(mode.toString()), new Getter() { @Override public String get() { final Ref answer = new Ref(); @@ -184,7 +184,7 @@ public class AuthenticationService { @NotNull public AcceptResult acceptCertificate(@NotNull final SVNURL url, @NotNull final String certificateInfo) { // TODO: Probably explicitly construct server url for realm here - like in CertificateTrustManager. - String kind = "svn.ssl.server"; + String kind = "terminal.ssl.server"; String realm = url.toDecodedString(); Object data = SvnConfiguration.RUNTIME_AUTH_CACHE.getDataWithLowerCheck(kind, realm); AcceptResult result; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CertificateTrustManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CertificateTrustManager.java index c5bd5a54182b..07aed1461c91 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CertificateTrustManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CertificateTrustManager.java @@ -113,7 +113,7 @@ public class CertificateTrustManager extends ClientOnlyTrustManager { } private void acknowledge(@NotNull X509Certificate certificate) throws CertificateEncodingException { - myAuthenticationService.getVcs().getSvnConfiguration().acknowledge("svn.ssl.server", myRealm, certificate); + myAuthenticationService.getVcs().getSvnConfiguration().acknowledge("cmd.ssl.server", myRealm, certificate); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseTerminalModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseTerminalModule.java index d4b9475ee5d5..95a0e7474f78 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseTerminalModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseTerminalModule.java @@ -80,6 +80,6 @@ public abstract class BaseTerminalModule extends LineCommandAdapter implements C } protected void cancelAuthentication() { - myExecutor.destroyProcess("Authentication canceled for repository: " + myExecutor.getCommand().getRepositoryUrl()); + myExecutor.destroyProcess("Authentication canceled for repository: " + myExecutor.getCommand().requireRepositoryUrl()); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java index 50215fba76c8..a20e2db48495 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java @@ -79,6 +79,14 @@ public class Command { return myRepositoryUrl; } + @NotNull + public SVNURL requireRepositoryUrl() { + SVNURL result = getRepositoryUrl(); + assert result != null; + + return result; + } + @NotNull public SvnTarget getTarget() { return myTarget; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java index caeb1c26cc67..46b716c3bde2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java @@ -126,7 +126,7 @@ public class CommandRuntime { private boolean handleErrorText(CommandExecutor executor, Command command) throws SvnBindException { final String errText = executor.getErrorOutput().trim(); - final AuthCallbackCase callback = executor instanceof TerminalExecutor ? null : createCallback(errText, command.getRepositoryUrl()); + final AuthCallbackCase callback = createCallback(errText, command.getRepositoryUrl(), executor instanceof TerminalExecutor); // do not handle possible authentication errors if command was manually cancelled // force checking if command is cancelled and not just use corresponding value from executor - as there could be cases when command // finishes quickly but with some auth error - this way checkCancelled() is not called by executor itself and so command is repeated @@ -166,13 +166,25 @@ public class CommandRuntime { } @Nullable - private AuthCallbackCase createCallback(@NotNull final String errText, @Nullable final SVNURL url) { + private AuthCallbackCase createCallback(@NotNull final String errText, @Nullable final SVNURL url, boolean isUnderTerminal) { List authCases = ContainerUtil.newArrayList(); - authCases.add(new CertificateCallbackCase(myAuthenticationService, url)); - authCases.add(new ProxyCallback(myAuthenticationService, url)); - authCases.add(new TwoWaySslCallback(myAuthenticationService, url)); - authCases.add(new UsernamePasswordCallback(myAuthenticationService, url)); + if (isUnderTerminal) { + // Subversion client does not prompt for proxy credentials (just fails with error) even in terminal mode. So we handle this case the + // same way as in non-terminal mode - repeat command with new credentials. + // NOTE: We could also try getting proxy credentials from user in advance (by issuing separate request and asking for credentials if + // NOTE: required) - not to execute same command several times like it is currently for all other cases in terminal mode. But such + // NOTE: behaviour is not mandatory for now - so we just use "repeat command" logic. + authCases.add(new ProxyCallback(myAuthenticationService, url)); + // Same situation (described above) as with proxy settings is here. + authCases.add(new TwoWaySslCallback(myAuthenticationService, url)); + } + else { + authCases.add(new CertificateCallbackCase(myAuthenticationService, url)); + authCases.add(new ProxyCallback(myAuthenticationService, url)); + authCases.add(new TwoWaySslCallback(myAuthenticationService, url)); + authCases.add(new UsernamePasswordCallback(myAuthenticationService, url)); + } return ContainerUtil.find(authCases, new Condition() { @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java index bdfdd55ed6e1..b9e83e7bf850 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -15,7 +15,6 @@ */ package org.jetbrains.idea.svn.commandLine; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; @@ -31,38 +30,29 @@ import java.net.Proxy; */ public class ProxyModule extends BaseCommandRuntimeModule { - private static final Logger LOG = Logger.getInstance(ProxyModule.class); - public ProxyModule(@NotNull CommandRuntime runtime) { super(runtime); } @Override public void onStart(@NotNull Command command) throws SvnBindException { - if (myAuthenticationService.haveDataForTmpConfig()) { + if (myAuthenticationService.haveDataForTmpConfig() && !CommandRuntime.isLocal(command)) { setupProxy(command); } } private void setupProxy(@NotNull Command command) { - // TODO: We assume that if repository url is null - command is local and do not require repository access - // TODO: Check if this is correct for all cases - SVNURL repositoryUrl = command.getRepositoryUrl(); + SVNURL repositoryUrl = command.requireRepositoryUrl(); + Proxy proxy = AuthenticationService.getIdeaDefinedProxy(repositoryUrl); - if (repositoryUrl != null) { - Proxy proxy = AuthenticationService.getIdeaDefinedProxy(repositoryUrl); + if (proxy != null) { + String hostGroup = ensureGroupForHost(command, repositoryUrl.getHost()); + InetSocketAddress address = (InetSocketAddress)proxy.address(); - if (proxy != null) { - String hostGroup = ensureGroupForHost(command, repositoryUrl.getHost()); - InetSocketAddress address = (InetSocketAddress)proxy.address(); - - command.put("--config-option"); - command.put(String.format("servers:%s:http-proxy-host=%s", hostGroup, address.getHostName())); - command.put("--config-option"); - command.put(String.format("servers:%s:http-proxy-port=%s", hostGroup, address.getPort())); - } - } else { - LOG.info("Configured proxy should be used, but repository url is null for command - " + command.getText()); + command.put("--config-option"); + command.put(String.format("servers:%s:http-proxy-host=%s", hostGroup, address.getHostName())); + command.put("--config-option"); + command.put(String.format("servers:%s:http-proxy-port=%s", hostGroup, address.getPort())); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java index 1ebd86485033..740954cf31ca 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java @@ -112,13 +112,8 @@ public class TerminalSshModule extends BaseTerminalModule { } private boolean handleAuthPrompt(@NotNull final SimpleCredentialsDialog.Mode mode, @NotNull final String key) { - final SVNURL repositoryUrl = myExecutor.getCommand().getRepositoryUrl(); - - // TODO: repositoryUrl could be null for some cases, for instance for info command for file is invoked that requires - // TODO: authentication (like "svn info -r HEAD"), if it is invoked before all working copy roots are resolved. - // TODO: resolving repositoryUrl logic should be updated so that repositoryUrl is not null here. - String auth = - myRuntime.getAuthenticationService().requestSshCredentials(repositoryUrl != null ? repositoryUrl.toDecodedString() : "", mode, key); + SVNURL repositoryUrl = myExecutor.getCommand().requireRepositoryUrl(); + String auth = myRuntime.getAuthenticationService().requestSshCredentials(repositoryUrl.toDecodedString(), mode, key); if (!StringUtil.isEmpty(auth)) { sendData(auth); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalUserNamePasswordModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalUserNamePasswordModule.java index dbb1d211a8b4..489222ab8190 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalUserNamePasswordModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalUserNamePasswordModule.java @@ -79,8 +79,7 @@ public class TerminalUserNamePasswordModule extends BaseTerminalModule { * (before any user name prompt) for pre-configured/system user name. */ private boolean handleAuthPrompt(boolean isUserName) { - // TODO: check command is not local and get @NotNull url - also make same for for ssh module - SVNURL repositoryUrl = myExecutor.getCommand().getRepositoryUrl(); + SVNURL repositoryUrl = myExecutor.getCommand().requireRepositoryUrl(); if (needAskAuthentication(isUserName)) { // TODO: Probably pass real realm to dialog diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java index 34776f3fabd2..08f531077356 100644 --- a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java +++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java @@ -1,7 +1,7 @@ package com.jetbrains.python.edu; import com.intellij.codeInsight.CodeInsightSettings; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.ui.UISettings; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.PathManager; @@ -33,7 +33,7 @@ public class StudyInitialConfigurator { final PropertiesComponent propertiesComponent, FileTypeManager fileTypeManager, final ProjectManagerEx projectManager, - RecentProjectsManagerBase recentProjectsManager) { + RecentProjectsManager recentProjectsManager) { if (!propertiesComponent.getBoolean(CONFIGURED, false)) { final File file = new File(getCoursesRoot(), "introduction_course.zip"); final File newCourses = new File(PathManager.getConfigPath(), "courses"); diff --git a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java index 976d99c56da8..0f13419dadce 100644 --- a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java +++ b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java @@ -21,7 +21,7 @@ import com.intellij.codeInsight.intention.IntentionActionBean; import com.intellij.codeInsight.intention.IntentionManager; import com.intellij.ide.AppLifecycleListener; import com.intellij.ide.GeneralSettings; -import com.intellij.ide.RecentProjectsManagerBase; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.SelectInTarget; import com.intellij.ide.ui.UISettings; import com.intellij.ide.util.PropertiesComponent; @@ -86,7 +86,7 @@ public class PyCharmEduInitialConfigurator { final PropertiesComponent propertiesComponent, FileTypeManager fileTypeManager, final ProjectManagerEx projectManager, - RecentProjectsManagerBase recentProjectsManager) { + RecentProjectsManager recentProjectsManager) { if (!propertiesComponent.getBoolean(CONFIGURED, false)) { propertiesComponent.setValue(CONFIGURED, "true"); propertiesComponent.setValue("toolwindow.stripes.buttons.info.shown", "true"); diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java index 10f04181a118..a171aacb0249 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java @@ -15,7 +15,7 @@ */ package com.jetbrains.python.newProject.actions; -import com.intellij.ide.GeneralSettings; +import com.intellij.ide.RecentProjectsManager; import com.intellij.ide.util.projectWizard.WebProjectTemplate; import com.intellij.internal.statistic.UsageTrigger; import com.intellij.internal.statistic.beans.ConvertUsagesUtil; @@ -133,7 +133,7 @@ public class GenerateProjectCallback implements NullableConsumer