From 3303505018cdc48ccf3d93ea4ea9dc1e266c9131 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 15 Dec 2011 21:53:26 +0400 Subject: [PATCH 01/11] IDEA-78696 Filter in Add Actions to Quick List dialog --- .../src/com/intellij/ide/actions/StartUseVcsAction.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/ide/actions/StartUseVcsAction.java b/platform/vcs-impl/src/com/intellij/ide/actions/StartUseVcsAction.java index 80fb5a727de4..4dfba431591f 100644 --- a/platform/vcs-impl/src/com/intellij/ide/actions/StartUseVcsAction.java +++ b/platform/vcs-impl/src/com/intellij/ide/actions/StartUseVcsAction.java @@ -27,6 +27,10 @@ import com.intellij.openapi.vcs.VcsDirectoryMapping; import java.util.Arrays; public class StartUseVcsAction extends AnAction implements DumbAware { + public StartUseVcsAction() { + super(VcsBundle.message("action.enable.version.control.integration.text")); + } + @Override public void update(final AnActionEvent e) { final VcsDataWrapper data = new VcsDataWrapper(e); From 734ccedf02ce9a4dbd906c87de454f947a47c7df Mon Sep 17 00:00:00 2001 From: irengrig Date: Fri, 16 Dec 2011 17:22:17 +0400 Subject: [PATCH 02/11] P4 - working tests but not offline test --- .../vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java index 9a94a5cc02f2..49b5abdd9115 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java @@ -415,12 +415,16 @@ public abstract class VcsVFSListener implements Disposable { checkMovedAddedSourceBack(); if (!myAddedFiles.isEmpty()) { executeAdd(); + myAddedFiles.clear(); } if (!myDeletedFiles.isEmpty() || !myDeletedWithoutConfirmFiles.isEmpty()) { executeDelete(); + myDeletedFiles.clear(); + myDeletedWithoutConfirmFiles.clear(); } if (!myMovedFiles.isEmpty()) { executeMoveRename(); + myMovedFiles.clear(); } if (! myDirtyFiles.isEmpty()) { final List files = new ArrayList(); From 84de0a9d2517c266b9eba7997e6d1f34564e1794 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 19 Dec 2011 14:14:41 +0300 Subject: [PATCH 03/11] IDEA-78781 Fix hg for the case when there are spaces in the path to repository or in relative paths inside the repository. Escape paths for the case when hg is called via bash. For the standard call it is not needed. --- .../org/zmlx/hg4idea/execution/ShellCommand.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java index 73603cc7d3ca..b47fa966d08c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java @@ -15,7 +15,7 @@ package org.zmlx.hg4idea.execution; import com.intellij.execution.process.CapturingProcessHandler; import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; @@ -44,8 +44,12 @@ public final class ShellCommand { if (myRunViaBash) { // run via bash -cl => need to escape bash special symbols // '-l' makes bash execute as a login shell thus reading .bash_profile - String hgCommand = StringUtil.join(commandLine, " "); - hgCommand = escapeBashControlCharacters(hgCommand); + StringBuilder hgCommandBuilder = new StringBuilder(); + for (String command : commandLine) { + hgCommandBuilder.append(escapeSpacesIfNeeded(command)); + hgCommandBuilder.append(" "); + } + String hgCommand = escapeBashControlCharacters(hgCommandBuilder.toString()); commandLine = new ArrayList(3); commandLine.add("bash"); commandLine.add("-cl"); @@ -100,4 +104,9 @@ public final class ShellCommand { return sb.toString(); } + @NotNull + private String escapeSpacesIfNeeded(@NotNull String s) { + return myRunViaBash ? s.replace(" ", "\\ ") : s; + } + } From 5dafa4d52eedda5a1f45af8fd5b960f92428c2fe Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 19 Dec 2011 16:22:15 +0400 Subject: [PATCH 04/11] optimize imports for template languages (JSP, JSPX, Facelets) --- .../lang/LanguageImportStatements.java | 20 ++++++++++++++----- .../actions/OptimizeImportsAction.java | 2 +- .../XmlUnusedNamespaceInspection.java | 16 +++++++++------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/platform/lang-api/src/com/intellij/lang/LanguageImportStatements.java b/platform/lang-api/src/com/intellij/lang/LanguageImportStatements.java index 5fe4acefa9ce..cf7ae42ea17a 100644 --- a/platform/lang-api/src/com/intellij/lang/LanguageImportStatements.java +++ b/platform/lang-api/src/com/intellij/lang/LanguageImportStatements.java @@ -20,7 +20,11 @@ package com.intellij.lang; import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class LanguageImportStatements extends LanguageExtension { public static final LanguageImportStatements INSTANCE = new LanguageImportStatements(); @@ -29,9 +33,15 @@ public class LanguageImportStatements extends LanguageExtension super("com.intellij.lang.importOptimizer"); } - @Nullable - public ImportOptimizer forFile(PsiFile file) { - ImportOptimizer optimizer = forLanguage(file.getLanguage()); - return optimizer != null && optimizer.supports(file) ? optimizer : null; + public List forFile(PsiFile file) { + List runnables = new ArrayList(); + Set optimizers = new HashSet(); + for (PsiFile psiFile : file.getViewProvider().getAllFiles()) { + ImportOptimizer optimizer = forLanguage(psiFile.getLanguage()); + if (optimizer != null && optimizer.supports(psiFile) && optimizers.add(optimizer)) { + runnables.add(optimizer.processFile(psiFile)); + } + } + return runnables; } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index 951dbecd7c3c..416e2e4bc09b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -193,6 +193,6 @@ public class OptimizeImportsAction extends AnAction { } private static boolean isOptimizeImportsAvailable(final PsiFile file) { - return LanguageImportStatements.INSTANCE.forFile(file) != null; + return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty(); } } diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java index e1acc34b9356..009a89b175cd 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnusedNamespaceInspection.java @@ -73,21 +73,21 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool XmlAttributeValue value = attribute.getValueElement(); assert value != null; holder.registerProblem(attribute, "Namespace declaration is never used", ProblemHighlightType.LIKE_UNUSED_SYMBOL, - new RemoveNamespaceDeclarationFix(declaredPrefix)); + new RemoveNamespaceDeclarationFix(declaredPrefix, false)); XmlTag parent = attribute.getParent(); if (declaredPrefix.length() == 0) { XmlAttribute location = getDefaultLocation(parent); if (location != null) { holder.registerProblem(location, NAMESPACE_LOCATION_IS_NEVER_USED, ProblemHighlightType.LIKE_UNUSED_SYMBOL, - new RemoveNamespaceDeclarationFix(declaredPrefix)); + new RemoveNamespaceDeclarationFix(declaredPrefix, true)); } } else { for (PsiReference reference : getLocationReferences(namespace, parent)) { if (!XmlHighlightVisitor.hasBadResolve(reference, false)) holder.registerProblemForReference(reference, ProblemHighlightType.LIKE_UNUSED_SYMBOL, NAMESPACE_LOCATION_IS_NEVER_USED, - new RemoveNamespaceDeclarationFix(declaredPrefix)); + new RemoveNamespaceDeclarationFix(declaredPrefix, true)); } } } @@ -234,9 +234,11 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool public static final String NAME = "Remove unused namespace declaration"; protected final String myPrefix; + private final boolean myLocationFix; - private RemoveNamespaceDeclarationFix(@Nullable String prefix) { + private RemoveNamespaceDeclarationFix(@Nullable String prefix, boolean locationFix) { myPrefix = prefix; + myLocationFix = locationFix; } @NotNull @@ -328,7 +330,9 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool @Override public boolean equals(Object obj) { - return obj instanceof RemoveNamespaceDeclarationFix && Comparing.equal(myPrefix, ((RemoveNamespaceDeclarationFix)obj).myPrefix); + return obj instanceof RemoveNamespaceDeclarationFix && + Comparing.equal(myPrefix, ((RemoveNamespaceDeclarationFix)obj).myPrefix) && + (myLocationFix || ((RemoveNamespaceDeclarationFix)obj).myLocationFix); } @Override @@ -342,7 +346,7 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool public static final String NAME = "Remove unused namespace location"; private RemoveNamespaceLocationFix(String namespace) { - super(namespace); + super(namespace, true); } @NotNull From 5339ae5a1397f016e06bf0d9290781c5dcc43432 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Mon, 19 Dec 2011 16:26:31 +0400 Subject: [PATCH 05/11] EA-32634 - assert: AbstractMappingStrategy.processFoldRegion Debug info is added --- .../com/intellij/diagnostic/LogMessageEx.java | 6 +-- .../mapping/SoftWrapApplianceManager.java | 43 +++++++++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java index f299f783b408..41d17cba65b9 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java @@ -130,12 +130,12 @@ public class LogMessageEx extends LogMessage { }; } - public static void error(@NotNull Logger logger, @NotNull String message, @NotNull String... details) { + public static void error(@NotNull Logger logger, @NotNull String message, @NotNull String... attachmentText) { StringBuilder detailsBuffer = new StringBuilder(); - for (String detail : details) { + for (String detail : attachmentText) { detailsBuffer.append(detail).append(","); } - if (details.length > 0 && detailsBuffer.length() > 0) { + if (attachmentText.length > 0 && detailsBuffer.length() > 0) { detailsBuffer.setLength(detailsBuffer.length() - 1); } Attachment attachment = detailsBuffer.length() > 0 ? new Attachment("current-context.txt", detailsBuffer.toString()) : null; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index b9d800cbafb8..cb7e9f51571f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -15,7 +15,9 @@ */ package com.intellij.openapi.editor.impl.softwrap.mapping; +import com.intellij.diagnostic.LogMessageEx; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; @@ -24,10 +26,7 @@ import com.intellij.openapi.editor.event.VisibleAreaListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.ScrollingModelEx; import com.intellij.openapi.editor.ex.util.EditorUtil; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; -import com.intellij.openapi.editor.impl.FontInfo; -import com.intellij.openapi.editor.impl.IterationState; -import com.intellij.openapi.editor.impl.TextChangeImpl; +import com.intellij.openapi.editor.impl.*; import com.intellij.openapi.editor.impl.softwrap.*; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.text.StringUtil; @@ -54,7 +53,9 @@ import java.util.List; * @since Jul 5, 2010 10:01:27 AM */ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, DocumentListener { - + + private static final Logger LOG = Logger.getInstance("#" + SoftWrapApplianceManager.class.getName()); + /** Enumerates possible type of soft wrap indents to use. */ enum IndentType { /** Don't apply special indent to soft-wrapped line at all. */ @@ -90,14 +91,15 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume */ private int myLastTopLeftCornerOffset = -1; - private VisibleAreaWidthProvider myWidthProvider; - private LineWrapPositionStrategy myLineWrapPositionStrategy; - private boolean myVisualAreaListenerAttached; - private boolean myCustomIndentUsedLastTime; - private int myCustomIndentValueUsedLastTime; - private int myVisibleAreaWidth; - private boolean myInProgress; - private boolean myHasLinesWithFailedWrap; + private VisibleAreaWidthProvider myWidthProvider; + private LineWrapPositionStrategy myLineWrapPositionStrategy; + private IncrementalCacheUpdateEvent myEventBeingProcessed; + private boolean myVisualAreaListenerAttached; + private boolean myCustomIndentUsedLastTime; + private int myCustomIndentValueUsedLastTime; + private int myVisibleAreaWidth; + private boolean myInProgress; + private boolean myHasLinesWithFailedWrap; public SoftWrapApplianceManager(@NotNull SoftWrapsStorage storage, @NotNull EditorEx editor, @@ -172,16 +174,28 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume List events = new ArrayList(myEventsStorage.getEvents()); myActiveEvents.addAll(events); myEventsStorage.release(); + if (myInProgress && !events.isEmpty()) { + String state = ""; + if (myEditor instanceof EditorImpl) { + state = ((EditorImpl)myEditor).dumpState(); + } + LogMessageEx.error(LOG, "Detected race condition at soft wraps recalculation", String.format( + "Current events: %s. Concurrent events: %s, event being processed: %s%n%s", + events, myActiveEvents, myEventBeingProcessed, state + )); + } myInProgress = true; myHasLinesWithFailedWrap = false; try { for (IncrementalCacheUpdateEvent event : events) { + myEventBeingProcessed = event; recalculateSoftWraps(event); } } finally { myInProgress = false; myActiveEvents.clear(); + myEventBeingProcessed = null; } updateLastTopLeftCornerOffset(); return true; @@ -896,7 +910,8 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume @Override public String toString() { return String.format( - "recalculation in progress: %b; stored update events: %s; active update events: %s", myInProgress, myEventsStorage, myActiveEvents + "recalculation in progress: %b; stored update events: %s; active update events: %s, event being processed: %s", + myInProgress, myEventsStorage, myActiveEvents, myEventBeingProcessed ); } From 6dca2d11de4715120623a66362a0bd0c195ca030 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 19 Dec 2011 16:30:11 +0400 Subject: [PATCH 06/11] optimize imports for template languages (JSP, JSPX, Facelets) --- .../codeInsight/actions/LayoutCodeDialog.java | 2 +- .../actions/OptimizeImportsProcessor.java | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index cfbc5907b75d..4e1f6f7deccb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -103,7 +103,7 @@ public class LayoutCodeDialog extends DialogWrapper { myCbIncludeSubdirs.setEnabled(myRbDirectory.isSelected()); myCbOptimizeImports.setEnabled( !myRbSelectedText.isSelected() && - !(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile) == null && myRbFile.isSelected())); + !(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty() && myRbFile.isSelected())); final boolean canTargetVcsChanges = canTargetVcsRegions(); myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsChanges); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index d16b9dcf3b46..f6ce2f44134e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -17,7 +17,6 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.lang.ImportOptimizer; import com.intellij.lang.LanguageImportStatements; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -27,6 +26,7 @@ import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.concurrent.FutureTask; public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { @@ -58,11 +58,16 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } @NotNull - protected FutureTask preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly) - throws IncorrectOperationException - { - final ImportOptimizer optimizer = LanguageImportStatements.INSTANCE.forFile(file); - Runnable runnable = optimizer != null ? optimizer.processFile(file) : EmptyRunnable.getInstance(); + protected FutureTask preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException { + final List optimizers = LanguageImportStatements.INSTANCE.forFile(file); + Runnable runnable = optimizers.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() { + @Override + public void run() { + for (Runnable optimizer : optimizers) { + optimizer.run(); + } + } + }; return new FutureTask(runnable, true); } } From 78647aba0975780a527048f57a19fa7bd09f6f6d Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 19 Dec 2011 17:06:19 +0400 Subject: [PATCH 07/11] use toolwindow title tabs instead of tabbed component inside structure view --- .../ide/impl/StructureViewWrapperImpl.java | 87 ++++++++++++------- .../impl/StructureViewComposite.java | 18 +--- .../impl/StructureViewFactoryImpl.java | 9 +- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java index fd367547323d..911ec07db1db 100644 --- a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java @@ -22,6 +22,7 @@ import com.intellij.ide.projectView.impl.ProjectRootsUtil; import com.intellij.ide.structureView.StructureView; import com.intellij.ide.structureView.StructureViewBuilder; import com.intellij.ide.structureView.StructureViewWrapper; +import com.intellij.ide.structureView.impl.StructureViewComposite; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ModalityState; @@ -43,6 +44,9 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; import com.intellij.psi.PsiDocumentManager; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; +import com.intellij.ui.content.ContentManager; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; @@ -59,13 +63,14 @@ import java.awt.event.HierarchyListener; */ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposable { private final Project myProject; + private final ToolWindow myToolWindow; private VirtualFile myFile; private StructureView myStructureView; private ModuleStructureComponent myModuleStructureComponent; - private final JPanel myPanel; + private JPanel[] myPanels = new JPanel[0]; private final MergingUpdateQueue myUpdateQueue; private final String myKey = new String("DATA_SELECTOR"); @@ -75,17 +80,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl private Runnable myPendingSelection; - public StructureViewWrapperImpl(Project project) { + public StructureViewWrapperImpl(Project project, ToolWindow toolWindow) { myProject = project; - myPanel = new ContentPanel(); - myPanel.setBackground(UIUtil.getTreeTextBackground()); - - myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myPanel, this, myPanel, true); + myToolWindow = toolWindow; + + myUpdateQueue = new MergingUpdateQueue("StructureView", Registry.intValue("structureView.coalesceTime"), false, myToolWindow.getComponent(), this, myToolWindow.getComponent(), true); myUpdateQueue.setRestartTimerOnAdd(true); ActionManager.getInstance().addTimerListener(500, new TimerListener() { public ModalityState getModalityState() { - return ModalityState.stateForComponent(myPanel); + return ModalityState.stateForComponent(myToolWindow.getComponent()); } public void run() { @@ -93,20 +97,21 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl } }); - getComponent().addHierarchyListener(new HierarchyListener() { + myToolWindow.getComponent().addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) { scheduleRebuild(); } } }); + Disposer.register(myToolWindow.getContentManager(), this); } private void checkUpdate() { if (myProject.isDisposed()) return; final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (SwingUtilities.isDescendingFrom(myPanel, owner) || JBPopupFactory.getInstance().isPopupActive()) return; + if (SwingUtilities.isDescendingFrom(myToolWindow.getComponent(), owner) || JBPopupFactory.getInstance().isPopupActive()) return; final DataContext dataContext = DataManager.getInstance().getDataContext(owner); if (dataContext.getData(myKey) == this) return; @@ -133,10 +138,6 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl // StructureView interface implementation // ------------------------------------------------------------------------- - public JComponent getComponent() { - return myPanel; - } - public void dispose() { rebuild(); } @@ -202,8 +203,8 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl myModuleStructureComponent = null; } - myPanel.removeAll(); - + final ContentManager contentManager = myToolWindow.getContentManager(); + contentManager.removeAllContents(true); if (!isStructureViewShowing()) { return; } @@ -216,19 +217,16 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl } } + String[] names = new String[] {""}; + JComponent focusedComponent = null; if (file != null && file.isValid()) { if (file.isDirectory()) { if (ProjectRootsUtil.isModuleContentRoot(file, myProject)) { Module module = ModuleUtil.findModuleForFile(file, myProject); if (module != null) { myModuleStructureComponent = new ModuleStructureComponent(module); - myPanel.add(myModuleStructureComponent, BorderLayout.CENTER); - if (hadFocus) { - JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent); - if (focusedComponent != null) { - IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true); - } - } + focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent) : null; + createSinglePanel(myModuleStructureComponent.getComponent()); } } } @@ -246,13 +244,22 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl if (myStructureView instanceof StructureView.Scrollable) { ((StructureView.Scrollable)myStructureView).setReferenceSizeWhileInitializing(referenceSize); } - myPanel.add(myStructureView.getComponent(), BorderLayout.CENTER); - if (hadFocus) { - JComponent focusedComponent = IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent()); - if (focusedComponent != null) { - IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true); + + final StructureViewComposite.StructureViewDescriptor[] views; + + if (myStructureView instanceof StructureViewComposite) { + final StructureViewComposite composite = (StructureViewComposite)myStructureView; + views = composite.getStructureViews(); + myPanels = new JPanel[views.length]; + names = new String[views.length]; + for (int i = 0; i < myPanels.length; i++) { + myPanels[i] = createContentPanel(views[i].structureView.getComponent()); + names[i] = views[i].title; } + } else { + createSinglePanel(myStructureView.getComponent()); } + focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myStructureView.getComponent()) : null; myStructureView.restoreState(); myStructureView.centerSelectedRow(); } @@ -264,11 +271,19 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl } if (myModuleStructureComponent == null && myStructureView == null) { - myPanel.add(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER), BorderLayout.CENTER); + createSinglePanel(new JLabel(IdeBundle.message("message.nothing.to.show.in.structure.view"), SwingConstants.CENTER)); } - myPanel.validate(); - myPanel.repaint(); + for (int i = 0; i < myPanels.length; i++) { + final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanels[i], names[i], false); + contentManager.addContent(content); + if (i == 0 && myStructureView != null) { + Disposer.register(content, myStructureView); + } + } + if (hadFocus && focusedComponent != null) { + IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true); + } if (myPendingSelection != null) { Runnable selection = myPendingSelection; @@ -277,6 +292,18 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl } } + private void createSinglePanel(final JComponent component) { + myPanels = new JPanel[1]; + myPanels[0] = createContentPanel(component); + } + + private ContentPanel createContentPanel(JComponent component) { + final ContentPanel panel = new ContentPanel(); + panel.setBackground(UIUtil.getTreeTextBackground()); + panel.add(component, BorderLayout.CENTER); + return panel; + } + @Nullable private FileEditor createTempFileEditor(VirtualFile file) { FileEditorProviderManager editorProviderManager = FileEditorProviderManager.getInstance(); diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java index 2928ac34fcce..dcf277dac1ca 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java @@ -20,12 +20,9 @@ import com.intellij.ide.structureView.StructureView; import com.intellij.ide.structureView.StructureViewModel; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.util.Disposer; -import com.intellij.ui.TabbedPaneWrapper; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; /** * @author cdr @@ -33,8 +30,6 @@ import javax.swing.event.ChangeListener; public class StructureViewComposite implements StructureView { @NotNull private final StructureViewDescriptor[] myStructureViews; @NotNull private StructureViewDescriptor mySelectedViewDescriptor; - @NotNull private final TabbedPaneWrapper myTabbedPaneWrapper; - public static class StructureViewDescriptor { public final String title; public final StructureView structureView; @@ -53,17 +48,6 @@ public class StructureViewComposite implements StructureView { Disposer.register(this, descriptor.structureView); } mySelectedViewDescriptor = views[0]; - myTabbedPaneWrapper = new TabbedPaneWrapper(this); - for (StructureViewDescriptor descriptor : views) { - myTabbedPaneWrapper.addTab(descriptor.title, descriptor.icon, descriptor.structureView.getComponent(), null); - } - myTabbedPaneWrapper.setSelectedIndex(0); - myTabbedPaneWrapper.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - int index = myTabbedPaneWrapper.getSelectedIndex(); - mySelectedViewDescriptor = myStructureViews[index]; - } - }); } public StructureView getSelectedStructureView() { @@ -84,7 +68,7 @@ public class StructureViewComposite implements StructureView { } public JComponent getComponent() { - return myTabbedPaneWrapper.getComponent(); + return mySelectedViewDescriptor.structureView.getComponent(); } public void dispose() { diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java index 18f50d1dca1c..4cd736adca3d 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java @@ -25,14 +25,11 @@ import com.intellij.openapi.components.Storage; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; import com.intellij.psi.PsiElement; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; import com.intellij.util.ReflectionCache; import org.jetbrains.annotations.NotNull; @@ -96,11 +93,7 @@ public final class StructureViewFactoryImpl extends StructureViewFactoryEx imple } public void initToolWindow(ToolWindow toolWindow) { - myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject); - final Content content = ContentFactory.SERVICE.getInstance().createContent(myStructureViewWrapperImpl.getComponent(), "", false); - Disposer.register(content, myStructureViewWrapperImpl); - toolWindow.getContentManager().addContent(content); - + myStructureViewWrapperImpl = new StructureViewWrapperImpl(myProject, toolWindow); if (myRunWhenInitialized != null) { myRunWhenInitialized.run(); myRunWhenInitialized = null; From 35162f1f3ed19a4d8a20bf1ca214ae3117032d71 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 19 Dec 2011 17:11:04 +0400 Subject: [PATCH 08/11] remove view from structure view tabs --- .../platform-resources-en/src/messages/IdeBundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index e58fb3eac2e1..0f0ffb142a7a 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -565,8 +565,8 @@ action.structureview.show.non.public=Show non-public node.structureview.invalid= action.structureview.group.methods.by.defining.type=Group Methods by Defining Type action.structureview.sort.by.visibility=Sort by Visibility -tab.structureview.jsp.view=JSP View -tab.structureview.baselanguage.view={0} View +tab.structureview.jsp.view=JSP +tab.structureview.baselanguage.view={0} action.next.todo=Next TODO action.previous.todo=Previous TODO action.filter.todo.items=Filter TODO Items From d2a69e08474fb2f2fec8c25d696002f020ed26b0 Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 19 Dec 2011 17:30:29 +0400 Subject: [PATCH 09/11] IDEA-79080 Deadlock after unstash --- .../openapi/vcs/changes/ChangeListManagerImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index 1484e4837743..88603bc6330e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -391,14 +391,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec myUpdateException = null; myAdditionalInfo.clear(); } - debugLogging("refresh procedure started, everything = " + wasEverythingDirty + " dirty scope: " + - StringUtil.join(scopes, new Function() { - @Override - public String fun(VcsDirtyScope scope) { - return scope.toString(); - } - }, "->\n")); } + final String scopeInString = (! LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function() { + @Override + public String fun(VcsDirtyScope scope) { + return scope.toString(); + } + }, "->\n"); + debugLogging("refresh procedure started, everything = " + wasEverythingDirty + " dirty scope: " + scopeInString); dataHolder.notifyStart(); myChangesViewManager.scheduleRefresh(); From c23d0e8b7ba48f527de28f867f9a64d9783d6957 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 19 Dec 2011 17:27:51 +0300 Subject: [PATCH 10/11] IDEA-77900 Use native Git for http if login and password information are specified in .netrc for the host. 1. NetrcData to parse and hold information defined in .netrc 2. GitHttpAdapter: don't call JGit if auth info is defined in .netrc for the host. 3. Tests for various NetrcData. 4. Moved GitTestUtil to git4idea.test (container for the local test framework). Known problem: if auth info for the host is defined in .netrc, but is incorrect (e.g. the password is invalid), JGit won't be called, and native Git would ask for the username/password in the command line, which would result in a well-known hang. --- .../src/git4idea/jgit/GitHttpAdapter.java | 22 +- .../git4idea/src/git4idea/util/NetrcData.java | 188 ++++++++++++++++++ .../testData/netrc/n0_no/n0_config.txt | 0 .../git4idea/testData/netrc/n0_no/n0_desc.txt | 1 + .../testData/netrc/n0_no/n0_result.txt | 0 .../netrc/n1_just_login/n1_config.txt | 2 + .../testData/netrc/n1_just_login/n1_desc.txt | 1 + .../netrc/n1_just_login/n1_result.txt | 1 + .../testData/netrc/n2_standard/n2_config.txt | 3 + .../testData/netrc/n2_standard/n2_desc.txt | 1 + .../testData/netrc/n2_standard/n2_result.txt | 1 + .../netrc/n3_two_standard/n3_config.txt | 6 + .../netrc/n3_two_standard/n3_desc.txt | 1 + .../netrc/n3_two_standard/n3_result.txt | 2 + .../n4_two_records_for_1_host/n4_config.txt | 4 + .../n4_two_records_for_1_host/n4_desc.txt | 2 + .../n4_two_records_for_1_host/n4_result.txt | 1 + .../netrc/n5_overriding_record/n5_config.txt | 5 + .../netrc/n5_overriding_record/n5_desc.txt | 1 + .../netrc/n5_overriding_record/n5_result.txt | 1 + .../netrc/n6_poor_format/n6_config.txt | 4 + .../testData/netrc/n6_poor_format/n6_desc.txt | 1 + .../netrc/n6_poor_format/n6_result.txt | 1 + .../tests/git4idea/repo/GitConfigTest.java | 51 +---- .../repo/GitRepositoryReaderTest.java | 2 +- .../git4idea/{tests => test}/GitTestUtil.java | 50 ++++- .../tests/git4idea/tests/GitBranchTest.java | 1 + .../git4idea/tests/GitChangeProviderTest.java | 1 + .../tests/git4idea/tests/GitMergeTest.java | 1 + .../tests/git4idea/util/NetrcDataTest.java | 72 +++++++ 30 files changed, 380 insertions(+), 47 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/util/NetrcData.java create mode 100644 plugins/git4idea/testData/netrc/n0_no/n0_config.txt create mode 100644 plugins/git4idea/testData/netrc/n0_no/n0_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n0_no/n0_result.txt create mode 100644 plugins/git4idea/testData/netrc/n1_just_login/n1_config.txt create mode 100644 plugins/git4idea/testData/netrc/n1_just_login/n1_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n1_just_login/n1_result.txt create mode 100644 plugins/git4idea/testData/netrc/n2_standard/n2_config.txt create mode 100644 plugins/git4idea/testData/netrc/n2_standard/n2_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n2_standard/n2_result.txt create mode 100644 plugins/git4idea/testData/netrc/n3_two_standard/n3_config.txt create mode 100644 plugins/git4idea/testData/netrc/n3_two_standard/n3_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n3_two_standard/n3_result.txt create mode 100644 plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_config.txt create mode 100644 plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_result.txt create mode 100644 plugins/git4idea/testData/netrc/n5_overriding_record/n5_config.txt create mode 100644 plugins/git4idea/testData/netrc/n5_overriding_record/n5_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n5_overriding_record/n5_result.txt create mode 100644 plugins/git4idea/testData/netrc/n6_poor_format/n6_config.txt create mode 100644 plugins/git4idea/testData/netrc/n6_poor_format/n6_desc.txt create mode 100644 plugins/git4idea/testData/netrc/n6_poor_format/n6_result.txt rename plugins/git4idea/tests/git4idea/{tests => test}/GitTestUtil.java (78%) create mode 100644 plugins/git4idea/tests/git4idea/util/NetrcDataTest.java diff --git a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java index 7ae79a689c12..f5ef78f7d239 100644 --- a/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java +++ b/plugins/git4idea/src/git4idea/jgit/GitHttpAdapter.java @@ -29,6 +29,7 @@ import git4idea.remote.GitRememberedInputs; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.update.GitFetchResult; +import git4idea.util.NetrcData; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.JGitInternalException; @@ -43,6 +44,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.ProxySelector; import java.net.URISyntaxException; @@ -65,9 +67,27 @@ public final class GitHttpAdapter { public static boolean isHttpUrlWithoutUserCredentials(@NotNull String url) { // if username & password are specified in the url, give it to the native Git - return url.startsWith("http") && !HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches(); + if (!url.startsWith("http")) { + return false; + } + if (HTTP_URL_WITH_USERNAME_AND_PASSWORD.matcher(url).matches()) { + return false; + } + + try { + NetrcData netrcData = NetrcData.parse(); + return !netrcData.hasAuthDataForUrl(url); + } + catch (FileNotFoundException e) { + return false; + } + catch (IOException e) { + LOG.warn("Couldn't read netrc file", e); + return false; + } } + private enum GeneralResult { SUCCESS, CANCELLED, diff --git a/plugins/git4idea/src/git4idea/util/NetrcData.java b/plugins/git4idea/src/git4idea/util/NetrcData.java new file mode 100644 index 000000000000..4fe9cfc9a5e2 --- /dev/null +++ b/plugins/git4idea/src/git4idea/util/NetrcData.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2011 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 git4idea.util; + +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.SystemProperties; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * Parses {@code .netrc} file and stores the parsed authentication information in {@link AuthRecord} objects. + * Parse only {@code machine}, {@code login} and {@code password} fields. + * + * @author Kirill Likhodedov + */ +public class NetrcData { + + private static final String NETRC_FILE = SystemInfo.isWindows ? "_netrc" : ".netrc"; + private final Map myAuthDataMap; + + private NetrcData(@NotNull Map authData) { + myAuthDataMap = authData; + } + + /** + * Parses the {@code .netrc} file (which is {@code _netrc} on Windows) and returns the NetrcData object which can be analyzed further. + */ + @NotNull + public static NetrcData parse() throws IOException { + String home = SystemProperties.getUserHome(); + File netrc = new File(home, NETRC_FILE); + return parse(netrc); + } + + @NotNull + static NetrcData parse(@NotNull File netrcFile) throws IOException { + if (!netrcFile.exists()) { + throw new FileNotFoundException(netrcFile.getPath()); + } + String netrcContent = FileUtil.loadFile(netrcFile); + return parse(netrcContent); + } + + /** + * @return true iff the host of the given url is contained in {@code .netrc}, and both login and password are set for this host. + */ + public boolean hasAuthDataForUrl(@NotNull String url) { + String host = getHostFromUrl(url); + AuthRecord authRecord = myAuthDataMap.get(host); + return authRecord != null && authRecord.getLogin() != null && authRecord.getPassword() != null; + } + + @NotNull + Collection getAuthData() { + return myAuthDataMap.values(); + } + + @NotNull + private static String getHostFromUrl(@NotNull String url) { + final String schemaSeparator = "://"; + String urlWithoutSchema = url.substring(url.indexOf(schemaSeparator) + schemaSeparator.length()); + return urlWithoutSchema.substring(0, urlWithoutSchema.indexOf('/')); + } + + @NotNull + private static NetrcData parse(@NotNull String content) { + Map result = new HashMap(); + StringTokenizer tokenizer = new StringTokenizer(content); + AuthRecord currentRecord = null; + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (token.equalsIgnoreCase("machine")) { + if (!tokenizer.hasMoreTokens()) { + break; + } + String host = tokenizer.nextToken(); + host = host.toLowerCase(); // hosts are case insensitive + if (result.containsKey(host)) { + currentRecord = result.get(host); + } else { + currentRecord = new AuthRecord(host); + result.put(host, currentRecord); + } + } + else if (token.equalsIgnoreCase("login")) { + if (!tokenizer.hasMoreTokens()) { + break; + } + if (currentRecord != null && currentRecord.getLogin() == null) { + currentRecord.setLogin(tokenizer.nextToken()); + } + } + else if (token.equalsIgnoreCase("password")) { + if (!tokenizer.hasMoreTokens()) { + break; + } + if (currentRecord != null && currentRecord.getPassword() == null) { + currentRecord.setPassword(tokenizer.nextToken()); + } + } + } + return new NetrcData(result); + } + + static class AuthRecord { + private final String myHost; + private String myLogin; + private String myPassword; + + AuthRecord(String host, String login, String password) { + myHost = host; + myLogin = login; + myPassword = password; + } + + private AuthRecord(String host) { + myHost = host; + } + + @Nullable + String getLogin() { + return myLogin; + } + + @Nullable + String getPassword() { + return myPassword; + } + + private void setLogin(String login) { + myLogin = login; + } + + private void setPassword(String password) { + myPassword = password; + } + + @Override + public String toString() { + return String.format("AuthRecord{host=%s, login=%s, password=%s}", myHost, myLogin, myPassword); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AuthRecord record = (AuthRecord)o; + + if (myHost != null ? !myHost.equalsIgnoreCase(record.myHost) : record.myHost != null) return false; // NB: host is case insensitive + if (myLogin != null ? !myLogin.equals(record.myLogin) : record.myLogin != null) return false; + if (myPassword != null ? !myPassword.equals(record.myPassword) : record.myPassword != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myHost != null ? myHost.hashCode() : 0; + result = 31 * result + (myLogin != null ? myLogin.hashCode() : 0); + result = 31 * result + (myPassword != null ? myPassword.hashCode() : 0); + return result; + } + } + +} diff --git a/plugins/git4idea/testData/netrc/n0_no/n0_config.txt b/plugins/git4idea/testData/netrc/n0_no/n0_config.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/git4idea/testData/netrc/n0_no/n0_desc.txt b/plugins/git4idea/testData/netrc/n0_no/n0_desc.txt new file mode 100644 index 000000000000..f7db4c9ef147 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n0_no/n0_desc.txt @@ -0,0 +1 @@ +n0 empty netrc diff --git a/plugins/git4idea/testData/netrc/n0_no/n0_result.txt b/plugins/git4idea/testData/netrc/n0_no/n0_result.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/git4idea/testData/netrc/n1_just_login/n1_config.txt b/plugins/git4idea/testData/netrc/n1_just_login/n1_config.txt new file mode 100644 index 000000000000..6044773e65b7 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n1_just_login/n1_config.txt @@ -0,0 +1,2 @@ +machine bitbucket.org + login john diff --git a/plugins/git4idea/testData/netrc/n1_just_login/n1_desc.txt b/plugins/git4idea/testData/netrc/n1_just_login/n1_desc.txt new file mode 100644 index 000000000000..b5d50118bf7a --- /dev/null +++ b/plugins/git4idea/testData/netrc/n1_just_login/n1_desc.txt @@ -0,0 +1 @@ +n1 just login for machine diff --git a/plugins/git4idea/testData/netrc/n1_just_login/n1_result.txt b/plugins/git4idea/testData/netrc/n1_just_login/n1_result.txt new file mode 100644 index 000000000000..d64e7625ca33 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n1_just_login/n1_result.txt @@ -0,0 +1 @@ +bitbucket.org john diff --git a/plugins/git4idea/testData/netrc/n2_standard/n2_config.txt b/plugins/git4idea/testData/netrc/n2_standard/n2_config.txt new file mode 100644 index 000000000000..f83592d76b83 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n2_standard/n2_config.txt @@ -0,0 +1,3 @@ +machine bitbucket.org + login john + password pass diff --git a/plugins/git4idea/testData/netrc/n2_standard/n2_desc.txt b/plugins/git4idea/testData/netrc/n2_standard/n2_desc.txt new file mode 100644 index 000000000000..e8e81d813e8d --- /dev/null +++ b/plugins/git4idea/testData/netrc/n2_standard/n2_desc.txt @@ -0,0 +1 @@ +n2 login & password defined diff --git a/plugins/git4idea/testData/netrc/n2_standard/n2_result.txt b/plugins/git4idea/testData/netrc/n2_standard/n2_result.txt new file mode 100644 index 000000000000..8d6804e3f9af --- /dev/null +++ b/plugins/git4idea/testData/netrc/n2_standard/n2_result.txt @@ -0,0 +1 @@ +bitbucket.org john pass diff --git a/plugins/git4idea/testData/netrc/n3_two_standard/n3_config.txt b/plugins/git4idea/testData/netrc/n3_two_standard/n3_config.txt new file mode 100644 index 000000000000..0a0045706482 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n3_two_standard/n3_config.txt @@ -0,0 +1,6 @@ +machine bitbucket.org + login john + password pass +machine github.com + login bob + password pswd diff --git a/plugins/git4idea/testData/netrc/n3_two_standard/n3_desc.txt b/plugins/git4idea/testData/netrc/n3_two_standard/n3_desc.txt new file mode 100644 index 000000000000..3e5951219a16 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n3_two_standard/n3_desc.txt @@ -0,0 +1 @@ +n3 two full standard hosts diff --git a/plugins/git4idea/testData/netrc/n3_two_standard/n3_result.txt b/plugins/git4idea/testData/netrc/n3_two_standard/n3_result.txt new file mode 100644 index 000000000000..741aaf46386b --- /dev/null +++ b/plugins/git4idea/testData/netrc/n3_two_standard/n3_result.txt @@ -0,0 +1,2 @@ +bitbucket.org john pass +github.com bob pswd diff --git a/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_config.txt b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_config.txt new file mode 100644 index 000000000000..8e86f2fdbf13 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_config.txt @@ -0,0 +1,4 @@ +machine bitbucket.org + login john +machine bitbucket.org + password pass diff --git a/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_desc.txt b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_desc.txt new file mode 100644 index 000000000000..31f0fc6d2f72 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_desc.txt @@ -0,0 +1,2 @@ +n4 two supplementary records for one host +One host defined twice, login is set in the first record, password - in the second => complete auth data should be read diff --git a/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_result.txt b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_result.txt new file mode 100644 index 000000000000..8d6804e3f9af --- /dev/null +++ b/plugins/git4idea/testData/netrc/n4_two_records_for_1_host/n4_result.txt @@ -0,0 +1 @@ +bitbucket.org john pass diff --git a/plugins/git4idea/testData/netrc/n5_overriding_record/n5_config.txt b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_config.txt new file mode 100644 index 000000000000..89f3ce41ad68 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_config.txt @@ -0,0 +1,5 @@ +machine bitbucket.org + login john + password pass +machine bitbucket.org + password doesnt_override diff --git a/plugins/git4idea/testData/netrc/n5_overriding_record/n5_desc.txt b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_desc.txt new file mode 100644 index 000000000000..d4f15fe11722 --- /dev/null +++ b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_desc.txt @@ -0,0 +1 @@ +n5 overriding records for 1 host diff --git a/plugins/git4idea/testData/netrc/n5_overriding_record/n5_result.txt b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_result.txt new file mode 100644 index 000000000000..8d6804e3f9af --- /dev/null +++ b/plugins/git4idea/testData/netrc/n5_overriding_record/n5_result.txt @@ -0,0 +1 @@ +bitbucket.org john pass diff --git a/plugins/git4idea/testData/netrc/n6_poor_format/n6_config.txt b/plugins/git4idea/testData/netrc/n6_poor_format/n6_config.txt new file mode 100644 index 000000000000..46c851b9d82c --- /dev/null +++ b/plugins/git4idea/testData/netrc/n6_poor_format/n6_config.txt @@ -0,0 +1,4 @@ +machine +bitbucket.org + login + john password pass diff --git a/plugins/git4idea/testData/netrc/n6_poor_format/n6_desc.txt b/plugins/git4idea/testData/netrc/n6_poor_format/n6_desc.txt new file mode 100644 index 000000000000..2dfc8d46c73d --- /dev/null +++ b/plugins/git4idea/testData/netrc/n6_poor_format/n6_desc.txt @@ -0,0 +1 @@ +n6 poorly formatted netrc for 1 host diff --git a/plugins/git4idea/testData/netrc/n6_poor_format/n6_result.txt b/plugins/git4idea/testData/netrc/n6_poor_format/n6_result.txt new file mode 100644 index 000000000000..8d6804e3f9af --- /dev/null +++ b/plugins/git4idea/testData/netrc/n6_poor_format/n6_result.txt @@ -0,0 +1 @@ +bitbucket.org john pass diff --git a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java index b5dc57ccd902..1b70071acb95 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitConfigTest.java @@ -15,71 +15,34 @@ */ package git4idea.repo; -import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import git4idea.tests.GitTestUtil; +import git4idea.test.GitTestUtil; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.File; -import java.io.FilenameFilter; import java.io.IOException; import java.util.*; -import static org.testng.Assert.assertNotNull; - /** * @author Kirill Likhodedov */ public class GitConfigTest { - + @DataProvider(name = "remote") public Object[][] loadRemotes() throws IOException { - return loadData("remote"); + return GitTestUtil.loadConfigData(getTestDataFolder("remote")); } @DataProvider(name = "branch") public Object[][] loadBranches() throws IOException { - return loadData("branch"); + return GitTestUtil.loadConfigData(getTestDataFolder("branch")); } - public static Object[][] loadData(String subfolder) throws IOException { - File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea")); - File dataDir = new File(new File(new File(pluginRoot, "testData"), "config"), subfolder); - File[] tests = dataDir.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return !name.startsWith("."); - } - }); - Object[][] data = new Object[tests.length][]; - for (int i = 0; i < tests.length; i++) { - File testDir = tests[i]; - File descriptionFile = null; - File configFile = null; - File resultFile = null; - for (File file : testDir.listFiles()) { - if (file.getName().endsWith("_desc.txt")) { - descriptionFile = file; - } - else if (file.getName().endsWith("_config.txt")) { - configFile = file; - } - else if (file.getName().endsWith("_result.txt")) { - resultFile = file; - } - } - assertNotNull(descriptionFile, String.format("description file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); - assertNotNull(configFile, String.format("config file file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); - assertNotNull(resultFile, String.format("result file file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); - - String testName = FileUtil.loadFile(descriptionFile).split("\n")[0]; // description is in the first line of the desc-file - data[i] = new Object[]{ - testName, configFile, resultFile - }; - } - return data; + private static File getTestDataFolder(String subfolder) { + File testData = GitTestUtil.getTestDataFolder(); + return new File(new File(testData, "config"), subfolder); } @Test(dataProvider = "remote") diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java index 21be415c4ade..02df94ede3ad 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryReaderTest.java @@ -21,7 +21,7 @@ import com.intellij.testFramework.LightIdeaTestCase; import com.intellij.util.Processor; import git4idea.GitBranch; import git4idea.branch.GitBranchesCollection; -import git4idea.tests.GitTestUtil; +import git4idea.test.GitTestUtil; import org.jetbrains.annotations.NotNull; import java.io.File; diff --git a/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java similarity index 78% rename from plugins/git4idea/tests/git4idea/tests/GitTestUtil.java rename to plugins/git4idea/tests/git4idea/test/GitTestUtil.java index c3f799d5bf9c..97944322e044 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitTestUtil.java +++ b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java @@ -13,21 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.tests; +package git4idea.test; +import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; +import git4idea.tests.GitTestRepository; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import static org.testng.Assert.assertNotNull; import static org.testng.Assert.fail; /** @@ -171,6 +178,47 @@ public class GitTestUtil { return false; } + public static Object[][] loadConfigData(@NotNull File dataFolder) throws IOException { + File[] tests = dataFolder.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return !name.startsWith("."); + } + }); + Object[][] data = new Object[tests.length][]; + for (int i = 0; i < tests.length; i++) { + File testDir = tests[i]; + File descriptionFile = null; + File configFile = null; + File resultFile = null; + for (File file : testDir.listFiles()) { + if (file.getName().endsWith("_desc.txt")) { + descriptionFile = file; + } + else if (file.getName().endsWith("_config.txt")) { + configFile = file; + } + else if (file.getName().endsWith("_result.txt")) { + resultFile = file; + } + } + assertNotNull(descriptionFile, String.format("description file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); + assertNotNull(configFile, String.format("config file file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); + assertNotNull(resultFile, String.format("result file file not found in %s among %s", testDir, Arrays.toString(testDir.list()))); + + String testName = FileUtil.loadFile(descriptionFile).split("\n")[0]; // description is in the first line of the desc-file + data[i] = new Object[]{ + testName, configFile, resultFile + }; + } + return data; + } + + public static File getTestDataFolder() { + File pluginRoot = new File(PluginPathManager.getPluginHomePath("git4idea")); + return new File(pluginRoot, "testData"); + } + public interface EqualityChecker { boolean areEqual(T actual, E expected); } diff --git a/plugins/git4idea/tests/git4idea/tests/GitBranchTest.java b/plugins/git4idea/tests/git4idea/tests/GitBranchTest.java index b4a4e01ed647..12dbde65af00 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitBranchTest.java +++ b/plugins/git4idea/tests/git4idea/tests/GitBranchTest.java @@ -18,6 +18,7 @@ package git4idea.tests; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitBranch; +import git4idea.test.GitTestUtil; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; diff --git a/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java b/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java index b791d2a58210..3c260a7de2f5 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java +++ b/plugins/git4idea/tests/git4idea/tests/GitChangeProviderTest.java @@ -26,6 +26,7 @@ import com.intellij.testFramework.vcs.MockChangelistBuilder; import com.intellij.testFramework.vcs.MockDirtyScope; import git4idea.GitVcs; import git4idea.status.GitChangeProvider; +import git4idea.test.GitTestUtil; import org.testng.annotations.BeforeMethod; import java.util.Arrays; diff --git a/plugins/git4idea/tests/git4idea/tests/GitMergeTest.java b/plugins/git4idea/tests/git4idea/tests/GitMergeTest.java index 2694881e4b51..50495214d432 100644 --- a/plugins/git4idea/tests/git4idea/tests/GitMergeTest.java +++ b/plugins/git4idea/tests/git4idea/tests/GitMergeTest.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; +import git4idea.test.GitTestUtil; import org.testng.annotations.Test; import java.io.IOException; diff --git a/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java b/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java new file mode 100644 index 000000000000..ee872d8d4a58 --- /dev/null +++ b/plugins/git4idea/tests/git4idea/util/NetrcDataTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2011 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 git4idea.util; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import git4idea.test.GitTestUtil; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/** + * @author Kirill Likhodedov + */ +public class NetrcDataTest { + + @DataProvider(name = "netrc") + public Object[][] loadBranches() throws IOException { + return GitTestUtil.loadConfigData(new File(GitTestUtil.getTestDataFolder(), "netrc")); + } + + @Test(dataProvider = "netrc") + public void testBranches(String testName, File netrcFile, File resultFile) throws IOException { + NetrcData netrcData = NetrcData.parse(netrcFile); + Collection expectedRecord = readAuthData(resultFile); + GitTestUtil.assertEqualCollections(netrcData.getAuthData(), expectedRecord); + + if (!testName.startsWith("n0") && !testName.startsWith("n1")) { // auth data not defined for these tests + assertTrue(netrcData.hasAuthDataForUrl("http://bitbucket.org")); + assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org")); + assertTrue(netrcData.hasAuthDataForUrl("bitbucket.org")); + assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo.git")); + assertTrue(netrcData.hasAuthDataForUrl("https://bitbucket.org/user/repo")); + } + + assertFalse(netrcData.hasAuthDataForUrl("http://example.com")); + assertFalse(netrcData.hasAuthDataForUrl("https://example.com")); + assertFalse(netrcData.hasAuthDataForUrl("example.com")); + } + + private static Collection readAuthData(File file) throws IOException { + Collection authRecords = new ArrayList(); + for (String authLine : FileUtil.loadFile(file).split("\n")) { + if (StringUtil.isEmptyOrSpaces(authLine)) { + continue; + } + String[] data = authLine.split(" "); + authRecords.add(new NetrcData.AuthRecord(data[0], data[1], data.length > 2 ? data[2] : null)); + } + return authRecords; + } +} From be5e179dabe8da9069d1eaab19867cde329100ec Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 19 Dec 2011 15:37:53 +0100 Subject: [PATCH 11/11] fix rename test --- .../refactoring/RenamePackageTest.java | 63 ------------------- 1 file changed, 63 deletions(-) delete mode 100644 java/java-tests/testSrc/com/intellij/refactoring/RenamePackageTest.java diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenamePackageTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenamePackageTest.java deleted file mode 100644 index c3782af2980e..000000000000 --- a/java/java-tests/testSrc/com/intellij/refactoring/RenamePackageTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.intellij.refactoring; - -import com.intellij.codeInsight.CodeInsightTestCase; -import com.intellij.openapi.application.ex.PathManagerEx; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiPackage; -import com.intellij.refactoring.rename.RenameProcessor; -import com.intellij.testFramework.IdeaTestUtil; -import com.intellij.testFramework.PsiTestUtil; - -import java.io.File; - -public class RenamePackageTest extends CodeInsightTestCase { - public void testJspImport() throws Exception { - doTest("jspImport", "pack1", "pack2"); - } - - public void testNonJava() throws Exception { - doTest("nonJava", "com.foo", "fooNew"); - } - - public void testInBrokenXml() throws Exception { - doTest("inBrokenXml", "somepckg", "somepckg1"); - } - - - public void testJsp() throws Exception { - doTest("jsp", "pack1", "pack2"); - } - - private void doTest(String testName, String packageName, String newPackageName) throws Exception { - String root = PathManagerEx.getTestDataPath()+ "/refactoring/renamePackage/" + testName; - - String rootBefore = root + "/before"; - PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk17()); - VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete); - - performAction(packageName, newPackageName); - - String rootAfter = root + "/after"; - VirtualFile rootDir2 = LocalFileSystem.getInstance().findFileByPath(rootAfter.replace(File.separatorChar, '/')); - IdeaTestUtil.assertDirectoriesEqual(rootDir2, rootDir, IdeaTestUtil.CVS_FILE_FILTER); - } - - private void performAction(String packageName, String newPackageName) throws Exception { - PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName); - assertNotNull("Package " + packageName + " not found", aPackage); - - //PsiDirectory dir = aPackage.getDirectories()[0]; - //it is now impossible to rename dir without renaming corresponding package via rename processor - move processor would be used instead - new RenameProcessor(myProject, aPackage, newPackageName, true, true).run(); - FileDocumentManager.getInstance().saveAllDocuments(); - } - - @Override - protected boolean isRunInWriteAction() { - return false; - } -}