diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java index cea5800d3483..1fe5de1d8951 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java @@ -126,8 +126,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { if (rawText != null && rawText.rawText != null) return rawText.rawText; // Copied from the string literal. Copy as is. StringBuilder buffer = new StringBuilder(text.length()); - CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); - @NonNls String breaker = codeStyleSettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE ? "\\n\"\n+ \"" : "\\n\" +\n\""; + @NonNls String breaker = getLineBreaker(token); final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true); for (int i = 0; i < lines.length; i++) { String line = lines[i]; @@ -143,6 +142,11 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { return text; } + protected String getLineBreaker(PsiElement token) { + CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(token.getProject()); + return codeStyleSettings.BINARY_OPERATION_SIGN_ON_NEXT_LINE ? "\\n\"\n+ \"" : "\\n\" +\n\""; + } + @Nullable private PsiElement findLiteralTokenType(PsiFile file, int selectionStart, int selectionEnd) { final PsiElement elementAtSelectionStart = file.findElementAt(selectionStart); diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java index 60a4cc365860..97d72513e9bf 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java @@ -109,7 +109,7 @@ public class DiffApplication implements ApplicationStarterEx { final DirDiffSettings settings = new DirDiffSettings(); settings.showInFrame = false; - diffManager.showDiff(d1, d2, settings); + diffManager.showDiff(d1, d2, settings, null); } else { SimpleDiffRequest request = SimpleDiffRequest.compareFiles(file1, file2, null); request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java b/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java index 20368ef73b19..915a49a1e054 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java @@ -22,6 +22,8 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.event.WindowListener; + /** * @author Konstantin Bulenkov */ @@ -30,7 +32,7 @@ public abstract class DirDiffManager { return ServiceManager.getService(project, DirDiffManager.class); } - public abstract void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings); + public abstract void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings, WindowListener windowListener); public abstract boolean canShow(@NotNull DiffElement dir1, @NotNull DiffElement dir2); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareDirectoriesAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareDirectoriesAction.java index 7bb751765ced..b9ccf6b2aa91 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareDirectoriesAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareDirectoriesAction.java @@ -53,7 +53,7 @@ public class CompareDirectoriesAction extends AnAction { } final DirDiffManager mgr = DirDiffManager.getInstance(project); if (src != null && trg != null && mgr.canShow(src, trg)) { - mgr.showDiff(src, trg, new DirDiffSettings()); + mgr.showDiff(src, trg, new DirDiffSettings(), null); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java index 95dafde9eabf..43609837ff84 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java @@ -62,7 +62,7 @@ public class CompareJarsAction extends AnAction { } final DirDiffManager mgr = DirDiffManager.getInstance(project); if (src != null && trg != null && mgr.canShow(src, trg)) { - mgr.showDiff(src, trg, new DirDiffSettings()); + mgr.showDiff(src, trg, new DirDiffSettings(), null); } } } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java index 404929bcb70b..3ebf3bad2406 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java @@ -282,7 +282,7 @@ public class MacMessagesImpl extends MacMessages { IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false); invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", - Foundation.createSelector("showVariableButtonsSheet:"), paramsArray, true); + Foundation.createSelector("showVariableButtonsSheet:"), paramsArray, false); } finally { invoke(pool, "release"); @@ -443,7 +443,7 @@ public class MacMessagesImpl extends MacMessages { IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false); invoke(delegate, "performSelectorOnMainThread:withObject:waitUntilDone:", - Foundation.createSelector("showSheet:"), paramsArray, true); + Foundation.createSelector("showSheet:"), paramsArray, false); } finally { invoke(pool, "release"); diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java index 829cbfcd0c95..d803cc50622d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java @@ -24,6 +24,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.event.WindowListener; /** * @author Konstantin Bulenkov @@ -36,15 +39,25 @@ public class DirDiffManagerImpl extends DirDiffManager { } @Override - public void showDiff(@NotNull final DiffElement dir1, @NotNull final DiffElement dir2, final DirDiffSettings settings) { + public void showDiff(@NotNull final DiffElement dir1, + @NotNull final DiffElement dir2, + final DirDiffSettings settings, + @Nullable WindowListener windowListener) { final DirDiffTableModel model = new DirDiffTableModel(myProject, dir1, dir2, settings); if (settings.showInFrame) { - new DirDiffFrame(myProject, model).show(); + DirDiffFrame frame = new DirDiffFrame(myProject, model); + if (windowListener != null) { + frame.getFrame().addWindowListener(windowListener); + } + frame.show(); } else { final DirDiffDialog dirDiffDialog = new DirDiffDialog(myProject, model); if (myProject == null || myProject.isDefault()) { dirDiffDialog.setModal(true); } + if (windowListener != null) { + dirDiffDialog.getOwner().addWindowListener(windowListener); + } dirDiffDialog.show(); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java index d0b88535b3ce..6f8480ce5e75 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java @@ -182,9 +182,9 @@ public class DirDiffPanel implements Disposable { column.setMinWidth(120); } } - final DirDiffToolbarActions actions = new DirDiffToolbarActions(myModel, this.getPanel()); + final DirDiffToolbarActions actions = new DirDiffToolbarActions(myModel, myDiffPanel); final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("DirDiff", actions, true); - registerCustomShortcuts(actions, myRootPanel); + registerCustomShortcuts(actions, myTable); myToolBarPanel.add(toolbar.getComponent(), BorderLayout.CENTER); final JBLoadingPanel loadingPanel = new JBLoadingPanel(new BorderLayout(), wnd.getDisposable()); loadingPanel.add(myComponent, BorderLayout.CENTER); @@ -350,10 +350,14 @@ public class DirDiffPanel implements Disposable { myDiffPanel.repaint(); } - private void registerCustomShortcuts(DirDiffToolbarActions actions, JPanel rootPanel) { - final ActionManager mgr = ActionManager.getInstance(); + private void registerCustomShortcuts(DirDiffToolbarActions actions, JComponent component) { for (AnAction action : actions.getChildren(null)) { - + if (action instanceof ShortcutProvider) { + final ShortcutSet shortcut = ((ShortcutProvider)action).getShortcut(); + if (shortcut != null) { + action.registerCustomShortcutSet(shortcut, component); + } + } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java index b0e469364e97..572cceafb0d8 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java @@ -44,6 +44,7 @@ import javax.swing.table.AbstractTableModel; import java.awt.*; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -62,7 +63,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode private DiffElement mySrc; private DiffElement myTrg; private DTree myTree; - private final List myElements = new ArrayList(); + private final List myElements = Collections.synchronizedList(new ArrayList()); private final AtomicBoolean myUpdating = new AtomicBoolean(false); private JBTable myTable; public String DECORATOR = "DIFF_TABLE_DECORATOR"; @@ -90,58 +91,65 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode public void applyRemove() { final List selectedElements = getSelectedElements(); myUpdating.set(true); - final Iterator i = myElements.iterator(); - while(i.hasNext()) { - final DType type = i.next().getType(); - switch (type) { - case SOURCE: - if (!mySettings.showNewOnSource) i.remove(); - break; - case TARGET: - if (!mySettings.showNewOnTarget) i.remove(); - break; - case SEPARATOR: - break; - case CHANGED: - if (!mySettings.showDifferent) i.remove(); - break; - case EQUAL: - if (!mySettings.showEqual) i.remove(); - break; - } - } - - boolean sep = true; - for (int j = myElements.size() - 1; j >= 0; j--) { - if (myElements.get(j).isSeparator()) { - if (sep) { - myElements.remove(j); - } else { - sep = true; + synchronized (myElements) { + final Iterator i = myElements.iterator(); + while(i.hasNext()) { + final DType type = i.next().getType(); + switch (type) { + case SOURCE: + if (!mySettings.showNewOnSource) i.remove(); + break; + case TARGET: + if (!mySettings.showNewOnTarget) i.remove(); + break; + case SEPARATOR: + break; + case CHANGED: + if (!mySettings.showDifferent) i.remove(); + break; + case EQUAL: + if (!mySettings.showEqual) i.remove(); + break; } - } else { - sep = false; } + + boolean sep = true; + for (int j = myElements.size() - 1; j >= 0; j--) { + if (myElements.get(j).isSeparator()) { + if (sep) { + myElements.remove(j); + } + else { + sep = true; + } + } + else { + sep = false; + } + } + fireTableDataChanged(); + myUpdating.set(false); + int index; + if (!selectedElements.isEmpty() && (index = myElements.indexOf(selectedElements.get(0))) != -1) { + myTable.getSelectionModel().setSelectionInterval(index, index); + TableUtil.scrollSelectionToVisible(myTable); + } + else { + selectFirstRow(); + } + myPanel.focusTable(); + myPanel.update(true); } - fireTableDataChanged(); - myUpdating.set(false); - int index; - if (!selectedElements.isEmpty() && (index = myElements.indexOf(selectedElements.get(0))) != -1) { - myTable.getSelectionModel().setSelectionInterval(index, index); - TableUtil.scrollSelectionToVisible(myTable); - } else { - selectFirstRow(); - } - myPanel.focusTable(); - myPanel.update(true); } public void selectFirstRow() { - if (myElements.size() > 0) { - int row = myElements.get(0).isSeparator() ? 1 : 0; - if (row < myTable.getRowCount()) { - myTable.getSelectionModel().setSelectionInterval(row, row); - TableUtil.scrollSelectionToVisible(myTable); + synchronized (myElements) { + if (myElements.size() > 0) { + int row = myElements.get(0).isSeparator() ? 1 : 0; + if (row < myTable.getRowCount()) { + myTable.getSelectionModel().setSelectionInterval(row, row); + TableUtil.scrollSelectionToVisible(myTable); + } } } } @@ -167,11 +175,14 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode String right; if (text == null) { right = EMPTY_STRING; - } else if (text.length() == LEN) { + } + else if (text.length() == LEN) { right = text; - } else if (text.length() < LEN) { + } + else if (text.length() < LEN) { right = text + EMPTY_STRING.substring(0, LEN - text.length()); - } else { + } + else { right = "..." + text.substring(text.length() - LEN + 2); } return "Loading... " + right; @@ -267,20 +278,22 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode fillElements(myTree, elements); final Runnable uiThread = new Runnable() { public void run() { - clear(); - myElements.addAll(elements); - myUpdating.set(false); - fireTableDataChanged(); - DirDiffTableModel.this.text.set(""); - if (loadingPanel.isLoading()) { - loadingPanel.stopLoading(); + synchronized (myElements) { + clear(); + myElements.addAll(elements); + myUpdating.set(false); + fireTableDataChanged(); + DirDiffTableModel.this.text.set(""); + if (loadingPanel.isLoading()) { + loadingPanel.stopLoading(); + } + if (mySelectionConfig == null) { + selectFirstRow(); + } else { + mySelectionConfig.restore(); + } + myPanel.update(true); } - if (mySelectionConfig == null) { - selectFirstRow(); - } else { - mySelectionConfig.restore(); - } - myPanel.update(true); } }; if (myProject.isDefault()) { @@ -328,10 +341,12 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode } public void clear() { - if (!myElements.isEmpty()) { - final int size = myElements.size(); - myElements.clear(); - fireTableRowsDeleted(0, size - 1); + synchronized (myElements) { + if (!myElements.isEmpty()) { + final int size = myElements.size(); + myElements.clear(); + fireTableRowsDeleted(0, size - 1); + } } } @@ -354,7 +369,9 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode @Nullable public DirDiffElement getElementAt(int index) { - return 0 <= index && index < myElements.size() ? myElements.get(index) : null; + synchronized (myElements) { + return 0 <= index && index < myElements.size() ? myElements.get(index) : null; + } } public DiffElement getSourceDir() { @@ -508,6 +525,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode Runnable onFinish = new Runnable() { @Override public void run() { + ApplicationManager.getApplication().assertIsDispatchThread(); if (!Disposer.isDisposed(DirDiffTableModel.this)) { DiffElement newElement = diff.get(); refreshElementAfterCopyTo(newElement, element); @@ -534,16 +552,18 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode private void refreshElementAfterCopyTo(DiffElement newElement, DirDiffElement element) { if (newElement != null) { - final DTree node = element.getNode(); - final int row = myElements.indexOf(element); - if (getSettings().showEqual) { - node.setType(DType.EQUAL); - node.setTarget(newElement); - element.updateSourceFromTarget(newElement); - fireTableRowsUpdated(row, row); - } - else { - removeElement(element); + synchronized (myElements) { + final DTree node = element.getNode(); + final int row = myElements.indexOf(element); + if (getSettings().showEqual) { + node.setType(DType.EQUAL); + node.setTarget(newElement); + element.updateSourceFromTarget(newElement); + fireTableRowsUpdated(row, row); + } + else { + removeElement(element); + } } } } @@ -559,6 +579,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode Runnable onFinish = new Runnable() { @Override public void run() { + ApplicationManager.getApplication().assertIsDispatchThread(); if (!Disposer.isDisposed(DirDiffTableModel.this)) { refreshElementAfterCopyFrom(element, diff.get()); if (!errorMessage.isNull()) { @@ -585,40 +606,45 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode private void refreshElementAfterCopyFrom(DirDiffElement element, DiffElement newElement) { if (newElement != null) { final DTree node = element.getNode(); - final int row = myElements.indexOf(element); - if (getSettings().showEqual) { - node.setType(DType.EQUAL); - node.setSource(newElement); - element.updateTargetFromSource(newElement); - fireTableRowsUpdated(row, row); - } - else { - removeElement(element); + synchronized (myElements) { + final int row = myElements.indexOf(element); + if (getSettings().showEqual) { + node.setType(DType.EQUAL); + node.setSource(newElement); + element.updateTargetFromSource(newElement); + fireTableRowsUpdated(row, row); + } + else { + removeElement(element); + } } } } private void removeElement(DirDiffElement element) { - int row = myElements.indexOf(element); - if (row != -1) { - final DTree node = element.getNode(); - final DTree parentNode = element.getParentNode(); - parentNode.remove(node); - myElements.remove(row); - int start = row; + synchronized (myElements) { + int row = myElements.indexOf(element); + if (row != -1) { + final DTree node = element.getNode(); + final DTree parentNode = element.getParentNode(); + parentNode.remove(node); + myElements.remove(row); + int start = row; - if (row > 0 && row == myElements.size() && myElements.get(row - 1).isSeparator()) { - final DirDiffElement el = myElements.get(row - 1); - el.getParentNode().remove(el.getNode()); - myElements.remove(row - 1); - start = row - 1; - } else if (row != myElements.size() && myElements.get(row).isSeparator() && row > 0 && myElements.get(row - 1).isSeparator()) { - final DirDiffElement el = myElements.get(row - 1); - el.getParentNode().remove(el.getNode()); - myElements.remove(row - 1); - start = row - 1; + if (row > 0 && row == myElements.size() && myElements.get(row - 1).isSeparator()) { + final DirDiffElement el = myElements.get(row - 1); + el.getParentNode().remove(el.getNode()); + myElements.remove(row - 1); + start = row - 1; + } + else if (row != myElements.size() && myElements.get(row).isSeparator() && row > 0 && myElements.get(row - 1).isSeparator()) { + final DirDiffElement el = myElements.get(row - 1); + el.getParentNode().remove(el.getNode()); + myElements.remove(row - 1); + start = row - 1; + } + fireTableRowsDeleted(start, row); } - fireTableRowsDeleted(start, row); } } @@ -636,8 +662,10 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode reportException(errorMessage.get()); } else { - if (myElements.indexOf(element) != -1) { - removeElement(element); + synchronized (myElements) { + if (myElements.indexOf(element) != -1) { + removeElement(element); + } } } } @@ -651,8 +679,10 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode } } else { - if (myElements.indexOf(element) != -1) { - removeElement(element); + synchronized (myElements) { + if (myElements.indexOf(element) != -1) { + removeElement(element); + } } final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { @@ -670,12 +700,14 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode } public void synchronizeSelected() { - rememberSelection(); - for (DirDiffElement element : getSelectedElements()) { - syncElement(element); + synchronized (myElements) { + rememberSelection(); + for (DirDiffElement element : getSelectedElements()) { + syncElement(element); + } + restoreSelection(); } - restoreSelection(); - } + } private void restoreSelection() { if (mySelectionConfig != null) { @@ -684,10 +716,12 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode } public void synchronizeAll() { - for (DirDiffElement element : getElements()) { - syncElement(element); + synchronized (myElements) { + for (DirDiffElement element : myElements) { + syncElement(element); + } + selectFirstRow(); } - selectFirstRow(); } private void syncElement(DirDiffElement element) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java index 341085035821..5add4b0df6de 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesManager.java @@ -327,8 +327,20 @@ public class ShelveChangesManager implements ProjectComponent, JDOMExternalizabl if (defaultPath.length() == 0) { defaultPath = "unnamed"; } - return FileUtil.findSequentNonexistentFile(file, defaultPath, - extension == null ? VcsConfiguration.getInstance(project).getPatchFileExtension() : extension); + if (defaultPath.length() > (PatchNameChecker.MAX - 10)) { + defaultPath = defaultPath.substring(0, PatchNameChecker.MAX - 10); + } + while (true) { + final File nonexistentFile = FileUtil.findSequentNonexistentFile(file, defaultPath, + extension == null + ? VcsConfiguration.getInstance(project).getPatchFileExtension() + : extension); + if (nonexistentFile.getName().length() >= PatchNameChecker.MAX) { + defaultPath = defaultPath.substring(0, defaultPath.length() - 1); + continue; + } + return nonexistentFile; + } } public void unshelveChangeList(final ShelvedChangeList changeList, @Nullable final List changes, diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserFilePathNode.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserFilePathNode.java index a8a7df04fc11..9ba8a0d7e750 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserFilePathNode.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserFilePathNode.java @@ -80,7 +80,7 @@ public class ChangesBrowserFilePathNode extends ChangesBrowserNode { } public static String getRelativePath(FilePath parent, FilePath child) { - if (parent == null) return child.getPath().replace('/', File.separatorChar); + if (parent == null || ! child.getPath().startsWith(parent.getPath())) return child.getPath().replace('/', File.separatorChar); final String parentPath = parent.getPath(); final int beginOffset = (parentPath.length() == 1 && '/' == parentPath.charAt(0)) ? 0 : 1; // IDEADEV-35767 return child.getPath().substring(parent.getPath().length() + beginOffset).replace('/', File.separatorChar); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java index bf609eba1eb9..8b9cfa09f8d0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/TreeModelBuilder.java @@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.FileStatus; @@ -283,7 +284,10 @@ public class TreeModelBuilder { for (FilePath file : filePaths) { assert file != null; // whether a folder does not matter - final StaticFilePath pathKey = new StaticFilePath(false, new File(file.getIOFile().getPath().replace('\\', '/')).getAbsolutePath(), file.getVirtualFile()); + final String path = file.getPath(); + final StaticFilePath pathKey = (! FileUtil.isAbsolute(path) || VcsUtil.isPathRemote(path)) ? + new StaticFilePath(false, path, null) : + new StaticFilePath(false, new File(file.getIOFile().getPath().replace('\\', '/')).getAbsolutePath(), file.getVirtualFile()); ChangesBrowserNode oldNode = myFoldersCache.get(pathKey.getKey()); if (oldNode == null) { final ChangesBrowserNode node = ChangesBrowserNode.create(myProject, file); @@ -437,7 +441,8 @@ public class TreeModelBuilder { } private static StaticFilePath staticFrom(final FilePath fp) { - if (fp.isNonLocal() && VcsUtil.isPathRemote(fp.getPath())) { + final String path = fp.getPath(); + if (fp.isNonLocal() && (! FileUtil.isAbsolute(path) || VcsUtil.isPathRemote(path))) { return new StaticFilePath(fp.isDirectory(), fp.getIOFile().getPath().replace('\\', '/'), fp.getVirtualFile()); } return new StaticFilePath(fp.isDirectory(), new File(fp.getIOFile().getPath().replace('\\', '/')).getAbsolutePath(), fp.getVirtualFile()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java index e40c06f557ed..e691cf786a16 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/GroovyLiteralCopyPasteProcessor.java @@ -39,6 +39,25 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce return TokenSets.STRING_LITERALS.contains(token.getNode().getElementType()); } + @Override + protected String getLineBreaker(PsiElement token) { + final String text = token.getText(); + if (text.contains("'''") || text.contains("\"\"\"")) { + return "\n"; + } + + final IElementType type = token.getNode().getElementType(); + if (type == mGSTRING_LITERAL || type == mGSTRING_CONTENT) { + return super.getLineBreaker(token); + } + if (type == mSTRING_LITERAL) { + return super.getLineBreaker(token).replace('"', '\''); + } + + return "\n"; + + } + @NotNull @Override protected String escapeCharCharacters(@NotNull String s, @NotNull PsiElement token) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy index 5e135aa3a17a..8a7a279b203b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy @@ -78,4 +78,28 @@ class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase { Foo f''' } + public void testPasteMultilineIntoMultilineGString() throws Exception { + myFixture.configureByText 'a.txt', 'a/b\nc/d' + myFixture.performEditorAction IdeActions.ACTION_COPY + myFixture.configureByText 'b.groovy', 'def x = """smth"""' + myFixture.performEditorAction IdeActions.ACTION_PASTE + myFixture.checkResult 'def x = """smtha/b\nc/d"""' + } + + public void testPasteMultilineIntoString() throws Exception { + myFixture.configureByText 'a.txt', 'a\nd' + myFixture.performEditorAction IdeActions.ACTION_COPY + myFixture.configureByText 'b.groovy', "def x = 'smth'" + myFixture.performEditorAction IdeActions.ACTION_PASTE + myFixture.checkResult "def x = 'smtha\\n' +\n 'd'" + } + + public void testPasteMultilineIntoGString() throws Exception { + myFixture.configureByText 'a.txt', 'a\nd' + myFixture.performEditorAction IdeActions.ACTION_COPY + myFixture.configureByText 'b.groovy', 'def x = "smth"' + myFixture.performEditorAction IdeActions.ACTION_PASTE + myFixture.checkResult 'def x = "smtha\\n" +\n "d"' + } + } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index 6a82be732bbb..97df183ba6f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.svn.history; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.ConcurrentTasks; @@ -28,6 +29,7 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import java.util.Map; public class FirstInBranch implements Runnable { + private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.FirstInBranch"); private final SvnVcs myVcs; private final String myFullBranchUrl; private final String myFullTrunkUrl; @@ -36,6 +38,10 @@ public class FirstInBranch implements Runnable { private final Consumer myConsumer; public FirstInBranch(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl, final Consumer consumer) { + if (LOG.isDebugEnabled()) { + LOG.debug("FirstInBranch created with: repoRoot: " + repositoryRoot + " branchUrl: " + branchUrl + + " trunkUrl: " + trunkUrl); + } myVcs = vcs; myConsumer = consumer; @@ -58,6 +64,7 @@ public class FirstInBranch implements Runnable { trunkURL = SVNURL.parseURIEncoded(myFullTrunkUrl); } catch (SVNException e) { + LOG.info(e); myConsumer.consume(null); return; } @@ -86,7 +93,7 @@ public class FirstInBranch implements Runnable { } }); } catch (SVNException e) { - // + LOG.info(e); } } } @@ -106,7 +113,7 @@ public class FirstInBranch implements Runnable { }); } catch (SVNException e) { - // + LOG.info(e); } return myRevisionCandidate.get(); } @@ -117,7 +124,10 @@ public class FirstInBranch implements Runnable { final SVNLogEntryPath path = (SVNLogEntryPath) o; final String localPath = path.getPath(); final String copyPath = path.getCopyPath(); - + if (LOG.isDebugEnabled()) { + LOG.debug("localPath: " + localPath + " copy path: " + copyPath); + } + if ('A' == path.getType()) { if ((myBranchUrl.equals(localPath) || SVNPathUtil.isAncestor(localPath, myBranchUrl)) && ((myTrunkUrl.equals(copyPath)) || SVNPathUtil.isAncestor(copyPath, myTrunkUrl))) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java index c4f6db2f69c8..bb2333844374 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java @@ -267,7 +267,11 @@ public class SvnChangeList implements CommittedChangeList { private FilePath getLocalPath(final String path, final NotNullFunction detector) { final String fullPath = myRepositoryRoot + path; if (myNonLocal) return VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, detector.fun(new File(fullPath))); - return myLocation.getLocalPath(fullPath, detector, myVcs); + final FilePath localPath = myLocation.getLocalPath(fullPath, detector, myVcs); + if (localPath == null) { + return VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, detector.fun(new File(fullPath))); + } + return localPath; } private long getRevision(final boolean isBeforeRevision) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index 7b78afe63ce3..a771a6866dda 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -182,6 +182,8 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi throws VcsException { try { final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location; + final String path = myVcs.getSvnFileUrlMapping().getLocalPath(((SvnRepositoryLocation)location).getURL()); + final boolean isRemote = path == null; final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); if (progress != null) { progress.setText(SvnBundle.message("progress.text.changes.collecting.changes")); @@ -206,7 +208,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer() { public void consume(final SVNLogEntry svnLogEntry) { - final SvnChangeList cl = new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot); + final SvnChangeList cl = new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot, isRemote); if (filter.accepts(cl)) { consumer.consume(cl); }