From e4dbca8a776eb989f02572d7ca71a02e94019970 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 12 May 2015 14:10:58 +0300 Subject: [PATCH 01/17] IDEA-135191 Incremental search on a non-project triggers 'Non-project files access' dialog when it shouldn't Reapplied original fix for IDEA-113468, while allowing some custom typing handlers to run outside of command/write action scope. --- .../editorActions/TypedHandler.java | 4 - .../lookup/impl/LookupTypedHandler.java | 3 +- .../navigation/IncrementalSearchHandler.java | 2 +- .../editor/actionSystem/TypedAction.java | 103 +++++++++++------- 4 files changed, 67 insertions(+), 45 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java index a47175cd1cda..9b3cccc73f77 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -37,7 +37,6 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.fileTypes.LanguageFileType; @@ -143,9 +142,6 @@ public class TypedHandler extends TypedActionHandlerBase { } if (!CodeInsightUtilBase.prepareEditorForWrite(originalEditor)) return; - if (!FileDocumentManager.getInstance().requestWriting(originalEditor.getDocument(), project)) { - return; - } final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); final Document originalDocument = originalEditor.getDocument(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java index e84667ebd4d0..f96cb1a50cac 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupTypedHandler.java @@ -40,7 +40,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; import com.intellij.openapi.editor.actionSystem.TypedActionHandler; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -68,7 +67,7 @@ public class LookupTypedHandler extends TypedActionHandlerBase { return; } - if (!CodeInsightUtilBase.prepareEditorForWrite(originalEditor) || !FileDocumentManager.getInstance().requestWriting(originalEditor.getDocument(), project)) { + if (!CodeInsightUtilBase.prepareEditorForWrite(originalEditor)) { return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java index 0a3eb2f03831..6ae657a0221a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java @@ -92,7 +92,7 @@ public class IncrementalSearchHandler { EditorActionManager actionManager = EditorActionManager.getInstance(); TypedAction typedAction = actionManager.getTypedAction(); - typedAction.setupHandler(new MyTypedHandler(typedAction.getHandler())); + typedAction.setupRawHandler(new MyTypedHandler(typedAction.getRawHandler())); actionManager.setActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE, new BackSpaceHandler(actionManager.getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE))); actionManager.setActionHandler(IdeActions.ACTION_EDITOR_MOVE_CARET_UP, new UpHandler(actionManager.getActionHandler(IdeActions.ACTION_EDITOR_MOVE_CARET_UP))); diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java index 98d83656b580..ee2445f75031 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java @@ -23,7 +23,6 @@ import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.editor.*; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,11 +32,14 @@ import org.jetbrains.annotations.Nullable; * @see EditorActionManager#getTypedAction() */ public class TypedAction { + @NotNull + private TypedActionHandler myRawHandler; private TypedActionHandler myHandler; private boolean myHandlersLoaded; public TypedAction() { myHandler = new Handler(); + myRawHandler = new DefaultRawHandler(); } private void ensureHandlersLoaded() { @@ -55,11 +57,6 @@ public class TypedAction { if (editor.isViewer()) return; Document doc = editor.getDocument(); - Project project = CommonDataKeys.PROJECT.getData(dataContext); - if (!FileDocumentManager.getInstance().requestWriting(doc, project)) { - return; - } - doc.startGuardedBlockChecking(); try { final String str = String.valueOf(charTyped); @@ -99,43 +96,73 @@ public class TypedAction { return tmp; } - public final void actionPerformed(@Nullable final Editor editor, final char charTyped, final DataContext dataContext) { - if (editor == null) return; - - Runnable command = new TypingCommand(editor, charTyped, dataContext); - - CommandProcessor.getInstance().executeCommand(CommonDataKeys.PROJECT.getData(dataContext), command, "", editor.getDocument(), UndoConfirmationPolicy.DEFAULT, editor.getDocument()); + /** + * Gets the current 'raw' typing handler. + * + * @see #setupRawHandler(TypedActionHandler) + */ + @NotNull + public TypedActionHandler getRawHandler() { + return myRawHandler; } - private class TypingCommand implements Runnable { - private final Editor myEditor; - private final char myCharTyped; - private final DataContext myDataContext; - - public TypingCommand(Editor editor, char charTyped, DataContext dataContext) { - myEditor = editor; - myCharTyped = charTyped; - myDataContext = dataContext; - } + /** + * Replaces current 'raw' typing handler with the specified handler. The handler should pass unprocessed typing to the + * previously registered 'raw' handler. + *

+ * 'Raw' handler is a handler directly invoked by the code which handles typing in editor. Default 'raw' handler + * performs some generic logic that has to be done on typing (like checking whether file has write access, creating a command + * instance for undo subsystem, initiating write action, etc), but delegates to 'normal' handler for actual typing logic. + * + * @param handler the handler to set. + * @return the previously registered handler. + * + * @see #getRawHandler() + * @see #getHandler() + * @see #setupHandler(TypedActionHandler) + */ + @NotNull + public TypedActionHandler setupRawHandler(@NotNull TypedActionHandler handler) { + TypedActionHandler tmp = myRawHandler; + myRawHandler = handler; + return tmp; + } + public final void actionPerformed(@Nullable final Editor editor, final char charTyped, final DataContext dataContext) { + if (editor == null) return; + myRawHandler.execute(editor, charTyped, dataContext); + } + + private class DefaultRawHandler implements TypedActionHandler { @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(myEditor.getDocument(), myEditor.getProject()) { - @Override - public void run() { - Document doc = myEditor.getDocument(); - doc.startGuardedBlockChecking(); - try { - getHandler().execute(myEditor, myCharTyped, myDataContext); + public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext dataContext) { + CommandProcessor.getInstance().executeCommand( + CommonDataKeys.PROJECT.getData(dataContext), + new Runnable() { + @Override + public void run() { + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), editor.getProject())) { + return; + } + ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(editor.getDocument(), editor.getProject()) { + @Override + public void run() { + Document doc = editor.getDocument(); + doc.startGuardedBlockChecking(); + try { + getHandler().execute(editor, charTyped, dataContext); + } + catch (ReadOnlyFragmentModificationException e) { + EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e); + } + finally { + doc.stopGuardedBlockChecking(); + } + } + }); } - catch (ReadOnlyFragmentModificationException e) { - EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e); - } - finally { - doc.stopGuardedBlockChecking(); - } - } - }); + }, + "", editor.getDocument(), UndoConfirmationPolicy.DEFAULT, editor.getDocument()); } } } From 7b3f8556829dbc5b802912ffbbb4c702c94372d9 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Tue, 12 May 2015 14:30:36 +0300 Subject: [PATCH 02/17] Align debugger "tab" headers to the left. --- .../execution/ui/layout/impl/GridCellImpl.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index 43a54661ac57..dea14877f2eb 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -35,6 +35,7 @@ import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsListener; import com.intellij.ui.tabs.UiDecorator; import com.intellij.ui.tabs.impl.JBEditorTabs; +import com.intellij.ui.tabs.impl.TabLabel; import com.intellij.ui.tabs.impl.singleRow.ScrollableSingleRowLayout; import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout; import com.intellij.util.containers.HashSet; @@ -114,6 +115,16 @@ public class GridCellImpl implements GridCell { public void resetDropOver(TabInfo tabInfo) { ((RunnerContentUi)myContext).myTabs.resetDropOver(tabInfo); } + + @Override + protected TabLabel createTabLabel(TabInfo info) { + return new TabLabel(this, info) { + @Override + public void setAlignmentToCenter(boolean toCenter) { + super.setAlignmentToCenter(false); + } + }; + } }.setDataProvider(new DataProvider() { @Override @Nullable From ea91cd6ddaebb476a2c336c3081c6441e49071eb Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 12 May 2015 13:38:23 +0200 Subject: [PATCH 03/17] clear cached version data for java SDK if libraries under SDK home are updated --- .../projectRoots/impl/JavaSdkImpl.java | 38 +++++- .../impl/ProjectJdkTableImpl.java | 125 ++++++++++++++---- .../projectRoots/impl/ProjectJdkImpl.java | 7 +- 3 files changed, 139 insertions(+), 31 deletions(-) diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index fc35e56c78b2..a6a940e401cc 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -23,6 +23,8 @@ import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.AnnotationOrderRootType; @@ -62,8 +64,40 @@ public class JavaSdkImpl extends JavaSdk { private static final String JAVA_VERSION_PREFIX = "java version "; private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; - public JavaSdkImpl() { + public JavaSdkImpl(final VirtualFileManager fileManager, final FileTypeManager fileTypeManager) { super("JavaSDK"); + + fileManager.addVirtualFileListener(new VirtualFileAdapter() { + + public void fileDeleted(@NotNull VirtualFileEvent event) { + updateCache(event); + } + + @Override + public void contentsChanged(@NotNull VirtualFileEvent event) { + updateCache(event); + } + + @Override + public void fileCreated(@NotNull VirtualFileEvent event) { + updateCache(event); + } + + private void updateCache(VirtualFileEvent event) { + final VirtualFile file = event.getFile(); + if (FileTypes.ARCHIVE.equals(fileTypeManager.getFileTypeByFileName(event.getFileName()))) { + final String filePath = file.getPath(); + synchronized (myCachedVersionStrings) { + for (String sdkHome : myCachedVersionStrings.keySet()) { + if (FileUtil.isAncestor(sdkHome, filePath, false)) { + myCachedVersionStrings.remove(sdkHome); + break; + } + } + } + } + } + }); } @Override @@ -428,7 +462,7 @@ public class JavaSdkImpl extends JavaSdk { modificator.addRoot(root, annoType); } - private final Map myCachedVersionStrings = new HashMap(); + private final Map myCachedVersionStrings = Collections.synchronizedMap(new HashMap()); @Override public final String getVersionString(String sdkHome) { diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java index 0b7e0bc449c4..28a074a7743a 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java @@ -26,8 +26,16 @@ import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; -import com.intellij.openapi.vfs.*; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.util.containers.SmartHashSet; import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.impl.MessageListenerList; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -35,10 +43,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @State( name = "ProjectJdkTable", @@ -60,38 +65,102 @@ public class ProjectJdkTableImpl extends ProjectJdkTable implements ExportableCo myMessageBus = ApplicationManager.getApplication().getMessageBus(); myListenerList = new MessageListenerList(myMessageBus, JDK_TABLE_TOPIC); // support external changes to jdk libraries (Endorsed Standards Override) - VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { + final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); + connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { private FileTypeManager myFileTypeManager = FileTypeManager.getInstance(); - @Override - public void fileCreated(@NotNull VirtualFileEvent event) { - updateJdks(event.getFile()); + public void before(@NotNull List events) { } - private void updateJdks(VirtualFile file) { - if (file.isDirectory() || - // avoid calling getFileType() because it will try to detect file type from content for unknown/text file types - !FileTypes.ARCHIVE.equals(myFileTypeManager.getFileTypeByFileName(file.getName()))) { - // consider only archive files that may contain libraries - return; - } - for (Sdk sdk : mySdks) { - final SdkType sdkType = (SdkType)sdk.getSdkType(); - if (!(sdkType instanceof JavaSdkType)) { - continue; + public void after(@NotNull List events) { + if (!events.isEmpty()) { + final Set affected = new SmartHashSet(); + for (VFileEvent event : events) { + addAffectedJavaSdk(event, affected); } - final VirtualFile home = sdk.getHomeDirectory(); - if (home == null) { - continue; - } - if (VfsUtilCore.isAncestor(home, file, true)) { - sdkType.setupSdkPaths(sdk); - // no need to iterate further assuming the file cannot be under the home of several SDKs - break; + if (!affected.isEmpty()) { + for (Sdk sdk : affected) { + ((SdkType)sdk.getSdkType()).setupSdkPaths(sdk); + } } } } + + private void addAffectedJavaSdk(VFileEvent event, Set affected) { + final VirtualFile file = event.getFile(); + String fileName = null; + if (file != null && file.isValid()) { + if (file.isDirectory()) { + return; + } + fileName = file.getName(); + } + final String eventPath = event.getPath(); + if (fileName == null) { + fileName = VfsUtil.extractFileName(eventPath); + } + if (fileName != null) { + // avoid calling getFileType() because it will try to detect file type from content for unknown/text file types + // consider only archive files that may contain libraries + if (!FileTypes.ARCHIVE.equals(myFileTypeManager.getFileTypeByFileName(fileName))) { + return; + } + } + + for (Sdk sdk : mySdks) { + if (sdk.getSdkType() instanceof JavaSdkType && !affected.contains(sdk)) { + final String homePath = sdk.getHomePath(); + if (!StringUtil.isEmpty(homePath) && FileUtil.isAncestor(homePath, eventPath, true)) { + affected.add(sdk); + // no need to iterate further assuming the file cannot be under the home of several SDKs + break; + } + } + } + } + }); + //VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { + // private FileTypeManager myFileTypeManager = FileTypeManager.getInstance(); + // + // public void fileDeleted(@NotNull VirtualFileEvent event) { + // updateJdks(event.getFile()); + // } + // + // @Override + // public void contentsChanged(@NotNull VirtualFileEvent event) { + // updateJdks(event.getFile()); + // } + // + // @Override + // public void fileCreated(@NotNull VirtualFileEvent event) { + // updateJdks(event.getFile()); + // } + // + // private void updateJdks(VirtualFile file) { + // if (file.isDirectory() || + // // avoid calling getFileType() because it will try to detect file type from content for unknown/text file types + // !FileTypes.ARCHIVE.equals(myFileTypeManager.getFileTypeByFileName(file.getName()))) { + // // consider only archive files that may contain libraries + // return; + // } + // for (Sdk sdk : mySdks) { + // final SdkType sdkType = (SdkType)sdk.getSdkType(); + // if (!(sdkType instanceof JavaSdkType)) { + // continue; + // } + // final VirtualFile home = sdk.getHomeDirectory(); + // if (home == null) { + // continue; + // } + // if (VfsUtilCore.isAncestor(home, file, true)) { + // sdkType.setupSdkPaths(sdk); + // // no need to iterate further assuming the file cannot be under the home of several SDKs + // break; + // } + // } + // } + //}); } @Override diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java index 2f8f22913b9a..e47c19e27829 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkImpl.java @@ -389,7 +389,12 @@ public class ProjectJdkImpl extends UserDataHolderBase implements JDOMExternaliz } public void update() { - myRootContainer.update(); + try { + myRootContainer.update(); + } + finally { + resetVersionString(); + } } @Override From e60549c39d7aa9f850f535f0d9857a3d82862e4b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 12 May 2015 13:41:24 +0200 Subject: [PATCH 04/17] remove commented code --- .../impl/ProjectJdkTableImpl.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java index 28a074a7743a..af1500d8fc5c 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/ProjectJdkTableImpl.java @@ -120,47 +120,6 @@ public class ProjectJdkTableImpl extends ProjectJdkTable implements ExportableCo } }); - //VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { - // private FileTypeManager myFileTypeManager = FileTypeManager.getInstance(); - // - // public void fileDeleted(@NotNull VirtualFileEvent event) { - // updateJdks(event.getFile()); - // } - // - // @Override - // public void contentsChanged(@NotNull VirtualFileEvent event) { - // updateJdks(event.getFile()); - // } - // - // @Override - // public void fileCreated(@NotNull VirtualFileEvent event) { - // updateJdks(event.getFile()); - // } - // - // private void updateJdks(VirtualFile file) { - // if (file.isDirectory() || - // // avoid calling getFileType() because it will try to detect file type from content for unknown/text file types - // !FileTypes.ARCHIVE.equals(myFileTypeManager.getFileTypeByFileName(file.getName()))) { - // // consider only archive files that may contain libraries - // return; - // } - // for (Sdk sdk : mySdks) { - // final SdkType sdkType = (SdkType)sdk.getSdkType(); - // if (!(sdkType instanceof JavaSdkType)) { - // continue; - // } - // final VirtualFile home = sdk.getHomeDirectory(); - // if (home == null) { - // continue; - // } - // if (VfsUtilCore.isAncestor(home, file, true)) { - // sdkType.setupSdkPaths(sdk); - // // no need to iterate further assuming the file cannot be under the home of several SDKs - // break; - // } - // } - // } - //}); } @Override From c28dafab31a861962f51d45dacd0ea0162a30292 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 12 May 2015 14:49:07 +0300 Subject: [PATCH 05/17] IDEA-139903 Add test to check extraction of card's board-local number --- .../tasks/integration/live/TrelloIntegrationTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java index d9150d342ce2..8ad9d30c059b 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java @@ -33,6 +33,7 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase objects, @NotNull String... names) { assertEquals(message, ContainerUtil.newHashSet(names), ContainerUtil.map2Set(objects, new Function() { @Override From 4094cc0620d1c1aa87aa41c5cbed6d4dcbc36883 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 12 May 2015 15:26:32 +0300 Subject: [PATCH 06/17] diff: javadoc --- .../diff/util/BackgroundTaskUtil.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/util/BackgroundTaskUtil.java b/platform/diff-impl/src/com/intellij/diff/util/BackgroundTaskUtil.java index 9cf267a06075..37493c5db27a 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/BackgroundTaskUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/BackgroundTaskUtil.java @@ -30,13 +30,24 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -/* - * Executor to perform long operations on pooled thread - * Is is used to reduce blinking, in case of fast end of background task. - */ public class BackgroundTaskUtil { private static final Runnable TOO_SLOW_OPERATION = new EmptyRunnable(); + /* + * Executor to perform long operations on pooled thread + * It can be used to reduce blinking if background task completed fast. In this case callback will be called without invokeLater(). + * + * Simple approach: + * + * onSlowAction.run() // show "Loading..." + * executeOnPooledThread({ + * Runnable callback = backgroundTask(); // some background computations + * invokeLater(callback); // apply changes + * }); + * + * will lead to "Loading..." visible between current moment and execution of invokeLater() event. + * This period can be very short and looks like 'jumping' if background operation is fast. + */ @CalledInAwt @NotNull public static ProgressIndicator executeAndTryWait(@NotNull final Function backgroundTask, From e475fefbdaf91aa8c621f684d5c70dd7819c74a8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 12 May 2015 15:26:32 +0300 Subject: [PATCH 07/17] EA-68328 - IAE: AbstractPopup.showInCenterOf --- .../src/com/intellij/ide/actions/Switcher.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 5ca9f2e3036a..131f11bb18f0 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -45,6 +45,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.impl.ToolWindowImpl; import com.intellij.openapi.wm.impl.ToolWindowManagerImpl; import com.intellij.ui.*; @@ -584,7 +585,10 @@ public class Switcher extends AnAction implements DumbAware { } }.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup); - final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); + Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); + if (window == null) { + window = WindowManager.getInstance().getFrame(project); + } myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myPopup); myPopup.showInCenterOf(window); } From acaa3e2e2db5a753b8b9ea905648357fb177e311 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 12 May 2015 14:54:47 +0200 Subject: [PATCH 08/17] new Spacer colors for Darcula --- .../src/com/intellij/uiDesigner/DesignSpacer.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/DesignSpacer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/DesignSpacer.java index 42cc9b8e6f66..c7c0844da74d 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/DesignSpacer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/DesignSpacer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ */ package com.intellij.uiDesigner; +import com.intellij.ui.Gray; +import com.intellij.ui.JBColor; import com.intellij.uiDesigner.core.Spacer; import java.awt.*; @@ -32,7 +34,7 @@ abstract class DesignSpacer extends Spacer{ protected static final int SPRING_PRERIOD = 4; - protected static final Color ourColor1 = new Color(8,8,108); - protected static final Color ourColor2 = new Color(3,26,142); - protected static final Color ourColor3 = Color.BLACK; + protected static final Color ourColor1 = new JBColor(new Color(8,8,108), Gray._168); + protected static final Color ourColor2 = new JBColor(new Color(3, 26, 142), Gray._128); + protected static final Color ourColor3 = new JBColor(Gray._0, Gray._128); } From 4d5c3e1105246bdc026ad7e8b4a130da44cdb7ba Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 12 May 2015 14:37:29 +0300 Subject: [PATCH 09/17] IDEABKL-5810 Editing of RTL languages (Arabic, Hebrew) is not supported * allow to disable RTL in new rendering code --- .../src/com/intellij/openapi/editor/impl/view/LineLayout.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java index 0eca68c8d9e1..daf98719bd2c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/LineLayout.java @@ -18,6 +18,7 @@ package com.intellij.openapi.editor.impl.view; import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; import com.intellij.openapi.editor.impl.EditorImpl; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.text.CharArrayUtil; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NotNull; @@ -109,6 +110,7 @@ class LineLayout { } private static List createRuns(char[] text) { + if (Registry.is("editor.disable.rtl")) return Collections.singletonList(new BidiRun((byte)0, 0, text.length)); Bidi bidi = new Bidi(text, 0, null, 0, text.length, Bidi.DIRECTION_LEFT_TO_RIGHT); int runCount = bidi.getRunCount(); List runs = new ArrayList(runCount); From 3e5fd2169390e4317007be62b5e17d9133862316 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 12 May 2015 16:02:54 +0300 Subject: [PATCH 10/17] IDEABKL-5810 Editing of RTL languages (Arabic, Hebrew) is not supported * fix display of glyph vector fragments on Mac --- .../editor/impl/view/TextFragment.java | 229 +++--------------- 1 file changed, 35 insertions(+), 194 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/TextFragment.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/TextFragment.java index 85db14f14b32..3324349040ac 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/TextFragment.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/TextFragment.java @@ -19,17 +19,16 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; import java.awt.font.FontRenderContext; -import java.awt.font.GlyphJustificationInfo; -import java.awt.font.GlyphMetrics; import java.awt.font.GlyphVector; -import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; /** * Fragment of text using a common font */ class TextFragment implements LineFragment { + // glyph location that should definitely be outside of painted region + private static final Point NOWHERE = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); + @NotNull private final GlyphVector myGlyphVector; @NotNull @@ -78,18 +77,42 @@ class TextFragment implements LineFragment { assert startOffset >= 0; assert endOffset <= myCharPositions.length; assert startOffset < endOffset; - GlyphVector vector; if (startOffset == 0 && endOffset == myCharPositions.length) { - vector = myGlyphVector; + g.drawGlyphVector(myGlyphVector, x, y); } else { - boolean isRtl = isRtl(); - vector = new GlyphVectorWindow(myGlyphVector, - isRtl ? myCharPositions.length - endOffset : startOffset, - isRtl ? myCharPositions.length - startOffset : endOffset, - getX(startOffset)); + // We cannot use our own GlyphVector implementation, as it wouldn't support + // Mac-specific automatic font fallback (negative glyph indices will be rejected, + // even though they are used inside StandardGlyphVector in that case). + // We also cannot clone myGlyphVector without casting to sun.font.StandardGlyphVector, + // as clone() method is not public in GlyphVector (even though it's Cloneable). + // So we are modifying glyph positions in-place, and restore them after painting. + int logicalStartOffset = isRtl() ? myCharPositions.length - endOffset : startOffset; + int logicalEndOffset = isRtl() ? myCharPositions.length - startOffset : endOffset; + int glyphCount = myGlyphVector.getNumGlyphs(); + Point2D[] savedPositions = new Point2D[glyphCount + 1]; + int lastPaintedGlyph = -1; + for (int i = 0; i < glyphCount; i++) { + savedPositions[i] = myGlyphVector.getGlyphPosition(i); + int c = myGlyphVector.getGlyphCharIndex(i); + if (c >= logicalStartOffset && c < logicalEndOffset) { + lastPaintedGlyph = i; + } + else { + myGlyphVector.setGlyphPosition(i, NOWHERE); + } + } + savedPositions[glyphCount] = myGlyphVector.getGlyphPosition(glyphCount); + myGlyphVector.setGlyphPosition(glyphCount, savedPositions[lastPaintedGlyph + 1]); + try { + g.drawGlyphVector(myGlyphVector, x - getX(startOffset), y); + } + finally { + for (int i = 0; i <= glyphCount; i++) { + myGlyphVector.setGlyphPosition(i, savedPositions[i]); + } + } } - g.drawGlyphVector(vector, x, y); } private boolean isRtl() { @@ -144,188 +167,6 @@ class TextFragment implements LineFragment { return startX + getX(column); } - /** - * GlyphVector that represents a portion of another (previously laid out) GlyphVector - */ - private static class GlyphVectorWindow extends GlyphVector { - private final GlyphVector myDelegate; - private final int[] myGlyphMap; - private final int myStartChar; - private final float myStartX; - - GlyphVectorWindow(@NotNull GlyphVector delegate, int startOffset, int endOffset, float startX) { - myDelegate = delegate; - myStartChar = startOffset; - myStartX = startX; - - int glyphCount = 0; - for (int i = 0; i < delegate.getNumGlyphs(); i++) { - int c = delegate.getGlyphCharIndex(i); - if (c >= startOffset && c < endOffset) { - glyphCount++; - } - } - - assert glyphCount > 0; - - myGlyphMap = new int[glyphCount]; - int p = 0; - for (int i = 0; i < delegate.getNumGlyphs(); i++) { - int c = delegate.getGlyphCharIndex(i); - if (c >= startOffset && c < endOffset) { - myGlyphMap[p++] = i; - } - } - } - - @Override - public Font getFont() { - return myDelegate.getFont(); - } - - @Override - public FontRenderContext getFontRenderContext() { - return myDelegate.getFontRenderContext(); - } - - @Override - public int getNumGlyphs() { - return myGlyphMap.length; - } - - @Override - public int getGlyphCode(int glyphIndex) { - return myDelegate.getGlyphCode(myGlyphMap[glyphIndex]); - } - - @Override - public int[] getGlyphCodes(int beginGlyphIndex, int numEntries, int[] codeReturn) { - if (codeReturn == null) { - codeReturn = new int[numEntries]; - } - for (int i = 0; i < numEntries; i++) { - codeReturn[i] = myDelegate.getGlyphCode(myGlyphMap[beginGlyphIndex + i]); - } - return codeReturn; - } - - @Override - public int getLayoutFlags() { - return myDelegate.getLayoutFlags() | FLAG_HAS_POSITION_ADJUSTMENTS; - } - - @Override - public int getGlyphCharIndex(int glyphIndex) { - return myDelegate.getGlyphCharIndex(myGlyphMap[glyphIndex]) - myStartChar; - } - - @Override - public int[] getGlyphCharIndices(int beginGlyphIndex, int numEntries, int[] codeReturn) { - if (codeReturn == null) { - codeReturn = new int[numEntries]; - } - for (int i = 0; i < numEntries; i++) { - codeReturn[i] = myDelegate.getGlyphCharIndex(myGlyphMap[beginGlyphIndex + i]) - myStartChar; - } - return codeReturn; - } - - @Override - public Point2D getGlyphPosition(int glyphIndex) { - Point2D.Float pos = (Point2D.Float) myDelegate.getGlyphPosition(glyphIndex < myGlyphMap.length ? - myGlyphMap[glyphIndex] : - myGlyphMap[glyphIndex - 1] + 1); - pos.x -= myStartX; - return pos; - } - - @Override - public float[] getGlyphPositions(int beginGlyphIndex, int numEntries, float[] positionReturn) { - if (positionReturn == null) { - positionReturn = new float[numEntries * 2]; - } - for (int i = 0; i < numEntries; i++) { - int index = beginGlyphIndex + i; - int delegateIndex = index < myGlyphMap.length ? myGlyphMap[index] : myGlyphMap[index - 1] + 1; - Point2D.Float pos = (Point2D.Float) myDelegate.getGlyphPosition(delegateIndex); - positionReturn[i * 2] = pos.x - myStartX; - positionReturn[i * 2 + 1] = pos.y; - } - return positionReturn; - } - - @Override - public AffineTransform getGlyphTransform(int glyphIndex) { - return myDelegate.getGlyphTransform(myGlyphMap[glyphIndex]); - } - - @Override - public void performDefaultLayout() { - throw new UnsupportedOperationException(); - } - - @Override - public Rectangle2D getLogicalBounds() { - throw new UnsupportedOperationException(); - } - - @Override - public Rectangle2D getVisualBounds() { - throw new UnsupportedOperationException(); - } - - @Override - public Shape getOutline() { - throw new UnsupportedOperationException(); - } - - @Override - public Shape getOutline(float x, float y) { - throw new UnsupportedOperationException(); - } - - @Override - public Shape getGlyphOutline(int glyphIndex) { - throw new UnsupportedOperationException(); - } - - @Override - public void setGlyphPosition(int glyphIndex, Point2D newPos) { - throw new UnsupportedOperationException(); - } - - @Override - public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { - throw new UnsupportedOperationException(); - } - - @Override - public Shape getGlyphLogicalBounds(int glyphIndex) { - throw new UnsupportedOperationException(); - } - - @Override - public Shape getGlyphVisualBounds(int glyphIndex) { - throw new UnsupportedOperationException(); - } - - @Override - public GlyphMetrics getGlyphMetrics(int glyphIndex) { - throw new UnsupportedOperationException(); - } - - @Override - public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex) { - throw new UnsupportedOperationException(); - } - - @SuppressWarnings("CovariantEquals") - @Override - public boolean equals(GlyphVector set) { - throw new UnsupportedOperationException(); - } - } - private class TextFragmentWindow implements LineFragment { private final int myStartOffset; private final int myEndOffset; From 80ba0371d20c5bae7ad20eeaba7a52dd5de92622 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 12 May 2015 14:27:20 +0300 Subject: [PATCH 11/17] Fix NPE EA-68121: value can be null in customizeCellRenderer, mark it as Nullable --- .../src/com/intellij/ui/ColoredTableCellRenderer.java | 6 ++++-- plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ColoredTableCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredTableCellRenderer.java index bb242c703f9d..da7ddedf10f2 100644 --- a/platform/platform-api/src/com/intellij/ui/ColoredTableCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/ColoredTableCellRenderer.java @@ -16,6 +16,8 @@ package com.intellij.ui; +import org.jetbrains.annotations.Nullable; + import javax.swing.*; import javax.swing.table.TableCellRenderer; import java.awt.*; @@ -25,7 +27,7 @@ import java.awt.*; * @author Konstantin Bulenkov */ public abstract class ColoredTableCellRenderer extends SimpleColoredRenderer implements TableCellRenderer { - public final Component getTableCellRendererComponent(JTable table, Object value, + public final Component getTableCellRendererComponent(JTable table, @Nullable Object value, boolean isSelected, boolean hasFocus, int row, int col) { clear(); setPaintFocusBorder(hasFocus && table.getCellSelectionEnabled()); @@ -35,5 +37,5 @@ public abstract class ColoredTableCellRenderer extends SimpleColoredRenderer imp return this; } - protected abstract void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column); + protected abstract void customizeCellRenderer(JTable table, @Nullable Object value, boolean selected, boolean hasFocus, int row, int column); } diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java index fc66de87c9d7..b20c82f3c881 100644 --- a/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java +++ b/plugins/git4idea/src/git4idea/rebase/GitRebaseEditor.java @@ -89,8 +89,10 @@ public class GitRebaseEditor extends DialogWrapper implements DataProvider { myCommitsTable.setDefaultRenderer(String.class, new ColoredTableCellRenderer() { @Override protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { - append(value.toString()); - SpeedSearchUtil.applySpeedSearchHighlighting(myCommitsTable, this, true, selected); + if (value != null) { + append(value.toString()); + SpeedSearchUtil.applySpeedSearchHighlighting(myCommitsTable, this, true, selected); + } } }); From 412c994231e73b5aca3709d8283f07add63532eb Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 9 May 2015 12:08:12 +0300 Subject: [PATCH 12/17] [git] IDEA-140079 "Checkout revision" should try to checkout to detached HEAD --- .../git4idea/src/git4idea/GitTaskHandler.java | 2 +- .../actions/GitCheckoutRevisionAction.java | 2 +- .../src/git4idea/branch/GitBranchWorker.java | 6 +++--- .../src/git4idea/branch/GitBrancher.java | 11 +++++++---- .../src/git4idea/branch/GitBrancherImpl.java | 6 ++++-- .../branch/GitCheckoutNewBranchOperation.java | 2 +- .../git4idea/branch/GitCheckoutOperation.java | 19 +++++++++++++------ .../git4idea/src/git4idea/commands/Git.java | 6 +++++- .../src/git4idea/commands/GitImpl.java | 11 ++++++----- .../ui/branch/GitBranchPopupActions.java | 4 ++-- .../branch/GitBranchWorkerTest.groovy | 2 +- 11 files changed, 44 insertions(+), 27 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitTaskHandler.java b/plugins/git4idea/src/git4idea/GitTaskHandler.java index b6cf56abce0a..f96dd5a014a5 100644 --- a/plugins/git4idea/src/git4idea/GitTaskHandler.java +++ b/plugins/git4idea/src/git4idea/GitTaskHandler.java @@ -43,7 +43,7 @@ public class GitTaskHandler extends DvcsTaskHandler { @Override protected void checkout(@NotNull String taskName, @NotNull List repos, @Nullable Runnable callInAwtLater) { - myBrancher.checkout(taskName, repos, callInAwtLater); + myBrancher.checkout(taskName, false, repos, callInAwtLater); } @Override diff --git a/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java index e0dfc03a66c7..b7ca9e963b01 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCheckoutRevisionAction.java @@ -28,7 +28,7 @@ public class GitCheckoutRevisionAction extends GitLogSingleCommitAction { @Override protected void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit) { GitBrancher brancher = ServiceManager.getService(repository.getProject(), GitBrancher.class); - brancher.checkout(commit.getId().asString(), Collections.singletonList(repository), null); + brancher.checkout(commit.getId().asString(), false, Collections.singletonList(repository), null); } } diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java b/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java index bcf993b21723..67e8d2e5f8cc 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java +++ b/plugins/git4idea/src/git4idea/branch/GitBranchWorker.java @@ -92,12 +92,12 @@ public final class GitBranchWorker { public void checkoutNewBranchStartingFrom(@NotNull String newBranchName, @NotNull String startPoint, @NotNull List repositories) { updateInfo(repositories); - new GitCheckoutOperation(myProject, myFacade, myGit, myUiHandler, repositories, startPoint, newBranchName).execute(); + new GitCheckoutOperation(myProject, myFacade, myGit, myUiHandler, repositories, startPoint, false, newBranchName).execute(); } - public void checkout(@NotNull final String reference, @NotNull List repositories) { + public void checkout(@NotNull final String reference, boolean detach, @NotNull List repositories) { updateInfo(repositories); - new GitCheckoutOperation(myProject, myFacade, myGit, myUiHandler, repositories, reference, null).execute(); + new GitCheckoutOperation(myProject, myFacade, myGit, myUiHandler, repositories, reference, detach, null).execute(); } diff --git a/plugins/git4idea/src/git4idea/branch/GitBrancher.java b/plugins/git4idea/src/git4idea/branch/GitBrancher.java index 922b643fad4d..80cea7e3ee89 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBrancher.java +++ b/plugins/git4idea/src/git4idea/branch/GitBrancher.java @@ -60,18 +60,21 @@ public interface GitBrancher { * If local changes prevent the checkout, shows the list of them and proposes to make a "smart checkout": * stash-checkout-unstash.

*

Doesn't check the reference for validity.

- * * @param reference reference to be checked out. + * @param detach if true, checkout operation will put the repository into the detached HEAD state + * (useful if one wants to checkout a remote branch position, but not create a new tracking local branch); + * if false, it will behave the same as {@code git checkout} command does, i.e. switch to the local branch, + * create a local branch tracking the given remote branch, checkout hash or tag into the detached HEAD. * @param repositories repositories to operate on. * @param callInAwtLater the Runnable that should be called after execution of the method (both successful and unsuccessful). - * If given, it will be called in the EDT {@link javax.swing.SwingUtilities#invokeLater(Runnable) later}. + * If given, it will be called in the EDT {@link javax.swing.SwingUtilities#invokeLater(Runnable) later}. */ - void checkout(@NotNull String reference, @NotNull List repositories, @Nullable Runnable callInAwtLater); + void checkout(@NotNull String reference, boolean detach, @NotNull List repositories, @Nullable Runnable callInAwtLater); /** * Creates and checks out a new local branch starting from the given reference: * {@code git checkout -b }.
- * Provides the "smart checkout" procedure the same as in {@link #checkout(String, java.util.List, Runnable)}. + * Provides the "smart checkout" procedure the same as in {@link #checkout(String, boolean, List, Runnable)}. * * @param newBranchName the name of the new local branch. * @param startPoint the reference to checkout. diff --git a/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java b/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java index 5dcdea4aa994..a1be7b8fea0f 100644 --- a/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java +++ b/plugins/git4idea/src/git4idea/branch/GitBrancherImpl.java @@ -69,11 +69,13 @@ class GitBrancherImpl implements GitBrancher { } @Override - public void checkout(@NotNull final String reference, @NotNull final List repositories, + public void checkout(@NotNull final String reference, + final boolean detach, + @NotNull final List repositories, @Nullable Runnable callInAwtLater) { new CommonBackgroundTask(myProject, "Checking out " + reference, callInAwtLater) { @Override public void execute(@NotNull ProgressIndicator indicator) { - newWorker(indicator).checkout(reference, repositories); + newWorker(indicator).checkout(reference, detach, repositories); } }.runInBackground(); } diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java index cdc4f7711801..397ddf3e9b77 100644 --- a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java @@ -104,7 +104,7 @@ class GitCheckoutNewBranchOperation extends GitBranchOperation { GitCompoundResult deleteResult = new GitCompoundResult(myProject); Collection repositories = getSuccessfulRepositories(); for (GitRepository repository : repositories) { - GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true); + GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true, false); checkoutResult.append(repository, result); if (result.success()) { deleteResult.append(repository, myGit.branchDelete(repository, myNewBranchName, false)); diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java index 8327a614725c..0c7b44cd719c 100644 --- a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java @@ -52,13 +52,20 @@ class GitCheckoutOperation extends GitBranchOperation { public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to previous branch) not to let branches diverge."; @NotNull private final String myStartPointReference; + private final boolean myDetach; @Nullable private final String myNewBranch; - GitCheckoutOperation(@NotNull Project project, GitPlatformFacade facade, @NotNull Git git, @NotNull GitBranchUiHandler uiHandler, + GitCheckoutOperation(@NotNull Project project, + GitPlatformFacade facade, + @NotNull Git git, + @NotNull GitBranchUiHandler uiHandler, @NotNull Collection repositories, - @NotNull String startPointReference, @Nullable String newBranch) { + @NotNull String startPointReference, + boolean detach, + @Nullable String newBranch) { super(project, facade, git, uiHandler, repositories); myStartPointReference = startPointReference; + myDetach = detach; myNewBranch = newBranch; } @@ -78,8 +85,8 @@ class GitCheckoutOperation extends GitBranchOperation { GitUntrackedFilesOverwrittenByOperationDetector untrackedOverwrittenByCheckout = new GitUntrackedFilesOverwrittenByOperationDetector(root); - GitCommandResult result = myGit.checkout(repository, myStartPointReference, myNewBranch, false, - localChangesDetector, unmergedFiles, untrackedOverwrittenByCheckout); + GitCommandResult result = myGit.checkout(repository, myStartPointReference, myNewBranch, false, myDetach, + localChangesDetector, unmergedFiles, untrackedOverwrittenByCheckout); if (result.success()) { refresh(repository); markSuccessful(repository); @@ -171,7 +178,7 @@ class GitCheckoutOperation extends GitBranchOperation { GitCompoundResult checkoutResult = new GitCompoundResult(myProject); GitCompoundResult deleteResult = new GitCompoundResult(myProject); for (GitRepository repository : getSuccessfulRepositories()) { - GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true); + GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true, false); checkoutResult.append(repository, result); if (result.success() && myNewBranch != null) { /* @@ -235,7 +242,7 @@ class GitCheckoutOperation extends GitBranchOperation { @NotNull String reference, @Nullable String newBranch, boolean force) { GitCompoundResult compoundResult = new GitCompoundResult(myProject); for (GitRepository repository : repositories) { - compoundResult.append(repository, myGit.checkout(repository, reference, newBranch, force)); + compoundResult.append(repository, myGit.checkout(repository, reference, newBranch, force, myDetach)); } if (compoundResult.totalSuccess()) { return true; diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java index 5b7aca309edc..e23541338af8 100644 --- a/plugins/git4idea/src/git4idea/commands/Git.java +++ b/plugins/git4idea/src/git4idea/commands/Git.java @@ -77,7 +77,11 @@ public interface Git { @NotNull GitLineHandlerListener... listeners); @NotNull - GitCommandResult checkout(@NotNull GitRepository repository, @NotNull String reference, @Nullable String newBranch, boolean force, + GitCommandResult checkout(@NotNull GitRepository repository, + @NotNull String reference, + @Nullable String newBranch, + boolean force, + boolean detach, @NotNull GitLineHandlerListener... listeners); @NotNull diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 93ec7cde808b..e9da68d2e065 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -236,10 +236,11 @@ public class GitImpl implements Git { @NotNull @Override public GitCommandResult checkout(@NotNull GitRepository repository, - @NotNull String reference, - @Nullable String newBranch, - boolean force, - @NotNull GitLineHandlerListener... listeners) { + @NotNull String reference, + @Nullable String newBranch, + boolean force, + boolean detach, + @NotNull GitLineHandlerListener... listeners) { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.CHECKOUT); h.setSilent(false); h.setStdoutSuppressed(false); @@ -247,7 +248,7 @@ public class GitImpl implements Git { h.addParameters("--force"); } if (newBranch == null) { // simply checkout - h.addParameters(reference); + h.addParameters(detach ? reference + "^0" : reference); // we could use `--detach` here, but it is supported only since 1.7.5. } else { // checkout reference as new branch h.addParameters("-b", newBranch, reference); diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java index 68df0d8d79f7..6d6e6387fd0b 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java @@ -113,7 +113,7 @@ class GitBranchPopupActions { .showInputDialog(myProject, "Enter reference (branch, tag) name or commit hash", "Checkout", Messages.getQuestionIcon()); if (reference != null) { GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class); - brancher.checkout(reference, Collections.singletonList(myRepository), null); + brancher.checkout(reference, true, Collections.singletonList(myRepository), null); } } @@ -194,7 +194,7 @@ class GitBranchPopupActions { @Override public void actionPerformed(AnActionEvent e) { GitBrancher brancher = ServiceManager.getService(myProject, GitBrancher.class); - brancher.checkout(myBranchName, myRepositories, null); + brancher.checkout(myBranchName, false, myRepositories, null); } } diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy index 9a2bad2ad663..39b95a913caf 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy @@ -646,7 +646,7 @@ class GitBranchWorkerTest extends GitPlatformTest { def checkoutBranch(String name, def uiHandler) { GitBranchWorker brancher = new GitBranchWorker(myProject, myPlatformFacade, myGit, uiHandler as GitBranchUiHandler) - brancher.checkout(name, myRepositories) + brancher.checkout(name, false, myRepositories) } def mergeBranch(String name, def uiHandler) { From 4e5fb1c7b728d272826d3e93c90dbcdbf0776acb Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 12 May 2015 16:41:53 +0300 Subject: [PATCH 13/17] Moved ipython notebook configurable to the language settings --- python/ipnb/resources/META-INF/ipython-notebook.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ipnb/resources/META-INF/ipython-notebook.xml b/python/ipnb/resources/META-INF/ipython-notebook.xml index 498c9ab281d2..a508d381e352 100644 --- a/python/ipnb/resources/META-INF/ipython-notebook.xml +++ b/python/ipnb/resources/META-INF/ipython-notebook.xml @@ -8,7 +8,7 @@ - Date: Tue, 12 May 2015 16:24:25 +0300 Subject: [PATCH 14/17] EA-68429 - NPE: EditorView.getFoldRegionLayout allow null folding placeholder attributes in new editor rendering code --- .../com/intellij/openapi/editor/impl/view/EditorPainter.java | 4 +++- .../src/com/intellij/openapi/editor/impl/view/EditorView.java | 4 +++- .../openapi/editor/impl/view/VisualLineFragmentsIterator.java | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 08c0be633551..121711675c5c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -37,6 +37,7 @@ import com.intellij.ui.JBColor; import com.intellij.util.Processor; import com.intellij.util.ui.UIUtil; import gnu.trove.TFloatArrayList; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -283,7 +284,8 @@ class EditorPainter { } } - float paintLineLayoutWithEffect(Graphics2D g, LineLayout layout, float x, float y, Color effectColor, EffectType effectType) { + float paintLineLayoutWithEffect(Graphics2D g, LineLayout layout, float x, float y, + @Nullable Color effectColor, @Nullable EffectType effectType) { float initialX = x; for (LineLayout.VisualFragment fragment : layout.getFragmentsInVisualOrder(x)) { fragment.draw(g, x, y); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java index c7212d497702..2ddae167d1ec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorView.java @@ -299,7 +299,9 @@ public class EditorView implements Disposable { LineLayout getFoldRegionLayout(FoldRegion foldRegion) { LineLayout layout = foldRegion.getUserData(FOLD_REGION_TEXT_LAYOUT); if (layout == null) { - layout = new LineLayout(this, foldRegion.getPlaceholderText(), myEditor.getFoldingModel().getPlaceholderAttributes().getFontType(), + TextAttributes placeholderAttributes = myEditor.getFoldingModel().getPlaceholderAttributes(); + layout = new LineLayout(this, foldRegion.getPlaceholderText(), + placeholderAttributes == null ? Font.PLAIN : placeholderAttributes.getFontType(), myFontRenderContext); foldRegion.putUserData(FOLD_REGION_TEXT_LAYOUT, layout); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/VisualLineFragmentsIterator.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/VisualLineFragmentsIterator.java index 9340c473f275..9aec6168f619 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/VisualLineFragmentsIterator.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/VisualLineFragmentsIterator.java @@ -271,7 +271,9 @@ class VisualLineFragmentsIterator implements Iterator Date: Tue, 12 May 2015 16:54:40 +0300 Subject: [PATCH 15/17] [vcs-log] try to prevent index out of bounds from completely breaking the log --- .../intellij/vcs/log/ui/frame/VcsLogGraphTable.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index aababb1fa7b9..58f375df7c69 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -18,6 +18,7 @@ package com.intellij.vcs.log.ui.frame; import com.intellij.icons.AllIcons; import com.intellij.ide.CopyProvider; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.Pair; @@ -69,6 +70,7 @@ import java.util.*; import java.util.List; public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, CopyProvider { + private static final Logger LOG = Logger.getInstance(VcsLogGraphTable.class); public static final int ROOT_INDICATOR_COLORED_WIDTH = 8; public static final int ROOT_INDICATOR_WHITE_WIDTH = 5; @@ -336,9 +338,16 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C } private VcsLogHighlighter.VcsCommitStyle getStyle(int row, int column, String text, boolean hasFocus, final boolean selected) { - final RowInfo rowInfo = myDataPack.getVisibleGraph().getRowInfo(row); - Component dummyRendererComponent = myDummyRenderer.getTableCellRendererComponent(this, text, selected, hasFocus, row, column); + + VisibleGraph visibleGraph = myDataPack.getVisibleGraph(); + if (row < 0 || row >= visibleGraph.getVisibleCommitCount()) { + LOG.error("Visible graph has " + visibleGraph.getVisibleCommitCount() + " commits, yet we want row " + row); + return VcsCommitStyleFactory.createStyle(dummyRendererComponent.getForeground(), dummyRendererComponent.getBackground()); + } + + final RowInfo rowInfo = visibleGraph.getRowInfo(row); + VcsLogHighlighter.VcsCommitStyle defaultStyle = VcsCommitStyleFactory .createStyle(rowInfo.getRowType() == RowType.UNMATCHED ? JBColor.GRAY : dummyRendererComponent.getForeground(), dummyRendererComponent.getBackground()); From 3b2664e9722731607627f7a99b813922a7fc86ee Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 12 May 2015 17:01:29 +0300 Subject: [PATCH 16/17] assert fold region is valid in EditorCoordinateMapper --- .../openapi/editor/impl/view/EditorCoordinateMapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorCoordinateMapper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorCoordinateMapper.java index 96609539ada0..3c1b30befc2b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorCoordinateMapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorCoordinateMapper.java @@ -180,6 +180,7 @@ class EditorCoordinateMapper { FoldRegion outermostCollapsed = myFoldingModel.getCollapsedRegionAtOffset(offset); if (outermostCollapsed != null && offset > outermostCollapsed.getStartOffset()) { + assert outermostCollapsed.isValid(); offset = outermostCollapsed.getStartOffset(); } From e311604a5e61a565eae72ff6d7368855ff7d6715 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 12 May 2015 17:08:54 +0300 Subject: [PATCH 17/17] more changes to allow null folding placeholder attributes in new editor rendering code --- .../openapi/editor/impl/view/EditorPainter.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 121711675c5c..934b5cf3af63 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -260,8 +260,10 @@ class EditorPainter { @Override public void paint(Graphics2D g, VisualLineFragmentsIterator.Fragment fragment, int start, int end, TextAttributes attributes, float xStart, float xEnd, int y) { - g.setColor(attributes.getForegroundColor()); - fragment.draw(g, xStart, y, start, end); + if (attributes != null && attributes.getForegroundColor() != null) { + g.setColor(attributes.getForegroundColor()); + fragment.draw(g, xStart, y, start, end); + } if (fragment.getCurrentFoldRegion() == null) { int logicalLine = fragment.getStartLogicalLine(); if (logicalLine != currentLogicalLine[0]) { @@ -270,7 +272,7 @@ class EditorPainter { } paintWhitespace(g, text, xStart, y, start, end, whitespacePaintingStrategy, fragment); } - if (hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) { + if (attributes != null && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) { paintTextEffect(g, xStart, xEnd, y, attributes.getEffectColor(), attributes.getEffectType()); } } @@ -298,7 +300,7 @@ class EditorPainter { return x; } - private static boolean hasTextEffect(Color effectColor, EffectType effectType) { + private static boolean hasTextEffect(@Nullable Color effectColor, @Nullable EffectType effectType) { return effectColor != null && (effectType == EffectType.LINE_UNDERSCORE || effectType == EffectType.BOLD_LINE_UNDERSCORE || effectType == EffectType.BOLD_DOTTED_LINE ||