From 9bad2a3166a6522f0e2f55ee85309c40ab032065 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 16:12:59 +0100 Subject: [PATCH 01/45] check for element validity (EA-31878 - PIEAE: PsiElementBase.getContainingFile) --- .../lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java index 90e007945a3d..fbd6b1db7d5a 100644 --- a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java +++ b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java @@ -220,7 +220,8 @@ public class PsiCopyPasteManager { if (myElements == null || myElements.length == 0) { return null; } - return myElements [0].getProject(); + final PsiElement element = myElements[0]; + return element.isValid() ? element.getProject() : null; } } From c4805befb6cfdbd43c9cdd6bc1640f3542a3b405 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 17:04:48 +0100 Subject: [PATCH 02/45] probabilistic check to avoid 'module disposed' exception (EA-31889 - assert: ComponentManagerImpl.getComponent) --- .../intellij/uiDesigner/ErrorAnalyzer.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/ErrorAnalyzer.java b/plugins/ui-designer/src/com/intellij/uiDesigner/ErrorAnalyzer.java index 1a1987c1c942..8eef6609d08a 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/ErrorAnalyzer.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/ErrorAnalyzer.java @@ -80,22 +80,26 @@ public final class ErrorAnalyzer { @Nullable final GuiEditor editor, @NotNull final IRootContainer rootContainer, @Nullable final ProgressIndicator progress) { + if (module.isDisposed()) { + return; + } + // 1. Validate class to bind final String classToBind = rootContainer.getClassToBind(); final PsiClass psiClass; - if(classToBind != null){ + if (classToBind != null) { psiClass = FormEditingUtil.findClassToBind(module, classToBind); - if(psiClass == null){ + if (psiClass == null) { final QuickFix[] fixes = editor != null ? new QuickFix[]{new CreateClassToBindFix(editor, classToBind)} : QuickFix.EMPTY_ARRAY; final ErrorInfo errorInfo = new ErrorInfo(null, null, UIDesignerBundle.message("error.class.does.not.exist", classToBind), HighlightDisplayLevel.ERROR, fixes); rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, errorInfo); } - else{ + else { rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null); } } - else{ + else { rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null); psiClass = null; } @@ -116,13 +120,13 @@ public final class ErrorAnalyzer { final String binding = component.getBinding(); // a. Check that field exists and field is not static - if(psiClass != null && binding != null) { + if (psiClass != null && binding != null) { if (validateFieldInClass(component, binding, component.getComponentClassName(), psiClass, editor, module)) return true; } // b. Check that binding is unique if (binding != null) { - if(usedBindings.contains(binding)){ + if (usedBindings.contains(binding)) { // TODO[vova] implement component.putClientProperty( CLIENT_PROP_BINDING_ERROR, @@ -162,14 +166,14 @@ public final class ErrorAnalyzer { // Clear previous error (if any) component.putClientProperty(CLIENT_PROP_ERROR_ARRAY, null); - if(!(component instanceof IContainer)){ + if (!(component instanceof IContainer)) { return true; } final IContainer container = (IContainer)component; - if(container instanceof IRootContainer){ + if (container instanceof IRootContainer) { final IRootContainer rootContainer = (IRootContainer)container; - if(rootContainer.getComponentCount() > 1){ + if (rootContainer.getComponentCount() > 1) { // TODO[vova] implement putError(component, new ErrorInfo( component, null, UIDesignerBundle.message("error.multiple.toplevel.components"), @@ -178,13 +182,13 @@ public final class ErrorAnalyzer { )); } } - else if(container.isXY() && container.getComponentCount() > 0){ + else if (container.isXY() && container.getComponentCount() > 0) { // TODO[vova] implement putError(component, new ErrorInfo( - component, null, UIDesignerBundle.message("error.panel.not.laid.out"), - HighlightDisplayLevel.ERROR, - QuickFix.EMPTY_ARRAY - ) + component, null, UIDesignerBundle.message("error.panel.not.laid.out"), + HighlightDisplayLevel.ERROR, + QuickFix.EMPTY_ARRAY + ) ); } return true; @@ -199,14 +203,14 @@ public final class ErrorAnalyzer { if (formPsiFile != null && rootContainer instanceof RadRootContainer) { final List formInspectionTools = new ArrayList(); final FormInspectionTool[] registeredFormInspections = Extensions.getExtensions(FormInspectionTool.EP_NAME); - for(FormInspectionTool formInspectionTool: registeredFormInspections) { + for (FormInspectionTool formInspectionTool : registeredFormInspections) { if (formInspectionTool.isActive(formPsiFile) && !rootContainer.isInspectionSuppressed(formInspectionTool.getShortName(), null)) { formInspectionTools.add(formInspectionTool); } } if (formInspectionTools.size() > 0 && editor != null) { - for(FormInspectionTool tool: formInspectionTools) { + for (FormInspectionTool tool : formInspectionTools) { tool.startCheckForm(rootContainer); } FormEditingUtil.iterate( @@ -215,7 +219,7 @@ public final class ErrorAnalyzer { public boolean visit(final RadComponent component) { if (progress != null && progress.isCanceled()) return false; - for(FormInspectionTool tool: formInspectionTools) { + for (FormInspectionTool tool : formInspectionTools) { if (rootContainer.isInspectionSuppressed(tool.getShortName(), component.getId())) continue; ErrorInfo[] errorInfos = tool.checkComponent(editor, component); if (errorInfos != null) { @@ -231,7 +235,7 @@ public final class ErrorAnalyzer { } } ); - for(FormInspectionTool tool: formInspectionTools) { + for (FormInspectionTool tool : formInspectionTools) { tool.doneCheckForm(rootContainer); } } From ee533056f4327f29bd2059bc6386c7ff3a2fd93c Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 17:15:41 +0100 Subject: [PATCH 03/45] one more module disposed check (EA-31857 - assert: ComponentManagerImpl.getPicoContainer) --- .../componentTree/ComponentPtrDescriptor.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentPtrDescriptor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentPtrDescriptor.java index 5ec5045b6321..6db460c216dd 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentPtrDescriptor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentPtrDescriptor.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.uiDesigner.radComponents.RadComponent; import com.intellij.uiDesigner.radComponents.RadRootContainer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Anton Katilin @@ -39,9 +40,9 @@ final class ComponentPtrDescriptor extends NodeDescriptor { myPtr=ptr; } - public boolean update(){ + public boolean update() { myPtr.validate(); - if(!myPtr.isValid()){ + if(!myPtr.isValid()) { myPtr=null; return true; } @@ -49,7 +50,10 @@ final class ComponentPtrDescriptor extends NodeDescriptor { final String oldBinding = myBinding; final String oldTitle = myTitle; final RadComponent component = myPtr.getComponent(); - if(component instanceof RadRootContainer){ + if (component.getModule().isDisposed()) { + return false; + } + if(component instanceof RadRootContainer) { myBinding = ((RadRootContainer)component).getClassToBind(); } else{ @@ -59,6 +63,7 @@ final class ComponentPtrDescriptor extends NodeDescriptor { return !Comparing.equal(oldBinding,myBinding) || !Comparing.equal(oldTitle, myTitle); } + @Nullable public RadComponent getComponent() { return myPtr != null ? myPtr.getComponent() : null; } From b369406131090cb0d28fdc425c2e8527abd86fc1 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 17:17:30 +0100 Subject: [PATCH 04/45] more robust tree structure (EA-31852 - IAE: ComponentTreeStructure.getParentElement) --- .../componentTree/ComponentTreeStructure.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeStructure.java b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeStructure.java index a7b0d9124234..100bff453c98 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeStructure.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/componentTree/ComponentTreeStructure.java @@ -42,13 +42,8 @@ final class ComponentTreeStructure extends AbstractTreeStructure{ private final GuiEditor myEditor; public ComponentTreeStructure(@NotNull final GuiEditor editor){ - myRootElement=new Object() { - @Override - public String toString() { - return "root of component tree structure " + ComponentTreeStructure.this.toString(); - } - }; - myEditor=editor; + myRootElement = new ComponentTreeStructureRoot(); + myEditor = editor; } public Object getRootElement(){ @@ -107,7 +102,7 @@ final class ComponentTreeStructure extends AbstractTreeStructure{ } public Object getParentElement(final Object element){ - if(element==myRootElement){ + if (element instanceof ComponentTreeStructureRoot) { return null; } else if (element instanceof LwInspectionSuppression[] || element instanceof RadButtonGroup[]) { @@ -180,4 +175,11 @@ final class ComponentTreeStructure extends AbstractTreeStructure{ public boolean hasSomethingToCommit(){ return false; } + + private class ComponentTreeStructureRoot { + @Override + public String toString() { + return "root of component tree structure " + ComponentTreeStructure.this.toString(); + } + } } From dfbb20f81f1b214df19e9e72ec35f19ca80fdcb6 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 17:35:39 +0100 Subject: [PATCH 05/45] always update document text after preprocess enter handlers have been run (PY-5099) --- .../com/intellij/codeInsight/editorActions/EnterHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java index 0a2d1a911aa6..af0a29796c3b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java @@ -125,7 +125,6 @@ public class EnterHandler extends BaseEnterHandler { if (result == EnterHandlerDelegate.Result.Stop) return; if (result != EnterHandlerDelegate.Result.Continue) { - text = document.getCharsSequence(); if (result == EnterHandlerDelegate.Result.DefaultForceIndent) { forceIndent = true; } @@ -133,6 +132,7 @@ public class EnterHandler extends BaseEnterHandler { } } + text = document.getCharsSequence(); // update after changes done in preprocessEnter() caretOffset = caretOffsetRef.get().intValue(); boolean isFirstColumn = caretOffset == 0 || text.charAt(caretOffset - 1) == '\n'; final boolean insertSpace = From b3822d0459fd14a588a6f38b6b2b0a796f382133 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 22 Nov 2011 22:33:51 +0300 Subject: [PATCH 06/45] fix missing toolbar & current editor on dialect change/floating --- .../console/LanguageConsoleImpl.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index da5a75381f49..2e3ce267e113 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -180,9 +180,6 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { myPanel.removeAll(); myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER); myFullEditor = fileManager.openTextEditor(new OpenFileDescriptor(getProject(), virtualFile, 0), true); - configureFullEditor(); - setConsoleFilePinned(fileManager); - myHistoryViewer.setHorizontalScrollbarVisible(true); myCurrentEditor = myFullEditor; } @@ -201,7 +198,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { public void setFullEditorActions(ActionGroup actionGroup) { myFullEditorActions = actionGroup; - configureFullEditor(); + configureFullEditor(myFullEditor); } public void setShowSeparatorLine(boolean showSeparatorLine) { @@ -539,6 +536,11 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { for (FileEditor fileEditor : source.getAllEditors(file)) { if (!(fileEditor instanceof TextEditor)) continue; final Editor editor = ((TextEditor)fileEditor).getEditor(); + // todo what if it is splitted? + myCurrentEditor = editor; + myFullEditor = editor; + configureFullEditor(editor); + setConsoleFilePinned((FileEditorManagerEx)source); EmptyAction.registerActionShortcuts(editor.getComponent(), myConsoleEditor.getComponent()); editor.getCaretModel().addCaretListener(new CaretListener() { public void caretPositionChanged(CaretEvent e) { @@ -595,20 +597,18 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { } editorManager.closeFile(file); myFullEditor = editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor); - configureFullEditor(); - setConsoleFilePinned(editorManager); } } } - private void configureFullEditor() { - if (myFullEditor == null || myFullEditorActions == null) return; + private void configureFullEditor(final Editor editor) { + if (editor == null || myFullEditorActions == null) return; final JPanel header = new JPanel(new BorderLayout()); final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myFullEditorActions, true); - actionToolbar.setTargetComponent(myFullEditor.getContentComponent()); + actionToolbar.setTargetComponent(editor.getContentComponent()); header.add(actionToolbar.getComponent(), BorderLayout.EAST); - myFullEditor.setHeaderComponent(header); - myFullEditor.getSettings().setLineMarkerAreaShown(false); + editor.setHeaderComponent(header); + editor.getSettings().setLineMarkerAreaShown(false); } public void setInputText(final String query) { From 1fec64189f28845e84793c078a4a97b23cc56bae Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 22 Nov 2011 20:09:28 +0100 Subject: [PATCH 07/45] move favorites up --- .../lang-api/src/com/intellij/ide/StandardTargetWeights.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/ide/StandardTargetWeights.java b/platform/lang-api/src/com/intellij/ide/StandardTargetWeights.java index ca41ff18a1ef..5b5ee0d7138e 100644 --- a/platform/lang-api/src/com/intellij/ide/StandardTargetWeights.java +++ b/platform/lang-api/src/com/intellij/ide/StandardTargetWeights.java @@ -20,11 +20,11 @@ package com.intellij.ide; */ public interface StandardTargetWeights { float PROJECT_WEIGHT = 1; + float FAVORITES_WEIGHT = 1.01f; float PACKAGES_WEIGHT = 2; float J2EE_WEIGHT = 3; float STRUCTURE_WEIGHT = 4; float COMMANDER_WEIGHT = 5; - float FAVORITES_WEIGHT = 6; float SCOPE_WEIGHT = 6.5f; float NAV_BAR_WEIGHT = 8; float CHANGES_VIEW = 9; From 4beb1e26c7f969e6156bc4e84195bbf9036aca6d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 22 Nov 2011 20:10:19 +0100 Subject: [PATCH 08/45] + create button from AnAction --- .../src/com/intellij/ui/AnActionButton.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButton.java b/platform/platform-api/src/com/intellij/ui/AnActionButton.java index 98789eda843f..7ecf3b2af477 100644 --- a/platform/platform-api/src/com/intellij/ui/AnActionButton.java +++ b/platform/platform-api/src/com/intellij/ui/AnActionButton.java @@ -30,6 +30,7 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide private boolean myEnabled = true; private boolean myVisible = true; private ShortcutSet myShortcut; + private AnAction myAction = null; private JComponent myContextComponent; public AnActionButton(String text) { @@ -47,6 +48,29 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide public AnActionButton() { } + + public static AnActionButton fromAction(final AnAction action) { + final Presentation presentation = action.getTemplatePresentation(); + return new AnActionButton(presentation.getText(), + presentation.getDescription(), + presentation.getIcon()) { + + @Override + public void actionPerformed(AnActionEvent e) { + action.actionPerformed(e); + } + + @Override + public void updateButton(AnActionEvent e) { + action.update(e); + final boolean enabled = e.getPresentation().isEnabled(); + final boolean visible = e.getPresentation().isVisible(); + if (enabled && visible) { + super.updateButton(e); + } + } + }; + } public boolean isEnabled() { return myEnabled; @@ -66,9 +90,17 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide @Override public final void update(AnActionEvent e) { - final boolean enabled = isEnabled() && isContextComponentOk(); + boolean myActionVisible = true; + boolean myActionEnabled = true; + if (myAction != null) { + myAction.update(e); + myActionEnabled = myAction.getTemplatePresentation().isEnabled(); + myActionVisible = myAction.getTemplatePresentation().isVisible(); + } + final boolean enabled = isEnabled() && isContextComponentOk() && myActionEnabled; e.getPresentation().setEnabled(enabled); - e.getPresentation().setVisible(isVisible()); + e.getPresentation().setVisible(isVisible() && myActionVisible); + if (enabled) { updateButton(e); } From 300055eb1cb331fb528d509ed7793828f4c2dd4c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 22 Nov 2011 20:16:51 +0100 Subject: [PATCH 09/45] Select in target for favorites --- .../FavoritesTreeViewPanel.java | 11 ++- .../FavoritesViewSelectInTarget.java | 86 ++++++++++++++++--- .../src/META-INF/LangExtensions.xml | 1 + 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java index 5709b7b20026..9ebf5fd37f61 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java @@ -52,7 +52,11 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.*; -import com.intellij.util.*; +import com.intellij.ui.treeStructure.actions.CollapseAllAction; +import com.intellij.util.ArrayUtil; +import com.intellij.util.EditSourceOnDoubleClickHandler; +import com.intellij.util.EditSourceOnEnterKeyHandler; +import com.intellij.util.IconUtil; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -68,6 +72,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +/** + * @author anna + * @author Konstantin Bulenkov + */ public class FavoritesTreeViewPanel extends JPanel implements DataProvider { private final FavoritesTreeStructure myFavoritesTreeStructure; private FavoritesViewTreeBuilder myBuilder; @@ -167,6 +175,7 @@ public class FavoritesTreeViewPanel extends JPanel implements DataProvider { return CustomShortcutSet.fromString("DELETE"); } }) + .addExtraAction(AnActionButton.fromAction(new CollapseAllAction(myTree))) .setLineBorder(0, 0, 0, 0) .createPanel(); panel.setBorder(IdeBorderFactory.createEmptyBorder(0)); diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesViewSelectInTarget.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesViewSelectInTarget.java index aeae7191306c..ed52ffd3afee 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesViewSelectInTarget.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesViewSelectInTarget.java @@ -16,19 +16,26 @@ package com.intellij.ide.favoritesTreeView; -import com.intellij.ide.SelectInContext; import com.intellij.ide.SelectInManager; import com.intellij.ide.StandardTargetWeights; -import com.intellij.ide.impl.ProjectViewSelectInTarget; +import com.intellij.ide.impl.SelectInTargetPsiWrapper; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiFileSystemItem; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowId; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiUtilBase; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** - * User: anna - * Date: Feb 25, 2005 + * @author anna + * @author Konstantin Bulenkov */ -public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget { +public class FavoritesViewSelectInTarget extends SelectInTargetPsiWrapper { public FavoritesViewSelectInTarget(final Project project) { super(project); } @@ -37,8 +44,68 @@ public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget { return SelectInManager.FAVORITES; } + @Override + public String getToolWindowId() { + return SelectInManager.FAVORITES; + } + + @Override + protected void select(Object selector, VirtualFile virtualFile, boolean requestFocus) { + select(myProject, selector, null, null, virtualFile, requestFocus); + } + + @Override + protected void select(PsiElement element, boolean requestFocus) { + PsiElement toSelect = null; + if (element instanceof PsiFile || element instanceof PsiDirectory) { + toSelect = element; + } + else { + final PsiFile containingFile = element.getContainingFile(); + if (containingFile == null) return; + final FileViewProvider viewProvider = containingFile.getViewProvider(); + toSelect = viewProvider.getPsi(viewProvider.getBaseLanguage()); + } + if (toSelect == null) return; + PsiElement originalElement = toSelect.getOriginalElement(); + final VirtualFile virtualFile = PsiUtilBase.getVirtualFile(originalElement); + select(originalElement, virtualFile, requestFocus); + } + + public static ActionCallback select(@NotNull Project project, + final Object toSelect, + @Nullable final String viewId, + @Nullable final String subviewId, + final VirtualFile virtualFile, + final boolean requestFocus) { + final ActionCallback result = new ActionCallback(); + + ToolWindowManager windowManager=ToolWindowManager.getInstance(project); + final ToolWindow favoritesToolWindow = windowManager.getToolWindow(ToolWindowId.FAVORITES_VIEW); + + if (favoritesToolWindow != null) { + final FavoritesTreeViewPanel panel = UIUtil.findComponentOfType(favoritesToolWindow.getComponent(), FavoritesTreeViewPanel.class); + + if (panel != null) { + final Runnable runnable = new Runnable() { + public void run() { + panel.selectElement(toSelect, virtualFile, requestFocus); + result.setDone(); + } + }; + + if (requestFocus) { + favoritesToolWindow.activate(runnable, false); + } else { + favoritesToolWindow.show(runnable); + } + } + } + + return result; + } + protected boolean canSelect(final PsiFileSystemItem file) { - if (!super.canSelect(file)) return false; return findSuitableFavoritesList(file.getVirtualFile(), myProject, null) != null; } @@ -63,9 +130,4 @@ public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget { protected boolean canWorkWithCustomObjects() { return false; } - - public boolean isSubIdSelectable(String subId, SelectInContext context) { - final FavoritesManager favoritesManager = FavoritesManager.getInstance(myProject); - return favoritesManager.contains(subId, context.getVirtualFile()); - } } diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 2d846bb5d1b5..accdf885ecdd 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -457,6 +457,7 @@ + From 3a915e21c6097e00afa768ce29f3db22839472e7 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Nov 2011 11:09:53 +0100 Subject: [PATCH 10/45] @Nullable --- .../intellij/psi/impl/java/stubs/PsiMethodStub.java | 11 ++++++----- .../psi/impl/java/stubs/impl/PsiMethodStubImpl.java | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiMethodStub.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiMethodStub.java index 67ae992346a4..1e1099e31e5f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiMethodStub.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiMethodStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,22 +14,23 @@ * limitations under the License. */ -/* - * @author max - */ package com.intellij.psi.impl.java.stubs; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.cache.TypeInfo; import com.intellij.psi.stubs.NamedStub; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +/** + * @author max + */ public interface PsiMethodStub extends NamedStub { boolean isConstructor(); boolean isVarArgs(); boolean isAnnotationMethod(); - String getDefaultValueText(); + @Nullable String getDefaultValueText(); @NotNull TypeInfo getReturnTypeText(boolean doResolve); boolean isDeprecated(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java index 35dd68955db4..81420296c9dd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -174,8 +174,9 @@ public class PsiMethodStubImpl extends StubBase implements PsiMethodS builder.append(getName()).append(":").append(TypeInfo.createTypeText(getReturnTypeText(false))); - if (getDefaultValueText() != null) { - builder.append(" default=").append(getDefaultValueText()); + final String defaultValue = getDefaultValueText(); + if (defaultValue != null) { + builder.append(" default=").append(defaultValue); } builder.append("]"); From ac71fba0ebe360039710b61bb6c9670471235c4b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Nov 2011 17:52:16 +0100 Subject: [PATCH 11/45] API cleanup --- .../src/com/intellij/psi/impl/light/LightMethod.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java index bdd8d76a869a..8e997d680670 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java @@ -41,10 +41,6 @@ public class LightMethod extends LightElement implements PsiMethod { private final PsiMethod myMethod; private final PsiClass myContainingClass; - public LightMethod(PsiMethod method, PsiClass containingClass) { - this(method.getManager(), method, containingClass); - } - public LightMethod(PsiManager manager, PsiMethod method, PsiClass containingClass) { super(manager, JavaLanguage.INSTANCE); myMethod = method; From 965e972204be3916963b1704a158af74404a07c8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 22 Nov 2011 19:05:26 +0100 Subject: [PATCH 12/45] Light field --- .../intellij/psi/impl/light/LightField.java | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 java/java-impl/src/com/intellij/psi/impl/light/LightField.java diff --git a/java/java-impl/src/com/intellij/psi/impl/light/LightField.java b/java/java-impl/src/com/intellij/psi/impl/light/LightField.java new file mode 100644 index 000000000000..e337f7ae7cd2 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/light/LightField.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.light; + +import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.search.SearchScope; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LightField extends LightElement implements PsiField { + private final PsiField myField; + private final PsiClass myContainingClass; + + public LightField(@NotNull final PsiManager manager, @NotNull final PsiField field, @NotNull final PsiClass containingClass) { + super(manager, JavaLanguage.INSTANCE); + myField = field; + myContainingClass = containingClass; + } + + @Override + public void setInitializer(@Nullable final PsiExpression initializer) throws IncorrectOperationException { + throw new IncorrectOperationException("Not supported"); + } + + @NotNull + @Override + public SearchScope getUseScope() { + return myField.getUseScope(); + } + + @Override + public String getName() { + return myField.getName(); + } + + @NotNull + @Override + public PsiIdentifier getNameIdentifier() { + return myField.getNameIdentifier(); + } + + @Override + public PsiDocComment getDocComment() { + return myField.getDocComment(); + } + + @Override + public boolean isDeprecated() { + return myField.isDeprecated(); + } + + @Override + public PsiClass getContainingClass() { + return myContainingClass; + } + + @NotNull + @Override + public PsiType getType() { + return myField.getType(); + } + + @Override + public PsiTypeElement getTypeElement() { + return myField.getTypeElement(); + } + + @Override + public PsiExpression getInitializer() { + return myField.getInitializer(); + } + + @Override + public boolean hasInitializer() { + return myField.hasInitializer(); + } + + @Override + public void normalizeDeclaration() throws IncorrectOperationException { + throw new IncorrectOperationException("Not supported"); + } + + @Override + public Object computeConstantValue() { + return myField.computeConstantValue(); + } + + @Override + public PsiElement setName(@NonNls @NotNull final String name) throws IncorrectOperationException { + throw new IncorrectOperationException("Not supported"); + } + + @Override + public PsiType getTypeNoResolve() { + return myField.getTypeNoResolve(); + } + + @Override + public PsiModifierList getModifierList() { + return myField.getModifierList(); + } + + @Override + public boolean hasModifierProperty(@Modifier @NonNls @NotNull final String name) { + return myField.hasModifierProperty(name); + } + + @Override + public String getText() { + return myField.getText(); + } + + @Override + public PsiElement copy() { + return new LightField(myManager, (PsiField)myField.copy(), myContainingClass); + } + + @Override + public TextRange getTextRange() { + return new TextRange(-1, -1); + } + + @Override + public boolean isValid() { + return myContainingClass.isValid(); + } + + @Override + public String toString() { + return "PsiField:" + getName(); + } +} From 3092bcc50523c2528728bf73d0ea79ad909ffb79 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 22 Nov 2011 20:51:22 +0100 Subject: [PATCH 13/45] update digital signatures (IDEA-76295) --- bin/win/fsnotifier.exe | Bin 67280 -> 70216 bytes bin/win/vistalauncher.exe | Bin 62368 -> 63048 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/win/fsnotifier.exe b/bin/win/fsnotifier.exe index 0794f8cedaf28b3940e30a5b7517cc3466bdeca7..7aa103c7f9a206bdf6b2e7d7bf578d542ccf8de5 100644 GIT binary patch delta 5399 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 R8PV*mbyc0xX0b4&`5*3imFEBe diff --git a/bin/win/vistalauncher.exe b/bin/win/vistalauncher.exe index 7a24123f268cd958fc915aa489a62c8421c01ceb..e58dcb531179e7e17edf43c01cc13d03ca8c687a 100644 GIT binary patch delta 3366 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 From 8f64d212c08f8fa48ede7c54046447d2df671c96 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 22 Nov 2011 16:27:47 +0400 Subject: [PATCH 14/45] debugging anonymous and inner classes in script --- .../intellij/debugger/engine/JVMNameUtil.java | 10 ---- .../debugger/engine/PositionManagerImpl.java | 4 +- .../engine/TopLevelParentClassProvider.java | 47 +++++++++++++++++ plugins/groovy/src/META-INF/plugin.xml | 2 + .../debugger/GroovyCodeFragmentFactory.java | 10 ++-- .../GroovyTopLevelParentClassProvider.java | 51 +++++++++++++++++++ resources/src/META-INF/IdeaPlugin.xml | 1 + 7 files changed, 108 insertions(+), 17 deletions(-) create mode 100644 java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyTopLevelParentClassProvider.java diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java index e1a28f705d66..edee6bb76c6a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java @@ -426,14 +426,4 @@ public class JVMNameUtil { } return ""; } - - public static PsiClass getTopLevelParentClass(PsiClass psiClass) { - PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true); - while (enclosing != null) { - psiClass = enclosing; - enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true); - } - return psiClass; - } - } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index d52466171885..8d4638c3fc09 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -85,7 +85,7 @@ public class PositionManagerImpl implements PositionManager { } if (PsiUtil.isLocalOrAnonymousClass(psiClass)) { - PsiClass parent = JVMNameUtil.getTopLevelParentClass(psiClass); + PsiClass parent = TopLevelParentClassProvider.getTopLevelParentClass(psiClass); if (parent == null) { return; @@ -244,7 +244,7 @@ public class PositionManagerImpl implements PositionManager { } if(PsiUtil.isLocalOrAnonymousClass(psiClass)) { - final PsiClass parentNonLocal = JVMNameUtil.getTopLevelParentClass(psiClass); + final PsiClass parentNonLocal = TopLevelParentClassProvider.getTopLevelParentClass(psiClass); if(parentNonLocal == null) { LOG.error("Local or anonymous class has no non-local parent"); return null; diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java b/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java new file mode 100644 index 000000000000..782bf3452e2e --- /dev/null +++ b/java/debugger/openapi/src/com/intellij/debugger/engine/TopLevelParentClassProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.debugger.engine; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiClass; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; + +/** + * @author Max Medvedev + */ +public abstract class TopLevelParentClassProvider { + private static final ExtensionPointName EP_NAME = + ExtensionPointName.create("com.intellij.topLevelClassProvider"); + + public static PsiClass getTopLevelParentClass(PsiClass psiClass) { + for (TopLevelParentClassProvider provider : EP_NAME.getExtensions()) { + final PsiClass custom = provider.getCustomTopLevelParentClass(psiClass); + if (custom != null) return custom; + } + + PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true); + while (enclosing != null) { + psiClass = enclosing; + enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true); + } + return psiClass; + } + + @Nullable + protected abstract PsiClass getCustomTopLevelParentClass(PsiClass psiClass); + +} diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index a2d199be85a3..584b94f7eca1 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -252,6 +252,8 @@ + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java index e12d416d0d44..acb5fddf1d03 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java @@ -94,8 +94,8 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory { javaText.append("groovy.lang.MetaClass |mc;\n"); javaText.append("java.lang.Class |clazz;\n"); if (!isStatic) { - javaText.append("|clazz = ((java.lang.Object)this).getClass();\n"); - javaText.append("|mc = ((groovy.lang.GroovyObject)this).getMetaClass();\n"); + javaText.append("|clazz = this.getClass();\n"); + javaText.append("|mc = this.getMetaClass();\n"); } else { assert contextClass != null; javaText.append("|clazz = java.lang.Class.forName(\"").append(contextClass.getQualifiedName()).append("\");\n"); @@ -118,16 +118,16 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory { javaText.append("groovy.lang.ExpandoMetaClass |emc = new groovy.lang.ExpandoMetaClass(|clazz);\n"); if (!isStatic) { javaText.append("|emc.setProperty(\"").append(EVAL_NAME).append("\", |closure);\n"); - javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|emc);\n"); + javaText.append("this.setMetaClass(|emc);\n"); } else { - javaText.append("((groovy.lang.GroovyObject)|emc.getProperty(\"static\")).setProperty(\"").append(EVAL_NAME).append("\", |closure);\n"); + javaText.append("|emc.getProperty(\"static\").setProperty(\"").append(EVAL_NAME).append("\", |closure);\n"); javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |emc);\n"); } javaText.append("|emc.initialize();\n"); javaText.append(unwrapVals(values)); if (!isStatic) { javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeMethod(this, \"").append(EVAL_NAME).append("\", |resVals);\n"); - javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|mc);"); //try/finally is not supported + javaText.append("this.setMetaClass(|mc);"); //try/finally is not supported } else { javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeStaticMethod(|clazz, \"").append(EVAL_NAME).append("\", |resVals);\n"); javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |mc);\n"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyTopLevelParentClassProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyTopLevelParentClassProvider.java new file mode 100644 index 000000000000..b1858a4d3e04 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyTopLevelParentClassProvider.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.debugger; + +import com.intellij.debugger.engine.TopLevelParentClassProvider; +import com.intellij.psi.PsiAnonymousClass; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; + +/** + * @author Max Medvedev + */ +public class GroovyTopLevelParentClassProvider extends TopLevelParentClassProvider { + @Nullable + @Override + protected PsiClass getCustomTopLevelParentClass(PsiClass psiClass) { + if (!(psiClass instanceof GrTypeDefinition)) return null; + + PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true); + while (enclosing != null) { + psiClass = enclosing; + enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true); + } + + if (psiClass instanceof PsiAnonymousClass) { + final PsiFile file = psiClass.getContainingFile(); + if (file instanceof GroovyFile) { + return ((GroovyFile)file).getScriptClass(); + } + } + + return psiClass; + } +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 6345c2431ea2..453e54c19a68 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -121,6 +121,7 @@ + From c42128d115413e78edcc0f0a3fc869fe0ffb121a Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 22 Nov 2011 17:05:27 +0400 Subject: [PATCH 15/45] unescape copied text from regexps --- .../StringLiteralCopyPasteProcessor.java | 9 +++++-- .../openapi/util/text/StringUtil.java | 26 +++++++++++++++++++ .../GroovyLiteralCopyPasteProcessor.java | 20 +++++++++++++- .../plugins/groovy/GroovyCopyPasteTest.groovy | 2 +- 4 files changed, 53 insertions(+), 4 deletions(-) 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 2f55b0e977f6..1c0f2fadb351 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java @@ -98,7 +98,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { numberOfSymbolsToCopy = Math.min(escapedEndOffset, fileEndOffset) - Math.max(fileStartOffset, escapedStartOffset); if (numberOfSymbolsToCopy > 0) { textWasChanged = true; - buffer.append(unescapeStringCharacters(text.substring(givenTextStartOffset, givenTextStartOffset + numberOfSymbolsToCopy))); + buffer.append(unescape(text.substring(givenTextStartOffset, givenTextStartOffset + numberOfSymbolsToCopy), element)); givenTextStartOffset += numberOfSymbolsToCopy; } @@ -112,7 +112,12 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { } return textWasChanged ? buffer.toString() : null; } - + + @NotNull + protected String unescape(String text, PsiElement token) { + return unescapeStringCharacters(text); + } + public String preprocessOnPaste(final Project project, final PsiFile file, final Editor editor, String text, final RawText rawText) { final Document document = editor.getDocument(); PsiDocumentManager.getInstance(project).commitDocument(document); diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 01ed5a5a4d42..09abebf8f37d 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1655,6 +1655,32 @@ public class StringUtil { idx += 2; } } + + public static String unescapeSlashes(@NotNull final String str) { + final StringBuilder buf = StringBuilderSpinAllocator.alloc(); + try { + unescapeSlashes(buf, str); + return buf.toString(); + } + finally { + StringBuilderSpinAllocator.dispose(buf); + } + } + + private static void unescapeSlashes(StringBuilder buf, String str) { + final int length = str.length(); + final int last = length - 1; + for (int i = 0; i < length; i++) { + char ch = str.charAt(i); + if (ch == '\\' && i != last) { + i++; + ch = str.charAt(i); + if (ch != '/') buf.append('\\'); + } + + buf.append(ch); + } + } public static void quote(@NotNull final StringBuilder builder) { quote(builder, '\"'); 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 304cc0956644..016eeba65cc0 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 @@ -64,7 +64,12 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce IElementType tokenType = token.getNode().getElementType(); if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) { - return StringUtil.escapeSlashes(s); + if (escapeSlashes) { + return StringUtil.escapeSlashes(s); + } + else { + return s; + } } String chars; @@ -87,4 +92,17 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce StringUtil.escapeStringCharacters(s.length(), s, chars, escapeSlashes, buffer); return buffer.toString(); } + + @NotNull + @Override + protected String unescape(String text, PsiElement token) { + final IElementType tokenType = token.getNode().getElementType(); + + if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) { + return StringUtil.unescapeSlashes(text); + } + + return super.unescape(text, token); + } + } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy index fdc8f2c63eb0..03ecee6658ae 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy @@ -54,7 +54,7 @@ class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase { myFixture.performEditorAction IdeActions.ACTION_COPY myFixture.configureByText 'b.groovy', 'def x = "smthh"' myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult 'def x = "smth$ah"' + myFixture.checkResult 'def x = "smth\\$ah"' } From 10abec569617a817e43b8570b7b28430eff14034 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 23 Nov 2011 11:47:02 +0400 Subject: [PATCH 16/45] test for debugging anonymous class in script --- .../groovy/compiler/GroovyDebuggerTest.groovy | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy index 79a28143d451..186e7c9b77d4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy @@ -211,6 +211,22 @@ cl.parseClass('''$mcText''', 'MyClass.groovy').foo(2) eval 'a', '2' } } + + void testAnonymousClassInScript() { + myFixture.addFileToProject('Foo.groovy', '''\ +new Runnable() { + void run() { + print 'foo' + } +}.run() + +''') + addBreakpoint 'Foo.groovy', 2 + runDebugger 'Foo', { + waitForBreakpoint() + eval '1+1', '2' + } + } private def addBreakpoint(String fileName, int line) { VirtualFile file = null From ac487a3dd1018b20adf6a9ac99b235a364d807eb Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 22 Nov 2011 19:17:16 +0400 Subject: [PATCH 17/45] git: do not close annotation gutter when user reverts *local* changes - annotation is still valid! --- .../git4idea/annotate/GitAnnotationProvider.java | 4 ++-- .../src/git4idea/annotate/GitFileAnnotation.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java index b5a328d0de78..e137b78bff2b 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java +++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java @@ -159,7 +159,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn h.endOptions(); h.addRelativePaths(repositoryFilePath); String output = h.run(); - GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null); + GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null, revision == null ? null : revision.getRevisionNumber()); class CommitInfo { Date date; String author; @@ -228,7 +228,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn String annotatedContent, boolean forCurrentRevision, VcsRevisionNumber revisionNumber) { final GitFileAnnotation gitFileAnnotation = - new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision); + new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision, revisionNumber); gitFileAnnotation.addLogEntries(session.getRevisionList()); final VcsLineAnnotationData basicAnnotation = vcsAnnotation.getBasicAnnotation(); final int size = basicAnnotation.getNumLines(); diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java index c5417fad8a26..a18a99b85e89 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java +++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java @@ -57,6 +57,7 @@ public class GitFileAnnotation implements FileAnnotation { * The project reference */ private final Project myProject; + private final VcsRevisionNumber myBaseRevision; /** * Annotation change listeners */ @@ -103,6 +104,7 @@ public class GitFileAnnotation implements FileAnnotation { return author == null ? "" : author; } }; + private final GitVcs myVcs; /** * A constructor @@ -110,10 +112,13 @@ public class GitFileAnnotation implements FileAnnotation { * @param project the project of annotation provider * @param file the git root * @param monitorFlag if false the file system will not be listened for changes (used for annotated files from the repository). + * @param revision */ - public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag) { + public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag, final VcsRevisionNumber revision) { myProject = project; + myVcs = GitVcs.getInstance(myProject); myFile = file; + myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision; myMonitorFlag = monitorFlag; if (myMonitorFlag) { myFileListener = new VirtualFileAdapter() { @@ -121,6 +126,8 @@ public class GitFileAnnotation implements FileAnnotation { public void contentsChanged(final VirtualFileEvent event) { if (myFile != event.getFile()) return; if (!event.isFromRefresh()) return; + final VcsRevisionNumber currentRevision = myVcs.getDiffProvider().getCurrentRevision(myFile); + if (currentRevision != null && currentRevision.equals(revision)) return; fireAnnotationChanged(); } }; @@ -391,6 +398,11 @@ public class GitFileAnnotation implements FileAnnotation { private void checkAndFire() { // for the case of commit changes... remove annotation gutter if (FileStatus.NOT_CHANGED.equals(FileStatusManager.getInstance(myProject).getStatus(myFile))) { + if (myBaseRevision != null) { + final VcsRevisionNumber currentRevision = myVcs.getDiffProvider().getCurrentRevision(myFile); + // revision is not when monitorFlag is true + if (currentRevision != null && currentRevision.equals(myBaseRevision)) return; + } fireAnnotationChanged(); } } From 0fc43334d6c22afb640a5ace1bce31fd65521038 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Nov 2011 16:49:03 +0400 Subject: [PATCH 18/45] addLast() crashes in case of new Queue(0) --- .../testSrc/com/intellij/util/containers/QueueTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platform/util/testSrc/com/intellij/util/containers/QueueTest.java b/platform/util/testSrc/com/intellij/util/containers/QueueTest.java index 833fad9398d1..1435d96e2b6f 100644 --- a/platform/util/testSrc/com/intellij/util/containers/QueueTest.java +++ b/platform/util/testSrc/com/intellij/util/containers/QueueTest.java @@ -48,6 +48,15 @@ public class QueueTest extends TestCase { testEmpty(); } + public void testQuibble() { + com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(0); + String xxx = "xxx"; + queue.addLast(xxx); + CHECK.compareAll(queue.toArray(), new String[] {xxx}); + Object x = queue.pullFirst(); + assertEquals(xxx,x); + assertTrue(queue.isEmpty()); + } public void testCycling() { com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(10); for (int i = 0; i < 9; i++) { From 607a1a022ea640d2a3285671e923804b38d59fe7 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Nov 2011 17:11:49 +0400 Subject: [PATCH 19/45] cleanup --- platform/util/src/com/intellij/util/containers/Queue.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/Queue.java b/platform/util/src/com/intellij/util/containers/Queue.java index aa0c112b96c5..a4c634254132 100644 --- a/platform/util/src/com/intellij/util/containers/Queue.java +++ b/platform/util/src/com/intellij/util/containers/Queue.java @@ -15,11 +15,12 @@ */ package com.intellij.util.containers; +import com.intellij.util.ArrayUtil; + import java.util.Arrays; import java.util.List; public class Queue { - private final static Object[] EMPTY = new Object[0]; private Object[] myArray; private int myFirst; private int myLast; @@ -29,7 +30,7 @@ public class Queue { private boolean isWrapped; public Queue(int initialCapacity) { - myArray = initialCapacity > 0 ? new Object[initialCapacity] : EMPTY; + myArray = initialCapacity > 0 ? new Object[initialCapacity] : ArrayUtil.EMPTY_OBJECT_ARRAY; } public void addLast(T object) { From 858c37f13bd0650c764ef4d94f34c55b012f6701 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 22 Nov 2011 17:29:25 +0400 Subject: [PATCH 20/45] less lock contention in IterationState, IterationState usage contract changed to DisposableIterator for that --- .../openapi/editor/ex/DisposableIterator.java | 43 + .../openapi/editor/impl/IntervalTreeImpl.java | 71 +- .../injected/editor/MarkupModelWindow.java | 7 +- .../openapi/editor/ex/MarkupModelEx.java | 4 +- .../openapi/editor/ex/util/EditorUtil.java | 40 +- .../impl/EditorGutterComponentImpl.java | 105 +-- .../openapi/editor/impl/EditorImpl.java | 804 +++++++++--------- .../openapi/editor/impl/EmptyMarkupModel.java | 8 +- .../openapi/editor/impl/IterationState.java | 41 +- .../openapi/editor/impl/MarkupModelImpl.java | 4 +- .../mapping/SoftWrapApplianceManager.java | 91 +- 11 files changed, 660 insertions(+), 558 deletions(-) create mode 100644 platform/core-impl/src/com/intellij/openapi/editor/ex/DisposableIterator.java diff --git a/platform/core-impl/src/com/intellij/openapi/editor/ex/DisposableIterator.java b/platform/core-impl/src/com/intellij/openapi/editor/ex/DisposableIterator.java new file mode 100644 index 000000000000..f9f1483d44a2 --- /dev/null +++ b/platform/core-impl/src/com/intellij/openapi/editor/ex/DisposableIterator.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.ex; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public interface DisposableIterator extends Iterator { + void dispose(); + DisposableIterator EMPTY = new DisposableIterator() { + @Override + public void dispose() { + } + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new IllegalAccessError(); + } + }; +} diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 832be08c629b..ff22a4e003be 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.openapi.editor.ex.DisposableIterator; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Trinity; import com.intellij.util.IncorrectOperationException; @@ -22,14 +23,12 @@ import com.intellij.util.Processor; import com.intellij.util.SmartList; import com.intellij.util.WalkingState; import com.intellij.util.concurrency.AtomicFieldUpdater; -import com.intellij.util.containers.ContainerUtil; import gnu.trove.TLongHashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; import java.util.ConcurrentModificationException; -import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.locks.Lock; @@ -495,15 +494,18 @@ public abstract class IntervalTreeImpl extends RedBla } @NotNull - Iterator overlappingIterator(final int startOffset, final int endOffset) { + DisposableIterator overlappingIterator(final int startOffset, final int endOffset) { final IntervalNode firstOverlap = findMinOverlappingWith(getRoot(), new TextRangeInterval(startOffset, endOffset), modCount, 0); if (firstOverlap == null) { - return ContainerUtil.emptyIterator(); + return DisposableIterator.EMPTY; } final int firstOverlapDelta = firstOverlap.computeDeltaUpToRoot(); final int firstOverlapStart = firstOverlap.intervalStart() + firstOverlapDelta; final int modCountBefore = modCount; - return new Iterator() { + + l.readLock().lock(); + + return new DisposableIterator() { private IntervalNode currentNode = firstOverlap; private int deltaUpToRootExclusive = firstOverlapDelta-firstOverlap.delta; private int indexInCurrentList = 0; @@ -513,39 +515,33 @@ public abstract class IntervalTreeImpl extends RedBla public boolean hasNext() { if (current != null) return true; if (currentNode == null) return false; - try { - l.readLock().lock(); - if (modCount != modCountBefore) throw new ConcurrentModificationException(); - while (indexInCurrentList != currentNode.intervals.size()) { - T t = currentNode.intervals.get(indexInCurrentList++).get(); - if (t != null) { - current = t; - return true; - } - } - indexInCurrentList = 0; - while (true) { - currentNode = nextNode(currentNode); - if (currentNode == null) { - return false; - } - if (overlaps(currentNode, startOffset, endOffset, deltaUpToRootExclusive)) { - assert currentNode.intervalStart() + deltaUpToRootExclusive + currentNode.delta >= firstOverlapStart; - indexInCurrentList = 0; - while (indexInCurrentList != currentNode.intervals.size()) { - T t = currentNode.intervals.get(indexInCurrentList++).get(); - if (t != null) { - current = t; - return true; - } - } - indexInCurrentList = 0; - } + if (modCount != modCountBefore) throw new ConcurrentModificationException(); + while (indexInCurrentList != currentNode.intervals.size()) { + T t = currentNode.intervals.get(indexInCurrentList++).get(); + if (t != null) { + current = t; + return true; } } - finally { - l.readLock().unlock(); + indexInCurrentList = 0; + while (true) { + currentNode = nextNode(currentNode); + if (currentNode == null) { + return false; + } + if (overlaps(currentNode, startOffset, endOffset, deltaUpToRootExclusive)) { + assert currentNode.intervalStart() + deltaUpToRootExclusive + currentNode.delta >= firstOverlapStart; + indexInCurrentList = 0; + while (indexInCurrentList != currentNode.intervals.size()) { + T t = currentNode.intervals.get(indexInCurrentList++).get(); + if (t != null) { + current = t; + return true; + } + } + indexInCurrentList = 0; + } } } @@ -562,6 +558,11 @@ public abstract class IntervalTreeImpl extends RedBla throw new IncorrectOperationException(); } + @Override + public void dispose() { + l.readLock().unlock(); + } + // next node in in-order traversal private IntervalNode nextNode(@NotNull IntervalNode root) { assert root.isValid(); diff --git a/platform/platform-impl/src/com/intellij/injected/editor/MarkupModelWindow.java b/platform/platform-impl/src/com/intellij/injected/editor/MarkupModelWindow.java index 979e176c9861..1f7bed30b5f6 100644 --- a/platform/platform-impl/src/com/intellij/injected/editor/MarkupModelWindow.java +++ b/platform/platform-impl/src/com/intellij/injected/editor/MarkupModelWindow.java @@ -18,6 +18,7 @@ package com.intellij.injected.editor; import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.DisposableIterator; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.ex.SweepProcessor; @@ -25,15 +26,13 @@ import com.intellij.openapi.editor.impl.event.MarkupModelListener; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.ProperTextRange; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.util.ProperTextRange; import com.intellij.util.Consumer; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; - /** * @author cdr */ @@ -146,7 +145,7 @@ public class MarkupModelWindow extends UserDataHolderBase implements MarkupModel @NotNull @Override - public Iterator overlappingIterator(int startOffset, int endOffset) { + public DisposableIterator overlappingIterator(int startOffset, int endOffset) { // todo convert return myHostModel.overlappingIterator(startOffset, endOffset); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/MarkupModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/MarkupModelEx.java index e2edfecd7f4b..6dad403e5f4b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/MarkupModelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/MarkupModelEx.java @@ -26,8 +26,6 @@ import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - /** * @author max */ @@ -46,7 +44,7 @@ public interface MarkupModelEx extends MarkupModel { boolean processRangeHighlightersOutside(int start, int end, @NotNull Processor processor); @NotNull - Iterator overlappingIterator(int startOffset, int endOffset); + DisposableIterator overlappingIterator(int startOffset, int endOffset); // optimization: creates highlighter and fires only one event: highlighterCreated RangeHighlighterEx addRangeHighlighterAndChangeAttributes(int startOffset, diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 28d09326c4e2..f0b4720bf534 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -320,26 +320,32 @@ public class EditorUtil { EditorEx editorImpl = (EditorEx)editor; int offset = start; IterationState state = new IterationState(editorImpl, start, end, false); - int fontType = state.getMergedAttributes().getFontType(); - int column = currentColumn[0]; - int spaceSize = getSpaceWidth(fontType, editorImpl); - for (; column < columnNumber && offset < end; offset++) { - if (offset >= state.getEndOffset()) { - state.advance(); - fontType = state.getMergedAttributes().getFontType(); - } + int column; + try { + int fontType = state.getMergedAttributes().getFontType(); + column = currentColumn[0]; + int spaceSize = getSpaceWidth(fontType, editorImpl); + for (; column < columnNumber && offset < end; offset++) { + if (offset >= state.getEndOffset()) { + state.advance(); + fontType = state.getMergedAttributes().getFontType(); + } - char c = text.charAt(offset); - if (c == '\t') { - int prevX = x; - x = nextTabStop(x, editorImpl); - column += columnsNumber(x - prevX, spaceSize); - } - else { - x += charWidth(c, fontType, editorImpl); - column++; + char c = text.charAt(offset); + if (c == '\t') { + int prevX = x; + x = nextTabStop(x, editorImpl); + column += columnsNumber(x - prevX, spaceSize); + } + else { + x += charWidth(c, fontType, editorImpl); + column++; + } } } + finally { + state.dispose(); + } if (column == columnNumber) { return offset; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 86d0467759a2..983810f02c62 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -399,64 +399,69 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse int docLength = document.getTextLength(); int patchedStartOffset = startOffset < docLength ? document.getLineStartOffset(document.getLineNumber(startOffset)) : docLength; int patchedEndOffset = endOffset <= docLength ? document.getLineEndOffset(document.getLineNumber(endOffset)) + 1 : docLength; - Iterator docHighlighters = docMarkup.overlappingIterator(patchedStartOffset, patchedEndOffset); + DisposableIterator docHighlighters = docMarkup.overlappingIterator(patchedStartOffset, patchedEndOffset); final MarkupModelEx editorMarkup = (MarkupModelEx)myEditor.getMarkupModel(); - Iterator editorHighlighters = editorMarkup.overlappingIterator(startOffset, endOffset); + DisposableIterator editorHighlighters = editorMarkup.overlappingIterator(startOffset, endOffset); - RangeHighlighterEx lastDocHighlighter = null; - RangeHighlighterEx lastEditorHighlighter = null; + try { + RangeHighlighterEx lastDocHighlighter = null; + RangeHighlighterEx lastEditorHighlighter = null; + while (true) { + if (lastDocHighlighter == null && docHighlighters.hasNext()) { + lastDocHighlighter = docHighlighters.next(); + if (!lastDocHighlighter.isValid() || lastDocHighlighter.getAffectedAreaStartOffset() > endOffset) { + lastDocHighlighter = null; + continue; + } + if (lastDocHighlighter.getAffectedAreaEndOffset() < startOffset) { + lastDocHighlighter = null; + continue; + } + } - while (true) { - if (lastDocHighlighter == null && docHighlighters.hasNext()) { - lastDocHighlighter = docHighlighters.next(); - if (!lastDocHighlighter.isValid() || lastDocHighlighter.getAffectedAreaStartOffset() > endOffset) { + if (lastEditorHighlighter == null && editorHighlighters.hasNext()) { + lastEditorHighlighter = editorHighlighters.next(); + if (!lastEditorHighlighter.isValid() || lastEditorHighlighter.getAffectedAreaStartOffset() > endOffset) { + lastEditorHighlighter = null; + continue; + } + if (lastEditorHighlighter.getAffectedAreaEndOffset() < startOffset) { + lastEditorHighlighter = null; + continue; + } + } + + if (lastDocHighlighter == null && lastEditorHighlighter == null) return; + + final RangeHighlighterEx lowerHighlighter; + + if (less(lastDocHighlighter, lastEditorHighlighter)) { + lowerHighlighter = lastDocHighlighter; lastDocHighlighter = null; - continue; } - if (lastDocHighlighter.getAffectedAreaEndOffset() < startOffset) { - lastDocHighlighter = null; - continue; - } - } - - if (lastEditorHighlighter == null && editorHighlighters.hasNext()) { - lastEditorHighlighter = editorHighlighters.next(); - if (!lastEditorHighlighter.isValid() || lastEditorHighlighter.getAffectedAreaStartOffset() > endOffset) { + else { + lowerHighlighter = lastEditorHighlighter; lastEditorHighlighter = null; - continue; } - if (lastEditorHighlighter.getAffectedAreaEndOffset() < startOffset) { - lastEditorHighlighter = null; - continue; + + assert lowerHighlighter != null; + if (!lowerHighlighter.isValid()) continue; + + int startLineIndex = lowerHighlighter.getDocument().getLineNumber(startOffset); + if (startLineIndex < 0 || startLineIndex >= document.getLineCount()) continue; + + int endLineIndex = lowerHighlighter.getDocument().getLineNumber(endOffset); + if (endLineIndex < 0 || endLineIndex >= document.getLineCount()) continue; + + if (lowerHighlighter.getEditorFilter().avaliableIn(myEditor)) { + processor.process(lowerHighlighter); } } - - if (lastDocHighlighter == null && lastEditorHighlighter == null) return; - - final RangeHighlighterEx lowerHighlighter; - - if (less(lastDocHighlighter, lastEditorHighlighter)) { - lowerHighlighter = lastDocHighlighter; - lastDocHighlighter = null; - } - else { - lowerHighlighter = lastEditorHighlighter; - lastEditorHighlighter = null; - } - - assert lowerHighlighter != null; - if (!lowerHighlighter.isValid()) continue; - - int startLineIndex = lowerHighlighter.getDocument().getLineNumber(startOffset); - if (startLineIndex < 0 || startLineIndex >= document.getLineCount()) continue; - - int endLineIndex = lowerHighlighter.getDocument().getLineNumber(endOffset); - if (endLineIndex < 0 || endLineIndex >= document.getLineCount()) continue; - - if (lowerHighlighter.getEditorFilter().avaliableIn(myEditor)) { - processor.process(lowerHighlighter); - } + } + finally { + docHighlighters.dispose(); + editorHighlighters.dispose(); } } @@ -968,7 +973,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Override public boolean isAnnotationsShown() { - return myTextAnnotationGutters.size() > 0; + return !myTextAnnotationGutters.isEmpty(); } @Override @@ -1122,7 +1127,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - if (toolTip != null && toolTip.length() != 0) { + if (toolTip != null && !toolTip.isEmpty()) { final Ref t = new Ref(e.getPoint()); int line = myEditor.yPositionToLogicalLine(e.getY()); ArrayList row = myLineToGutterRenderers.get(line); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 9943ff2fd45e..28f0d87f11a8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -985,10 +985,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // We mark that we're under such circumstances then. boolean activeSoftWrapProcessed = logicalPosition.softWrapLinesOnCurrentLogicalLine <= 0; - int column = 0; - int prevX = 0; CharSequence text = myDocument.getCharsNoThreadCheck(); - char c = ' '; LogicalPosition endLogicalPosition = visualToLogicalPosition(new VisualPosition(line+1, 0)); int endOffset = logicalPositionToOffset(endLogicalPosition); @@ -1004,125 +1001,133 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } IterationState state = new IterationState(this, offset, endOffset, false); - int fontType = state.getMergedAttributes().getFontType(); - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); + try { + int fontType = state.getMergedAttributes().getFontType(); + int spaceSize = EditorUtil.getSpaceWidth(fontType, this); - int x = 0; - int charWidth; - boolean onSoftWrapDrawing = false; - outer: - while (true) { - charWidth = -1; - if (offset >= textLength) { - break; - } + int x = 0; + int charWidth; + boolean onSoftWrapDrawing = false; + char c = ' '; + int prevX = 0; + int column = 0; + outer: + while (true) { + charWidth = -1; + if (offset >= textLength) { + break; + } - if (offset >= state.getEndOffset()) { - state.advance(); - fontType = state.getMergedAttributes().getFontType(); - } + if (offset >= state.getEndOffset()) { + state.advance(); + fontType = state.getMergedAttributes().getFontType(); + } - SoftWrap softWrap = mySoftWrapModel.getSoftWrap(offset); - if (softWrap != null) { - if (activeSoftWrapProcessed) { - prevX = x; - charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); - x += charWidth; - if (x >= px) { - onSoftWrapDrawing = true; + SoftWrap softWrap = mySoftWrapModel.getSoftWrap(offset); + if (softWrap != null) { + if (activeSoftWrapProcessed) { + prevX = x; + charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); + x += charWidth; + if (x >= px) { + onSoftWrapDrawing = true; + } + else { + column++; + } + break outer; } else { - column++; - } - break outer; - } - else { - CharSequence softWrapText = softWrap.getText(); - for (int i = 1/*Assuming line feed is located at the first position*/; i < softWrapText.length(); i++) { - c = softWrapText.charAt(i); + CharSequence softWrapText = softWrap.getText(); + for (int i = 1/*Assuming line feed is located at the first position*/; i < softWrapText.length(); i++) { + c = softWrapText.charAt(i); + prevX = x; + charWidth = charToVisibleWidth(c, fontType, x); + x += charWidth; + if (x >= px) { + break outer; + } + column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + } + + // Process 'after soft wrap' sign. prevX = x; - charWidth = charToVisibleWidth(c, fontType, x); + charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); x += charWidth; + if (x >= px) { + onSoftWrapDrawing = true; + break outer; + } + column++; + activeSoftWrapProcessed = true; + } + } + FoldRegion region = state.getCurrentFold(); + if (region != null) { + char[] placeholder = region.getPlaceholderText().toCharArray(); + for (char aPlaceholder : placeholder) { + c = aPlaceholder; + x += EditorUtil.charWidth(c, fontType, this); if (x >= px) { break outer; } - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + column++; } - - // Process 'after soft wrap' sign. + offset = region.getEndOffset(); + } + else { prevX = x; - charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); + c = text.charAt(offset); + charWidth = charToVisibleWidth(c, fontType, x); + if (charWidth == 0) { + break; + } x += charWidth; + if (x >= px) { - onSoftWrapDrawing = true; - break outer; + break; } - column++; - activeSoftWrapProcessed = true; + column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + + offset++; } } - FoldRegion region = state.getCurrentFold(); - if (region != null) { - char[] placeholder = region.getPlaceholderText().toCharArray(); - for (char aPlaceholder : placeholder) { - c = aPlaceholder; - x += EditorUtil.charWidth(c, fontType, this); - if (x >= px) { - break outer; - } - column++; + + if (charWidth < 0) { + charWidth = EditorUtil.charWidth(c, fontType, this); + } + + if (charWidth < 0) { + charWidth = spaceSize; + } + + if (x >= px && c == '\t' && !onSoftWrapDrawing) { + if (mySettings.isCaretInsideTabs()) { + column += (px - prevX) / spaceSize; + if ((px - prevX) % spaceSize > spaceSize / 2) column++; + } + else if ((x - px) * 2 < x - prevX) { + column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); } - offset = region.getEndOffset(); } else { - prevX = x; - c = text.charAt(offset); - charWidth = charToVisibleWidth(c, fontType, x); - if (charWidth == 0) { - break; - } - x += charWidth; - if (x >= px) { - break; + if ((x - px) * 2 < charWidth) column++; } - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); - - offset++; - } - } - - if (charWidth < 0) { - charWidth = EditorUtil.charWidth(c, fontType, this); - } - - if (charWidth < 0) { - charWidth = spaceSize; - } - - if (x >= px && c == '\t' && !onSoftWrapDrawing) { - if (mySettings.isCaretInsideTabs()) { - column += (px - prevX) / spaceSize; - if ((px - prevX) % spaceSize > spaceSize / 2) column++; - } - else if ((x - px) * 2 < x - prevX) { - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); - } - } - else { - if (x >= px) { - if ((x - px) * 2 < charWidth) column++; - } - else { - int diff = px - x; - column += diff / spaceSize; - if (diff % spaceSize * 2 >= spaceSize) { - column++; + else { + int diff = px - x; + column += diff / spaceSize; + if (diff % spaceSize * 2 >= spaceSize) { + column++; + } } } - } - return new VisualPosition(line, column); + return new VisualPosition(line, column); + } + finally { + state.dispose(); + } } /** @@ -1299,68 +1304,73 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi CharSequence text = myDocument.getCharsNoThreadCheck(); int textLength = myDocument.getTextLength(); IterationState state = new IterationState(this, startOffset, startOffset + length, false); - int fontType = state.getMergedAttributes().getFontType(); - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); + try { + int fontType = state.getMergedAttributes().getFontType(); + int spaceSize = EditorUtil.getSpaceWidth(fontType, this); - int column = 0; - outer: - while (column < length) { - if (offset >= textLength) break; + int column = 0; + outer: + while (column < length) { + if (offset >= textLength) break; - if (offset >= state.getEndOffset()) { - state.advance(); - fontType = state.getMergedAttributes().getFontType(); - } - // We need to consider 'before soft wrap drawing'. - SoftWrap softWrap = getSoftWrapModel().getSoftWrap(offset); - if (softWrap != null && offset > startOffset) { - column++; - x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); - // Assuming that first soft wrap symbol is line feed or all soft wrap symbols before the first line feed are spaces. - break; - } - - FoldRegion region = state.getCurrentFold(); - - if (region != null) { - char[] placeholder = region.getPlaceholderText().toCharArray(); - for (char aPlaceholder : placeholder) { - x += EditorUtil.charWidth(aPlaceholder, fontType, this); - column++; - if (column >= length) break outer; + if (offset >= state.getEndOffset()) { + state.advance(); + fontType = state.getMergedAttributes().getFontType(); } - offset = region.getEndOffset(); - } - else { - char c = text.charAt(offset); - if (c == '\n') { + // We need to consider 'before soft wrap drawing'. + SoftWrap softWrap = getSoftWrapModel().getSoftWrap(offset); + if (softWrap != null && offset > startOffset) { + column++; + x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); + // Assuming that first soft wrap symbol is line feed or all soft wrap symbols before the first line feed are spaces. break; } - if (c == '\t') { - int prevX = x; - x = EditorUtil.nextTabStop(x, this); - int columnDiff = (x - prevX) / spaceSize; - if ((x - prevX) % spaceSize > 0) { - // There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at - // soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented - // as a separate visual column may take less space than space width. - columnDiff++; + + FoldRegion region = state.getCurrentFold(); + + if (region != null) { + char[] placeholder = region.getPlaceholderText().toCharArray(); + for (char aPlaceholder : placeholder) { + x += EditorUtil.charWidth(aPlaceholder, fontType, this); + column++; + if (column >= length) break outer; } - column += columnDiff; + offset = region.getEndOffset(); } else { - x += EditorUtil.charWidth(c, fontType, this); - column++; + char c = text.charAt(offset); + if (c == '\n') { + break; + } + if (c == '\t') { + int prevX = x; + x = EditorUtil.nextTabStop(x, this); + int columnDiff = (x - prevX) / spaceSize; + if ((x - prevX) % spaceSize > 0) { + // There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at + // soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented + // as a separate visual column may take less space than space width. + columnDiff++; + } + column += columnDiff; + } + else { + x += EditorUtil.charWidth(c, fontType, this); + column++; + } + offset++; } - offset++; } - } - if (column != length) { - x += EditorUtil.getSpaceWidth(fontType, this) * (length - column); - } + if (column != length) { + x += EditorUtil.getSpaceWidth(fontType, this) * (length - column); + } - return x; + return x; + } + finally { + state.dispose(); + } } public int visibleLineToY(int line) { @@ -1910,7 +1920,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int start = clipStartOffset; int end = clipEndOffset; getSoftWrapModel().registerSoftWrapsIfNecessary(); - IterationState iterationState = new IterationState(this, start, end, isPaintSelection()); LineIterator lIterator = createLineIterator(); lIterator.start(start); @@ -1918,112 +1927,118 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return; } - TextAttributes attributes = iterationState.getMergedAttributes(); - Color backColor = getBackgroundColor(attributes); - int fontType = attributes.getFontType(); - CharSequence text = myDocument.getCharsNoThreadCheck(); - int lastLineIndex = Math.max(0, myDocument.getLineCount() - 1); + IterationState iterationState = new IterationState(this, start, end, isPaintSelection()); + try { + TextAttributes attributes = iterationState.getMergedAttributes(); + Color backColor = getBackgroundColor(attributes); + int fontType = attributes.getFontType(); + CharSequence text = myDocument.getCharsNoThreadCheck(); + int lastLineIndex = Math.max(0, myDocument.getLineCount() - 1); - // There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position - // has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset. - // Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary. - TIntHashSet softWrapsToSkip = new TIntHashSet(); - SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start); - if (softWrap != null) { - softWrapsToSkip.add(softWrap.getStart()); - Color color = null; - if (backColor != null && !backColor.equals(defaultBackground)) { - color = backColor; - } - - // There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active - // line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced - // virtual space then. - if (color == null && position.y == getCaretModel().getVisualPosition().line * getLineHeight()) { - color = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); - } - - if (color != null) { - drawBackground(g, color, softWrap.getIndentInPixels(), position, defaultBackground, clip); - } - position.x = softWrap.getIndentInPixels(); - } - - // There is a possible case that caret is located at soft-wrapped line. We don't need to paint caret row background - // on a last visual line of that soft-wrapped line then. Below is a holder for the flag that indicates if caret row - // background is already drawn. - boolean[] caretRowPainted = new boolean[1]; - - while (!iterationState.atEnd() && !lIterator.atEnd()) { - int hEnd = iterationState.getEndOffset(); - int lEnd = lIterator.getEnd(); - - if (hEnd >= lEnd) { - FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); - if (collapsedFolderAt == null) { - position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType, - defaultBackground, clip, softWrapsToSkip, caretRowPainted); - - if (lIterator.getLineNumber() < lastLineIndex) { - if (backColor != null && !backColor.equals(defaultBackground)) { - g.setColor(backColor); - g.fillRect(position.x, position.y, clip.x + clip.width - position.x, lineHeight); - } - } - else { - paintAfterFileEndBackground(iterationState, - g, - position, clip, - lineHeight, defaultBackground, caretRowPainted); - break; - } - - position.x = 0; - if (position.y > clip.y + clip.height) break; - position.y += lineHeight; - start = lEnd; + // There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position + // has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset. + // Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary. + TIntHashSet softWrapsToSkip = new TIntHashSet(); + SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start); + if (softWrap != null) { + softWrapsToSkip.add(softWrap.getStart()); + Color color = null; + if (backColor != null && !backColor.equals(defaultBackground)) { + color = backColor; } - lIterator.advance(); + // There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active + // line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced + // virtual space then. + if (color == null && position.y == getCaretModel().getVisualPosition().line * getLineHeight()) { + color = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR); + } + + if (color != null) { + drawBackground(g, color, softWrap.getIndentInPixels(), position, defaultBackground, clip); + } + position.x = softWrap.getIndentInPixels(); } - else { - FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); - if (collapsedFolderAt != null) { - softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset()); - if (softWrap != null) { - position.x = drawSoftWrapAwareBackground( - g, backColor, text, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, fontType, - defaultBackground, clip, softWrapsToSkip, caretRowPainted - ); + + // There is a possible case that caret is located at soft-wrapped line. We don't need to paint caret row background + // on a last visual line of that soft-wrapped line then. Below is a holder for the flag that indicates if caret row + // background is already drawn. + boolean[] caretRowPainted = new boolean[1]; + + while (!iterationState.atEnd() && !lIterator.atEnd()) { + int hEnd = iterationState.getEndOffset(); + int lEnd = lIterator.getEnd(); + + if (hEnd >= lEnd) { + FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); + if (collapsedFolderAt == null) { + position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType, + defaultBackground, clip, softWrapsToSkip, caretRowPainted); + + if (lIterator.getLineNumber() < lastLineIndex) { + if (backColor != null && !backColor.equals(defaultBackground)) { + g.setColor(backColor); + g.fillRect(position.x, position.y, clip.x + clip.width - position.x, lineHeight); + } + } + else { + paintAfterFileEndBackground(iterationState, + g, + position, clip, + lineHeight, defaultBackground, caretRowPainted); + break; + } + + position.x = 0; + if (position.y > clip.y + clip.height) break; + position.y += lineHeight; + start = lEnd; } - position.x = drawBackground(g, backColor, collapsedFolderAt.getPlaceholderText(), position, fontType, defaultBackground, clip); + + lIterator.advance(); } else { - if (hEnd > lEnd - lIterator.getSeparatorLength()) { - position.x = drawSoftWrapAwareBackground( - g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType, - defaultBackground, clip, softWrapsToSkip, caretRowPainted - ); + FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); + if (collapsedFolderAt != null) { + softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset()); + if (softWrap != null) { + position.x = drawSoftWrapAwareBackground( + g, backColor, text, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, fontType, + defaultBackground, clip, softWrapsToSkip, caretRowPainted + ); + } + position.x = drawBackground(g, backColor, collapsedFolderAt.getPlaceholderText(), position, fontType, defaultBackground, clip); } else { - position.x = drawSoftWrapAwareBackground( - g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip, softWrapsToSkip, caretRowPainted - ); + if (hEnd > lEnd - lIterator.getSeparatorLength()) { + position.x = drawSoftWrapAwareBackground( + g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType, + defaultBackground, clip, softWrapsToSkip, caretRowPainted + ); + } + else { + position.x = drawSoftWrapAwareBackground( + g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip, softWrapsToSkip, caretRowPainted + ); + } } - } - iterationState.advance(); - attributes = iterationState.getMergedAttributes(); - backColor = getBackgroundColor(attributes); - fontType = attributes.getFontType(); - start = iterationState.getStartOffset(); + iterationState.advance(); + attributes = iterationState.getMergedAttributes(); + backColor = getBackgroundColor(attributes); + fontType = attributes.getFontType(); + start = iterationState.getStartOffset(); + } + } + + flushBackground(g, clip); + + if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) { + paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted); } } - - flushBackground(g, clip); - - if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) { - paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted); + finally { + iterationState.dispose(); } // Perform additional activity if soft wrap is added or removed during repainting. @@ -2356,92 +2371,97 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return; } - IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection()); LineIterator lIterator = createLineIterator(); lIterator.start(start); if (lIterator.atEnd()) { return; } - TextAttributes attributes = iterationState.getMergedAttributes(); - Color currentColor = attributes.getForegroundColor(); - if (currentColor == null) { - currentColor = getForegroundColor(); - } - Color effectColor = attributes.getEffectColor(); - EffectType effectType = attributes.getEffectType(); - int fontType = attributes.getFontType(); - g.setColor(currentColor); - - final char[] chars = myDocument.getRawChars(); - - while (!iterationState.atEnd() && !lIterator.atEnd()) { - int hEnd = iterationState.getEndOffset(); - int lEnd = lIterator.getEnd(); - if (hEnd >= lEnd) { - FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); - if (collapsedFolderAt == null) { - drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor, - effectType, fontType, currentColor, logicalPosition); - position.x = 0; - if (position.y > clip.y + clip.height) { - break; - } - position.y += lineHeight; - start = lEnd; - } - -// myBorderEffect.eolReached(g, this); - lIterator.advance(); + IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection()); + try { + TextAttributes attributes = iterationState.getMergedAttributes(); + Color currentColor = attributes.getForegroundColor(); + if (currentColor == null) { + currentColor = getForegroundColor(); } - else { - FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); - if (collapsedFolderAt != null) { - SoftWrap softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset()); - if (softWrap != null) { - position.x = drawStringWithSoftWraps( - g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType, - fontType, currentColor, logicalPosition - ); - } - int foldingXStart = position.x; - position.x = drawString( - g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor - ); - //drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, - // fontType, currentColor, logicalPosition); - BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, position.x, getLineHeight(), effectColor, effectType); + Color effectColor = attributes.getEffectColor(); + EffectType effectType = attributes.getEffectType(); + int fontType = attributes.getFontType(); + g.setColor(currentColor); + final char[] chars = myDocument.getRawChars(); + + while (!iterationState.atEnd() && !lIterator.atEnd()) { + int hEnd = iterationState.getEndOffset(); + int lEnd = lIterator.getEnd(); + if (hEnd >= lEnd) { + FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start); + if (collapsedFolderAt == null) { + drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor, + effectType, fontType, currentColor, logicalPosition); + position.x = 0; + if (position.y > clip.y + clip.height) { + break; + } + position.y += lineHeight; + start = lEnd; + } + + // myBorderEffect.eolReached(g, this); + lIterator.advance(); } else { - position.x = drawStringWithSoftWraps(g, chars, start, Math.min(hEnd, lEnd - lIterator.getSeparatorLength()) , position, clip, - effectColor, effectType, fontType, currentColor, logicalPosition); + FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); + if (collapsedFolderAt != null) { + SoftWrap softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset()); + if (softWrap != null) { + position.x = drawStringWithSoftWraps( + g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType, + fontType, currentColor, logicalPosition + ); + } + int foldingXStart = position.x; + position.x = drawString( + g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor + ); + //drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, + // fontType, currentColor, logicalPosition); + BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, position.x, getLineHeight(), effectColor, effectType); + + } + else { + position.x = drawStringWithSoftWraps(g, chars, start, Math.min(hEnd, lEnd - lIterator.getSeparatorLength()) , position, clip, + effectColor, effectType, fontType, currentColor, logicalPosition); + } + + iterationState.advance(); + attributes = iterationState.getMergedAttributes(); + + currentColor = attributes.getForegroundColor(); + if (currentColor == null) { + currentColor = getForegroundColor(); + } + + effectColor = attributes.getEffectColor(); + effectType = attributes.getEffectType(); + fontType = attributes.getFontType(); + + start = iterationState.getStartOffset(); } + } - iterationState.advance(); - attributes = iterationState.getMergedAttributes(); - - currentColor = attributes.getForegroundColor(); - if (currentColor == null) { - currentColor = getForegroundColor(); - } - - effectColor = attributes.getEffectColor(); - effectType = attributes.getEffectType(); - fontType = attributes.getFontType(); - - start = iterationState.getStartOffset(); + FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); + if (collapsedFolderAt != null) { + int foldingXStart = position.x; + int foldingXEnd = + drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, + fontType, currentColor, logicalPosition); + BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, foldingXEnd, getLineHeight(), effectColor, effectType); + // myBorderEffect.collapsedFolderReached(g, this); } } - - FoldRegion collapsedFolderAt = iterationState.getCurrentFold(); - if (collapsedFolderAt != null) { - int foldingXStart = position.x; - int foldingXEnd = - drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, - fontType, currentColor, logicalPosition); - BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, foldingXEnd, getLineHeight(), effectColor, effectType); -// myBorderEffect.collapsedFolderReached(g, this); + finally { + iterationState.dispose(); } flushCachedChars(g); @@ -5903,59 +5923,64 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } IterationState state = new IterationState(EditorImpl.this, offset, endOffset, false); - int fontType = state.getMergedAttributes().getFontType(); + try { + int fontType = state.getMergedAttributes().getFontType(); - int maxPreviousSoftWrappedWidth = -1; + int maxPreviousSoftWrappedWidth = -1; - while (offset < documentLength && line < lineCount) { - char c = text.charAt(offset); - if (offset >= state.getEndOffset()) { - state.advance(); - fontType = state.getMergedAttributes().getFontType(); - } - - while (softWrapsIndex < softWraps.size() && line < lineCount) { - SoftWrap softWrap = softWraps.get(softWrapsIndex); - if (softWrap.getStart() > offset) { - break; + while (offset < documentLength && line < lineCount) { + char c = text.charAt(offset); + if (offset >= state.getEndOffset()) { + state.advance(); + fontType = state.getMergedAttributes().getFontType(); } - softWrapsIndex++; - if (softWrap.getStart() == offset) { - maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x); - x = softWrap.getIndentInPixels(); + + while (softWrapsIndex < softWraps.size() && line < lineCount) { + SoftWrap softWrap = softWraps.get(softWrapsIndex); + if (softWrap.getStart() > offset) { + break; + } + softWrapsIndex++; + if (softWrap.getStart() == offset) { + maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x); + x = softWrap.getIndentInPixels(); + } + } + + FoldRegion collapsed = state.getCurrentFold(); + if (collapsed != null) { + String placeholder = collapsed.getPlaceholderText(); + for (int i = 0; i < placeholder.length(); i++) { + x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this); + } + offset = collapsed.getEndOffset(); + line = myDocument.getLineNumber(offset); + } + else if (c == '\t') { + x = EditorUtil.nextTabStop(x, EditorImpl.this); + offset++; + } + else if (c == '\n') { + int width = Math.max(x, maxPreviousSoftWrappedWidth); + myLineWidths.set(line, width); + maxCalculatedLine = Math.max(maxCalculatedLine, line); + if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break; + offset++; + x = 0; + //noinspection AssignmentToForLoopParameter + line++; + if (line == lineCount - 1) { + lastLineLengthCalculated = true; + } + } + else { + x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c, myEditorComponent); + offset++; } } - - FoldRegion collapsed = state.getCurrentFold(); - if (collapsed != null) { - String placeholder = collapsed.getPlaceholderText(); - for (int i = 0; i < placeholder.length(); i++) { - x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this); - } - offset = collapsed.getEndOffset(); - line = myDocument.getLineNumber(offset); - } - else if (c == '\t') { - x = EditorUtil.nextTabStop(x, EditorImpl.this); - offset++; - } - else if (c == '\n') { - int width = Math.max(x, maxPreviousSoftWrappedWidth); - myLineWidths.set(line, width); - maxCalculatedLine = Math.max(maxCalculatedLine, line); - if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break; - offset++; - x = 0; - //noinspection AssignmentToForLoopParameter - line++; - if (line == lineCount - 1) { - lastLineLengthCalculated = true; - } - } - else { - x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c, myEditorComponent); - offset++; - } + } + finally { + state.dispose(); } } @@ -6011,35 +6036,40 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override public int calcColumnNumber(@NotNull CharSequence text, int start, int offset, int tabSize) { IterationState state = new IterationState(this, start, start+offset, false); - int fontType = state.getMergedAttributes().getFontType(); - int column = 0; - int x = 0; - int spaceSize = EditorUtil.getSpaceWidth(fontType, this); - for (int i = start; i < offset; i++) { - if (i >= state.getEndOffset()) { - state.advance(); - fontType = state.getMergedAttributes().getFontType(); + try { + int fontType = state.getMergedAttributes().getFontType(); + int column = 0; + int x = 0; + int spaceSize = EditorUtil.getSpaceWidth(fontType, this); + for (int i = start; i < offset; i++) { + if (i >= state.getEndOffset()) { + state.advance(); + fontType = state.getMergedAttributes().getFontType(); + } + + SoftWrap softWrap = getSoftWrapModel().getSoftWrap(i); + if (softWrap != null) { + column++; // For 'after soft wrap' drawing. + x = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); + } + + char c = text.charAt(i); + if (c == '\t') { + int prevX = x; + x = EditorUtil.nextTabStop(x, this); + column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); + } + else { + x += EditorUtil.charWidth(c, fontType, this); + column++; + } } - SoftWrap softWrap = getSoftWrapModel().getSoftWrap(i); - if (softWrap != null) { - column++; // For 'after soft wrap' drawing. - x = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP); - } - - char c = text.charAt(i); - if (c == '\t') { - int prevX = x; - x = EditorUtil.nextTabStop(x, this); - column += EditorUtil.columnsNumber(c, x, prevX, spaceSize); - } - else { - x += EditorUtil.charWidth(c, fontType, this); - column++; - } + return column; + } + finally { + state.dispose(); } - - return column; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java index 4490e1aca2e3..2367882c16fd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EmptyMarkupModel.java @@ -2,6 +2,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.DisposableIterator; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.ex.SweepProcessor; @@ -13,12 +14,9 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Key; import com.intellij.util.Consumer; import com.intellij.util.Processor; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - /** * This is mock implementation to be used in null-object pattern where necessary. * @author max @@ -126,8 +124,8 @@ public class EmptyMarkupModel implements MarkupModelEx { @NotNull @Override - public Iterator overlappingIterator(int startOffset, int endOffset) { - return ContainerUtil.emptyIterator(); + public DisposableIterator overlappingIterator(int startOffset, int endOffset) { + return DisposableIterator.EMPTY; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java index cfb4c985734f..44250317f389 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java @@ -35,15 +35,13 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -@SuppressWarnings({"ForLoopReplaceableByForEach"}) // Way too many garbage in AbstractList.iterator() produced otherwise. public final class IterationState { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.IterationState"); private final TextAttributes myMergedAttributes = new TextAttributes(); private final HighlighterIterator myHighlighterIterator; - private final HighlighterSweep myView = new HighlighterSweep(); - - private final HighlighterSweep myDoc = new HighlighterSweep(); + private final HighlighterSweep myView; + private final HighlighterSweep myDoc; private int myStartOffset; @@ -71,6 +69,9 @@ public final class IterationState { private final EditorEx myEditor; private final Color myReadOnlyColor; + /** + * You MUST CALL {@link #dispose()} afterwards + */ public IterationState(@NotNull EditorEx editor, int start, int end, boolean useCaretAndSelection) { ApplicationManager.getApplication().assertReadAccessAllowed(); myDocument = (DocumentEx)editor.getDocument(); @@ -104,22 +105,29 @@ public final class IterationState { myCurrentHighlighters = new ArrayList(); MarkupModelEx editorMarkup = (MarkupModelEx)editor.getMarkupModel(); - myView.init(editorMarkup, start, myEnd); + myView = new HighlighterSweep(editorMarkup, start, myEnd); final MarkupModelEx docMarkup = (MarkupModelEx)DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), true); - myDoc.init(docMarkup, start, myEnd); + myDoc = new HighlighterSweep(docMarkup, start, myEnd); myEndOffset = myStartOffset; advance(); } - private class HighlighterSweep { - private RangeHighlighterEx myNextHighlighter = null; - private PushBackIterator myIterator; + public void dispose() { + myView.dispose(); + myDoc.dispose(); + } - private void init(@NotNull MarkupModelEx markupModel, int start, int end) { - myIterator = new PushBackIterator(markupModel.overlappingIterator(start, end)); + private class HighlighterSweep { + private RangeHighlighterEx myNextHighlighter; + private final PushBackIterator myIterator; + private final DisposableIterator myDisposableIterator; + + private HighlighterSweep(@NotNull MarkupModelEx markupModel, int start, int end) { + myDisposableIterator = markupModel.overlappingIterator(start, end); + myIterator = new PushBackIterator(myDisposableIterator); int skipped = 0; while (myIterator.hasNext()) { RangeHighlighterEx highlighter = myIterator.next(); @@ -176,6 +184,10 @@ public final class IterationState { } return Integer.MAX_VALUE; } + + public void dispose() { + myDisposableIterator.dispose(); + } } private boolean skipHighlighter(@NotNull RangeHighlighterEx highlighter) { @@ -230,6 +242,7 @@ public final class IterationState { private int getGuardedBlockEnd(int start) { List blocks = myDocument.getGuardedBlocks(); int min = myEnd; + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < blocks.size(); i++) { RangeMarker block = blocks.get(i); if (block.getStartOffset() > start) { @@ -257,7 +270,6 @@ public final class IterationState { private void advanceSegmentHighlighters() { myDoc.advance(); - myView.advance(); for (int i = myCurrentHighlighters.size() - 1; i >= 0; i--) { @@ -296,6 +308,7 @@ public final class IterationState { private int getMinSegmentHighlightersEnd() { int end = myEnd; + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < myCurrentHighlighters.size(); i++) { RangeHighlighterEx highlighter = myCurrentHighlighters.get(i); if (highlighter.getAffectedAreaEndOffset() < end) { @@ -332,6 +345,7 @@ public final class IterationState { ContainerUtil.quickSort(myCurrentHighlighters, LayerComparator.INSTANCE); } + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < size; i++) { RangeHighlighterEx highlighter = myCurrentHighlighters.get(i); if (highlighter.getTextAttributes() == TextAttributes.ERASE_MARKER) { @@ -342,6 +356,7 @@ public final class IterationState { List cachedAttributes = myCachedAttributesList; cachedAttributes.clear(); + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < size; i++) { RangeHighlighterEx highlighter = myCurrentHighlighters.get(i); if (selection != null && highlighter.getLayer() < HighlighterLayer.SELECTION) { @@ -387,6 +402,7 @@ public final class IterationState { EffectType effectType = null; int fontType = 0; + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < cachedAttributes.size(); i++) { TextAttributes attrs = cachedAttributes.get(i); @@ -453,6 +469,7 @@ public final class IterationState { ContainerUtil.quickSort(myCurrentHighlighters, LayerComparator.INSTANCE); + //noinspection ForLoopReplaceableByForEach for (int i = 0; i < myCurrentHighlighters.size(); i++) { RangeHighlighterEx highlighter = myCurrentHighlighters.get(i); if (caret != null && highlighter.getLayer() < HighlighterLayer.CARET_ROW) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java index e8f4cad9e41a..524082380b9d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java @@ -28,6 +28,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.ex.DisposableIterator; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.ex.SweepProcessor; @@ -45,7 +46,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx { @@ -257,7 +257,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx @Override @NotNull - public Iterator overlappingIterator(int startOffset, int endOffset) { + public DisposableIterator overlappingIterator(int startOffset, int endOffset) { return myHighlighterTree.overlappingIterator(startOffset, endOffset); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 147f41506cd9..1223be9d2e6a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -208,51 +208,56 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume myContext.text = document.getCharsSequence(); myContext.tokenStartOffset = start; IterationState iterationState = new IterationState(myEditor, start, document.getTextLength(), false); - TextAttributes attributes = iterationState.getMergedAttributes(); - myContext.fontType = attributes.getFontType(); - myContext.rangeEndOffset = event.getNewEndOffset(); - - EditorPosition position = new EditorPosition(logical, start, myEditor, myRepresentationHelper); - Point point = myEditor.visualPositionToXY(visual); - position.x = point.x; - int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor); - - myContext.logicalLineData.update(logical.line, spaceWidth, myEditor); - - myContext.currentPosition = position; - myContext.lineStartPosition = position.clone(); - myContext.fontType2spaceWidth.put(myContext.fontType, spaceWidth); - myContext.softWrapStartOffset = position.offset; - - myContext.contentComponent = myEditor.getContentComponent(); - myContext.reservedWidthInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); - - // Perform soft wraps calculation. - while (!iterationState.atEnd() && myContext.currentPosition.offset <= event.getNewEndOffset()) { - FoldRegion currentFold = iterationState.getCurrentFold(); - if (currentFold == null) { - myContext.tokenEndOffset = iterationState.getEndOffset(); - processNonFoldToken(); - } - else { - boolean continueProcessing = processCollapsedFoldRegion(currentFold); - if (!continueProcessing) { - return false; - } - - // 'myOffset2widthInPixels' contains information necessary to processing soft wraps that lay before the current offset. - // We do know that soft wraps are not allowed to go backward after processed collapsed fold region, hence, we drop - // information about processed symbols width. - myOffset2widthInPixels.clear(); - } - - iterationState.advance(); - attributes = iterationState.getMergedAttributes(); + try { + TextAttributes attributes = iterationState.getMergedAttributes(); myContext.fontType = attributes.getFontType(); - myContext.tokenStartOffset = iterationState.getStartOffset(); - myOffset2fontType.fill(myContext.tokenStartOffset, iterationState.getEndOffset(), myContext.fontType); + myContext.rangeEndOffset = event.getNewEndOffset(); + + EditorPosition position = new EditorPosition(logical, start, myEditor, myRepresentationHelper); + Point point = myEditor.visualPositionToXY(visual); + position.x = point.x; + int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor); + + myContext.logicalLineData.update(logical.line, spaceWidth, myEditor); + + myContext.currentPosition = position; + myContext.lineStartPosition = position.clone(); + myContext.fontType2spaceWidth.put(myContext.fontType, spaceWidth); + myContext.softWrapStartOffset = position.offset; + + myContext.contentComponent = myEditor.getContentComponent(); + myContext.reservedWidthInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); + + // Perform soft wraps calculation. + while (!iterationState.atEnd() && myContext.currentPosition.offset <= event.getNewEndOffset()) { + FoldRegion currentFold = iterationState.getCurrentFold(); + if (currentFold == null) { + myContext.tokenEndOffset = iterationState.getEndOffset(); + processNonFoldToken(); + } + else { + boolean continueProcessing = processCollapsedFoldRegion(currentFold); + if (!continueProcessing) { + return false; + } + + // 'myOffset2widthInPixels' contains information necessary to processing soft wraps that lay before the current offset. + // We do know that soft wraps are not allowed to go backward after processed collapsed fold region, hence, we drop + // information about processed symbols width. + myOffset2widthInPixels.clear(); + } + + iterationState.advance(); + attributes = iterationState.getMergedAttributes(); + myContext.fontType = attributes.getFontType(); + myContext.tokenStartOffset = iterationState.getStartOffset(); + myOffset2fontType.fill(myContext.tokenStartOffset, iterationState.getEndOffset(), myContext.fontType); + } + notifyListenersOnVisualLineEnd(); + } + finally { + iterationState.dispose(); } - notifyListenersOnVisualLineEnd(); return true; } From 328a1d267b3c008d9cd69cb237d0fa3f578b2f3d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 23 Nov 2011 12:28:08 +0400 Subject: [PATCH 21/45] crash in injectors in multiroot files during PSI modification of the main root --- .../src/com/intellij/psi/impl/PsiDocumentManagerImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index bf3eca1e8b6d..3ce6ebc02c86 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -371,7 +371,10 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec }); if (ok[0]) { - ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).startRunInjectors(document, synchronously); + // otherwise changes maybe not synced to the document yet, and injectors will crash + if (!mySynchronizer.isDocumentAffectedByTransactions(document)) { + ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).startRunInjectors(document, synchronously); + } // run after commit actions outside write action runAfterCommitActions(document); if (DebugUtil.DO_EXPENSIVE_CHECKS) { From f8f7a14ee5ef51fc05248615688082d64eb7f490 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Nov 2011 17:46:01 +0100 Subject: [PATCH 22/45] do not complete during inplace refactorings --- ...CompletionContributorForInplaceRename.java | 41 +++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 1 + 2 files changed, 42 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/refactoring/rename/inplace/CompletionContributorForInplaceRename.java diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/CompletionContributorForInplaceRename.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/CompletionContributorForInplaceRename.java new file mode 100644 index 000000000000..1a6069b582a9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/CompletionContributorForInplaceRename.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.rename.inplace; + +import com.intellij.codeInsight.completion.CompletionContributor; +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.openapi.editor.Editor; + +/** + * User: anna + * Date: 11/22/11 + */ +public class CompletionContributorForInplaceRename extends CompletionContributor { + + @Override + public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { + final Editor editor = parameters.getLookup().getEditor(); + final TemplateState state = TemplateManagerImpl.getTemplateState(editor); + if (state != null) { + if (editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER) != null) { + result.stopHere(); + } + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index accdf885ecdd..903cfba08491 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -654,6 +654,7 @@ + From 4fd9082b41de402e640fafcfc4dce0e7feea9d3b Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Nov 2011 19:14:52 +0100 Subject: [PATCH 23/45] no more border --- .../intellij/openapi/updateSettings/impl/NoUpdatesPanel.form | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form index 1253b05bd2d0..7d35bc1db405 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form @@ -5,7 +5,7 @@ - + @@ -52,7 +52,7 @@ - + From 1bb7a9c409aac82e5b045b3bb6511c2649779190 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 22 Nov 2011 19:42:16 +0100 Subject: [PATCH 24/45] inplace rename: choose substitutor on start (all choosers should be replaced with popups - to be continued) --- .../rename/inplace/MemberInplaceRenamer.java | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index 353b9b581bab..6635812edf22 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -25,6 +25,7 @@ import com.intellij.openapi.command.impl.FinishMarkAction; import com.intellij.openapi.command.impl.StartMarkAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; @@ -34,6 +35,7 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.rename.RenameProcessor; import com.intellij.refactoring.rename.RenamePsiElementProcessor; @@ -53,10 +55,16 @@ import java.util.List; */ public class MemberInplaceRenamer extends VariableInplaceRenamer { protected final String myOldName; + private final PsiElement mySubstituted; + private RangeMarker mySubstitutedRange; public MemberInplaceRenamer(@NotNull PsiNameIdentifierOwner elementToRename, Editor editor) { super(elementToRename, editor); myOldName = elementToRename.getName(); + final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(elementToRename); + mySubstituted = processor.substituteElementToRename(elementToRename, myEditor); + mySubstitutedRange = mySubstituted != null && mySubstituted != myElementToRename && mySubstituted.getTextRange() != null ? myEditor.getDocument().createRangeMarker(mySubstituted.getTextRange()) : null; + showDialogAdvertisement("RenameElement"); } @@ -99,8 +107,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { final ArrayList references = new ArrayList(super.collectRefs(referencesSearchScope)); final PsiNamedElement variable = getVariable(); if (variable != null) { - final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable); - final PsiElement substituted = processor.substituteElementToRename(variable, myEditor); + final PsiElement substituted = getSubstituted(); if (substituted != null && substituted != variable) { references.addAll(ReferencesSearch.search(substituted, referencesSearchScope, false).findAll()); } @@ -126,11 +133,10 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { boolean showChooser = super.appendAdditionalElement(stringUsages); PsiNamedElement variable = getVariable(); if (variable != null) { - RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable); - final PsiElement substituted = processor.substituteElementToRename(variable, myEditor); + final PsiElement substituted = getSubstituted(); if (substituted != null) { appendAdditionalElement(stringUsages, variable, substituted); - processor = RenamePsiElementProcessor.forElement(substituted); + RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(substituted); final HashMap allRenames = new HashMap(); PsiFile currentFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument()); processor.prepareRenaming(substituted, "", allRenames, new LocalSearchScope(currentFile)); @@ -163,9 +169,8 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { final NamesValidator namesValidator = LanguageNamesValidation.INSTANCE.forLanguage(variable.getLanguage()); LOG.assertTrue(namesValidator != null); if (namesValidator.isIdentifier(newName, myProject)) { - RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable); - final PsiElement substitutedElement = processor.substituteElementToRename(variable, myEditor); - if (substitutedElement == null) { + final PsiElement substituted = getSubstituted(); + if (substituted == null) { return; } @@ -173,13 +178,14 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { .message("renaming.0.1.to.2", UsageViewUtil.getType(variable), UsageViewUtil.getDescriptiveName(variable), newName); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { - final RenamePsiElementProcessor elementProcessor = RenamePsiElementProcessor.forElement(substitutedElement); + + final RenamePsiElementProcessor elementProcessor = RenamePsiElementProcessor.forElement(substituted); final RenameProcessor - renameProcessor = new RenameProcessor(myProject, substitutedElement, newName, - elementProcessor.isToSearchInComments(substitutedElement), - elementProcessor.isToSearchForTextOccurrences(substitutedElement)); + renameProcessor = new RenameProcessor(myProject, substituted, newName, + elementProcessor.isToSearchInComments(substituted), + elementProcessor.isToSearchForTextOccurrences(substituted)); for (AutomaticRenamerFactory factory : Extensions.getExtensions(AutomaticRenamerFactory.EP_NAME)) { - if (factory.isApplicable(substitutedElement) && factory.getOptionName() != null) { + if (factory.isApplicable(substituted) && factory.getOptionName() != null) { if (factory.isEnabled()) { renameProcessor.addRenamerFactory(factory); } @@ -254,4 +260,16 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { if (ex[0] != null) throw ex[0]; return markAction[0]; } + + @Nullable + public PsiElement getSubstituted() { + if (mySubstituted != null && mySubstituted.isValid()) return mySubstituted; + if (mySubstitutedRange != null) { + final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument()); + if (psiFile != null) { + return PsiTreeUtil.getParentOfType(psiFile.findElementAt(mySubstitutedRange.getStartOffset()), PsiNameIdentifierOwner.class); + } + } + return getVariable(); + } } From c29b5854fa968c62d50d278c70d9554018da5fba Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Nov 2011 09:40:29 +0100 Subject: [PATCH 25/45] inplace rename: ask about super method non-modal --- .../ide/util/SuperMethodWarningUtil.java | 52 +++++++++++++++++++ .../java/JavaRefactoringSupportProvider.java | 3 -- .../rename/RenameJavaMethodProcessor.java | 21 ++++++++ .../rename/RenamePsiElementProcessor.java | 13 +++++ .../inplace/MemberInplaceRenameHandler.java | 18 ++++++- .../rename/inplace/MemberInplaceRenamer.java | 5 +- .../inplace/VariableInplaceRenameHandler.java | 29 ++++++----- 7 files changed, 120 insertions(+), 21 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java index ed577175a08c..5ac29a8c7231 100644 --- a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java @@ -16,12 +16,17 @@ package com.intellij.ide.util; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; +import com.intellij.psi.presentation.java.SymbolPresentationUtil; +import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; +import com.intellij.ui.components.JBList; import com.intellij.usageView.UsageViewUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -102,4 +107,51 @@ public class SuperMethodWarningUtil { return null; } + + public static void checkSuperMethod(final PsiMethod method, + final String actionString, + final PsiElementProcessor processor, + final Editor editor) { + PsiClass aClass = method.getContainingClass(); + if (aClass == null) { + processor.execute(method); + return; + } + + PsiMethod superMethod = method.findDeepestSuperMethod(); + if (superMethod == null) { + processor.execute(method); + return; + } + + final PsiClass containingClass = superMethod.getContainingClass(); + if (containingClass == null) { + processor.execute(method); + return; + } + + if (ApplicationManager.getApplication().isUnitTestMode()) { + processor.execute(superMethod); + return; + } + + final PsiMethod[] methods = new PsiMethod[]{superMethod, method}; + final String renameBase = actionString + " base method"; + final String renameCurrent = actionString + " only current method"; + final JBList list = new JBList(renameBase, renameCurrent); + JBPopupFactory.getInstance().createListPopupBuilder(list) + .setTitle(method.getName() + (containingClass.isInterface() && !aClass.isInterface() ? " implements" : " overrides") + " method of " + + SymbolPresentationUtil.getSymbolPresentableText(containingClass)) + .setMovable(false) + .setResizable(false) + .setRequestFocus(true) + .setItemChoosenCallback(new Runnable() { + public void run() { + final Object value = list.getSelectedValue(); + if (value instanceof String) { + processor.execute(methods[value.equals(renameBase) ? 0 : 1]); + } + } + }).createPopup().showInBestPositionFor(editor); + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java index 4ff4ec49cf6a..6d057ff4c795 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java @@ -65,9 +65,6 @@ public class JavaRefactoringSupportProvider extends RefactoringSupportProvider { @Override public boolean isMemberInplaceRenameAvailable(PsiElement elementToRename, PsiElement context) { - if (elementToRename instanceof PsiMethod && ((PsiMethod)elementToRename).findDeepestSuperMethods().length > 0) { - return false; - } return elementToRename instanceof PsiMember; } diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java index 5b751432ed29..2868623dcbaf 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java @@ -18,8 +18,10 @@ package com.intellij.refactoring.rename; import com.intellij.ide.util.SuperMethodWarningUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Pass; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.MethodReferencesSearch; @@ -237,6 +239,25 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor { return SuperMethodWarningUtil.checkSuperMethod(psiMethod, RefactoringBundle.message("to.rename")); } + @Override + public void substituteElementToRename(@NotNull PsiElement element, + @NotNull Editor editor, + @NotNull final Pass renameCallback) { + PsiMethod psiMethod = (PsiMethod)element; + if (psiMethod.isConstructor()) { + super.substituteElementToRename(element, editor, renameCallback); + } + else { + SuperMethodWarningUtil.checkSuperMethod(psiMethod, "Rename", new PsiElementProcessor() { + @Override + public boolean execute(@NotNull PsiMethod method) { + renameCallback.pass(method); + return false; + } + }, editor); + } + } + private static void findSubmemberHidesMemberCollisions(final PsiMethod method, final String newName, final List result) { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java index 3148befc6895..ce040f54e6b1 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java @@ -21,6 +21,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileSystemItem; @@ -161,6 +162,18 @@ public abstract class RenamePsiElementProcessor { return element; } + /** + * Substitutes element to be renamed and initiate rename procedure. Should be used in order to prevent modal dialogs to appear during inplace rename + * @param element the element on which refactoring was invoked + * @param editor the editor in which inplace refactoring was invoked + * @param renameCallback rename procedure which should be called on the chosen substitution + */ + public void substituteElementToRename(@NotNull final PsiElement element, @NotNull Editor editor, @NotNull Pass renameCallback) { + final PsiElement psiElement = substituteElementToRename(element, editor); + if (psiElement == null) return; + renameCallback.pass(psiElement); + } + public void findCollisions(final PsiElement element, final String newName, final Map allRenames, final List result) { } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java index 923abea7ef0f..3000a9961214 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenameHandler.java @@ -18,12 +18,15 @@ package com.intellij.refactoring.rename.inplace; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.lang.refactoring.RefactoringSupportProvider; +import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.rename.RenamePsiElementProcessor; import org.jetbrains.annotations.NotNull; /** @@ -45,9 +48,20 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler { } @Override - protected VariableInplaceRenamer createRenamer(@NotNull PsiElement elementToRename, Editor editor) { + public VariableInplaceRenamer doRename(@NotNull final PsiElement elementToRename, final Editor editor, final DataContext dataContext) { if (elementToRename instanceof PsiNameIdentifierOwner) { - return new MemberInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor); + RenamePsiElementProcessor.forElement(elementToRename).substituteElementToRename(elementToRename, editor, new Pass() { + @Override + public void pass(PsiElement element) { + final MemberInplaceRenamer renamer = new MemberInplaceRenamer((PsiNameIdentifierOwner)elementToRename, element, editor); + boolean startedRename = renamer.performInplaceRename(); + if (!startedRename) { + performDialogRename(elementToRename, editor, dataContext); + } + } + }); + } else { + performDialogRename(elementToRename, editor, dataContext); } return null; } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index 6635812edf22..2e0f6b5f83e8 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -58,11 +58,10 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { private final PsiElement mySubstituted; private RangeMarker mySubstitutedRange; - public MemberInplaceRenamer(@NotNull PsiNameIdentifierOwner elementToRename, Editor editor) { + public MemberInplaceRenamer(@NotNull PsiNameIdentifierOwner elementToRename, PsiElement substituted, Editor editor) { super(elementToRename, editor); myOldName = elementToRename.getName(); - final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(elementToRename); - mySubstituted = processor.substituteElementToRename(elementToRename, myEditor); + mySubstituted = substituted; mySubstitutedRange = mySubstituted != null && mySubstituted != myElementToRename && mySubstituted.getTextRange() != null ? myEditor.getDocument().createRangeMarker(mySubstituted.getTextRange()) : null; showDialogAdvertisement("RenameElement"); diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java index a72a435b9452..cfc21482fab4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java @@ -112,23 +112,26 @@ public class VariableInplaceRenameHandler implements RenameHandler { boolean startedRename = renamer == null ? false : renamer.performInplaceRename(); if (!startedRename) { - try { - ourPreventInlineRenameFlag.set(Boolean.TRUE); - - RenameHandler handler = RenameHandlerRegistry.getInstance().getRenameHandler(dataContext); - assert handler != null; - handler.invoke( - elementToRename.getProject(), - editor, - elementToRename.getContainingFile(), dataContext - ); - } finally { - ourPreventInlineRenameFlag.set(null); - } + performDialogRename(elementToRename, editor, dataContext); } return renamer; } + protected static void performDialogRename(PsiElement elementToRename, Editor editor, DataContext dataContext) { + try { + ourPreventInlineRenameFlag.set(Boolean.TRUE); + RenameHandler handler = RenameHandlerRegistry.getInstance().getRenameHandler(dataContext); + assert handler != null; + handler.invoke( + elementToRename.getProject(), + editor, + elementToRename.getContainingFile(), dataContext + ); + } finally { + ourPreventInlineRenameFlag.set(null); + } + } + @Nullable protected VariableInplaceRenamer createRenamer(@NotNull PsiElement elementToRename, Editor editor) { return new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor); From 897288f36e331accbff7a34a535f1fe14f9b5441 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 23 Nov 2011 12:49:59 +0400 Subject: [PATCH 26/45] [mac] enabling mac sheets dialog back --- platform/platform-resources-en/src/misc/registry.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 30ae23cae219..57df2da3bffa 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -101,7 +101,7 @@ ide.tabbedPane.dragOutMultiplier=1.2 ide.mac.filechooser.showhidden.files=false ide.mac.filechooser.native=true -ide.mac.message.dialogs.as.sheets=false +ide.mac.message.dialogs.as.sheets=true ide.mac.inplaceDialogMnemonicsFix=true debugger.valueTooltipAutoShow=true From 0900779ebe1170b3374a77f75d13a3dc4e0a9822 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Nov 2011 09:45:07 +0100 Subject: [PATCH 27/45] more concise groovy copy-paste test --- .../plugins/groovy/GroovyCopyPasteTest.groovy | 82 +++++++------------ 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy index 03ecee6658ae..e50d513f3a27 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy @@ -25,39 +25,6 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase { int myAddImportsOld - public void testEscapeSlashesInRegex() { - myFixture.configureByText 'a.groovy', 'a/b' - myFixture.performEditorAction IdeActions.ACTION_COPY - myFixture.configureByText 'b.groovy', 'def x = /smth/' - myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult 'def x = /smtha\\/b/' - } - - public void testEscapeSlashesInRegexFromRegex() { - myFixture.configureByText 'a.groovy', 'def x = /a\\/b/' - myFixture.performEditorAction IdeActions.ACTION_COPY - myFixture.configureByText 'b.groovy', 'def x = /smth/' - myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult 'def x = /smtha\\/b/' - } - - void testDontEscapeSymbolsInRegex(){ - myFixture.configureByText 'a.groovy', '''def x = a/b''' - myFixture.performEditorAction IdeActions.ACTION_COPY - myFixture.configureByText 'b.groovy', 'def x = / /' - myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult '''def x = /a\\/b /''' - } - - public void testEscapeDollarInGString() { - myFixture.configureByText 'a.groovy', '''def x = '$ab/''' - myFixture.performEditorAction IdeActions.ACTION_COPY - myFixture.configureByText 'b.groovy', 'def x = "smthh"' - myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult 'def x = "smth\\$ah"' - - } - @Override protected void setUp() throws Exception { super.setUp(); @@ -73,41 +40,50 @@ class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase { settings.ADD_IMPORTS_ON_PASTE = myAddImportsOld; super.tearDown(); } + + private void doTest(String fromFileName, String fromText, String toText, String expected) { + myFixture.configureByText fromFileName, fromText + myFixture.performEditorAction IdeActions.ACTION_COPY + myFixture.configureByText 'b.groovy', toText + myFixture.performEditorAction IdeActions.ACTION_PASTE + myFixture.checkResult expected + } + + public void testEscapeSlashesInRegex() { + doTest 'a.groovy', 'a/b', 'def x = /smth/', 'def x = /smtha\\/b/' + } + + public void testEscapeSlashesInRegexFromRegex() { + doTest 'a.groovy', 'def x = /a\\/b/', 'def x = /smth/', 'def x = /smtha\\/b/' + } + + void testDontEscapeSymbolsInRegex(){ + doTest 'a.groovy', '''def x = a/b''', 'def x = / /', '''def x = /a\\/b /''' + } + + public void testEscapeDollarInGString() { + doTest 'a.groovy', '''def x = '$ab/''', 'def x = "smthh"', 'def x = "smth\\$ah"' + + } public void testRestoreImports() { myFixture.addClass("package foo; public class Foo {}") - myFixture.configureByText 'a.groovy', '''import foo.*; Foo f''' - myFixture.performEditorAction IdeActions.ACTION_COPY - myFixture.configureByText 'b.groovy', '' - myFixture.performEditorAction IdeActions.ACTION_PASTE - myFixture.checkResult '''import foo.Foo + doTest 'a.groovy', '''import foo.*; Foo f''', '', '''import foo.Foo 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"""' + doTest 'a.txt', 'a/b\nc/d', 'def x = """smth"""', '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'" + doTest 'a.txt', 'a\nd', "def x = 'smth'", "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"' + doTest 'a.txt', 'a\nd', 'def x = "smth"', 'def x = "smtha\\n" +\n "d"' } } From c1242b0c71f045c28b9b04be324ea3ef43316d3b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Nov 2011 09:55:10 +0100 Subject: [PATCH 28/45] paste the last \n into gstring --- .../StringLiteralCopyPasteProcessor.java | 7 ++++--- .../plugins/groovy/GroovyCopyPasteTest.groovy | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) 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 1c0f2fadb351..1f6c01625a0d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/StringLiteralCopyPasteProcessor.java @@ -144,9 +144,10 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor { @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]; - buffer.append(escapeCharCharacters(line, token, escapeSlashes)); - if (i != lines.length - 1) buffer.append(breaker); + buffer.append(escapeCharCharacters(lines[i], token, escapeSlashes)); + if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) { + buffer.append(breaker); + } } text = buffer.toString(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy index e50d513f3a27..068f9efe47d3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCopyPasteTest.groovy @@ -86,4 +86,18 @@ Foo f''' doTest 'a.txt', 'a\nd', 'def x = "smth"', 'def x = "smtha\\n" +\n "d"' } + public void testGStringEolReplace() throws Exception { + doTest 'a.txt', + '''first +second +''', + '''def x = """ +foo +"""''', + '''def x = """ +first +second +"""''' + } + } From 35c3898cc9c2c88b815c949aa6053d231c2ba13f Mon Sep 17 00:00:00 2001 From: Serega Vasiliev Date: Wed, 23 Nov 2011 10:03:27 +0100 Subject: [PATCH 29/45] Play! more rename and usages searches (IDEA-76155 , IDEA-76814) --- .../expressions/literals/GrLiteral.java | 1 + .../literals/GrAbstractLiteral.java | 21 +++++++++++++++++++ .../expressions/literals/GrLiteralImpl.java | 2 +- .../expressions/literals/GrStringImpl.java | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrAbstractLiteral.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/literals/GrLiteral.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/literals/GrLiteral.java index 797684b0d03c..f543c5aea6cb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/literals/GrLiteral.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/literals/GrLiteral.java @@ -23,4 +23,5 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres * @author ilyas */ public interface GrLiteral extends GrExpression, PsiLiteral { + void setStringValue(String value); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrAbstractLiteral.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrAbstractLiteral.java new file mode 100644 index 000000000000..e41ec6c04f85 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrAbstractLiteral.java @@ -0,0 +1,21 @@ +package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals; + +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; +import org.jetbrains.plugins.groovy.lang.resolve.GroovyStringLiteralManipulator; + + +public abstract class GrAbstractLiteral extends GrExpressionImpl implements GrLiteral { + + public GrAbstractLiteral(@NotNull ASTNode node) { + super(node); + } + + @Override + public void setStringValue(String value) { + new GroovyStringLiteralManipulator().handleContentChange(this, value); + + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java index 704e5df0b239..d97758a4f99d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java @@ -43,7 +43,7 @@ import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; /** * @author ilyas */ -public class GrLiteralImpl extends GrExpressionImpl implements GrLiteral, PsiLanguageInjectionHost { +public class GrLiteralImpl extends GrAbstractLiteral implements GrLiteral, PsiLanguageInjectionHost { private static final Function TYPE_CALCULATOR = new NullableFunction() { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java index 16a2964096a6..161f3a5bded8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java @@ -35,7 +35,7 @@ import java.util.List; /** * @author ilyas */ -public class GrStringImpl extends GrExpressionImpl implements GrString { +public class GrStringImpl extends GrAbstractLiteral implements GrString { private static final Function TYPE_CALCULATOR = new Function() { @Override public PsiType fun(GrStringImpl grString) { From 4d4662fb9e33869d21f2141f3c8a7b3226ed50cd Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 23 Nov 2011 10:27:52 +0400 Subject: [PATCH 30/45] rebuild index on IllegalStateException --- .../src/com/intellij/util/indexing/FileBasedIndex.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index b587d056ad2d..ddd44b1fec11 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -932,7 +932,8 @@ public class FileBasedIndex implements ApplicationComponent { public static @Nullable Throwable getCauseToRebuildIndex(RuntimeException e) { Throwable cause = e.getCause(); - if (cause instanceof StorageException || cause instanceof IOException || cause instanceof IllegalArgumentException) return cause; + if (cause instanceof StorageException || cause instanceof IOException || + cause instanceof IllegalArgumentException || cause instanceof IllegalStateException) return cause; return null; } From 1280a26af6dc186e07abdb84ef0f624c83f1641a Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 23 Nov 2011 13:27:24 +0400 Subject: [PATCH 31/45] log for IDEA-77314 Unable to save changes in a file --- .../src/com/intellij/util/io/SafeFileOutputStream.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java index 89ec8f587cdd..c804d70068b7 100644 --- a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java +++ b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java @@ -16,6 +16,7 @@ package com.intellij.util.io; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileSystemUtil; import com.intellij.openapi.util.io.FileUtil; @@ -25,6 +26,7 @@ import java.io.*; * @author max */ public class SafeFileOutputStream extends OutputStream { + private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.SafeFileOutputStream"); private final File myTargetFile; private final boolean myPreserveAttributes; private final OutputStream myBackDoorStream; @@ -51,6 +53,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b); } catch (IOException e) { + LOG.info(e); failed = true; throw e; } @@ -61,6 +64,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b); } catch (IOException e) { + LOG.info(e); failed = true; throw e; } @@ -72,6 +76,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b, off, len); } catch (IOException e) { + LOG.info(e); failed = true; throw e; } @@ -83,6 +88,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.flush(); } catch (IOException e) { + LOG.info(e); failed = true; throw e; } @@ -94,6 +100,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.close(); } catch (IOException e) { + LOG.info(e); FileUtil.delete(backdoorFile()); throw e; } From 0868ae10d9b3632d69dd158dcb045d92a5dfe025 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 23 Nov 2011 10:28:40 +0100 Subject: [PATCH 32/45] drop subtag cache on changes in non-physical files, should fix tests --- .../src/com/intellij/psi/impl/PsiCachedValue.java | 8 ++++++-- .../src/com/intellij/psi/impl/source/xml/XmlTagImpl.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiCachedValue.java b/platform/core-impl/src/com/intellij/psi/impl/PsiCachedValue.java index 63b1f02e988d..808a1cfcb7fc 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiCachedValue.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiCachedValue.java @@ -52,9 +52,13 @@ public abstract class PsiCachedValue extends CachedValueBase { @Override protected boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) { - return !(dependency instanceof PsiElement && myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) && - super.isDependencyOutOfDate(dependency, oldTimeStamp); + if (dependency instanceof PsiElement && + myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount() && + ((PsiElement)dependency).isPhysical()) { + return false; + } + return super.isDependencyOutOfDate(dependency, oldTimeStamp); } @Override diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java index e9493f197f39..fbe5ae568fa5 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java @@ -615,7 +615,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag { final int s = result.size(); XmlTag[] tags = s > 0 ? ContainerUtil.toArray(result, new XmlTag[s]) : EMPTY; - return Result.create(tags, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); + return Result.create(tags, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, getContainingFile()); } }); From b9b477c1bac146163689fe4bc7516292a9c2c920 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 23 Nov 2011 13:18:11 +0300 Subject: [PATCH 33/45] IDEA-77414 Fix Git pull hang: don't fire new Task under the Task.Modal, just execute synchronously. --- plugins/git4idea/src/git4idea/actions/GitPull.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java index c5c475bd3b87..8c0e88b435b7 100644 --- a/plugins/git4idea/src/git4idea/actions/GitPull.java +++ b/plugins/git4idea/src/git4idea/actions/GitPull.java @@ -68,7 +68,7 @@ public class GitPull extends GitRepositoryAction { final Label beforeLabel = LocalHistory.getInstance().putSystemLabel(project, "Before update"); final AtomicReference handlerReference = new AtomicReference(); - new Task.Modal(project, GitBundle.message("pulling.title", dialog.getRemote()), false) { + new Task.Modal(project, GitBundle.message("pulling.title", dialog.getRemote()), true) { @Override public void run(@NotNull ProgressIndicator indicator) { GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(dialog.gitRoot()); @@ -103,8 +103,9 @@ public class GitPull extends GitRepositoryAction { final GitRevisionNumber currentRev = new GitRevisionNumber(revision); GitTask pullTask = new GitTask(project, handlerReference.get(), GitBundle.message("pulling.title", dialog.getRemote())); + pullTask.setProgressIndicator(indicator); pullTask.setProgressAnalyzer(new GitStandardProgressAnalyzer()); - pullTask.executeModal(new GitTaskResultHandlerAdapter() { + pullTask.execute(true, false, new GitTaskResultHandlerAdapter() { @Override protected void onSuccess() { GitMergeUtil.showUpdates(GitPull.this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE); From 771a66f13931d6e794c9f3939baa3a9578519dfe Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 23 Nov 2011 13:42:18 +0400 Subject: [PATCH 34/45] ui: smaller tabs + smaller font in tool windows --- platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java | 2 +- .../src/com/intellij/openapi/wm/impl/content/BaseLabel.java | 2 +- .../intellij/openapi/wm/impl/content/ToolWindowContentUi.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java b/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java index 15d51220864b..8857856e9e24 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java @@ -23,7 +23,7 @@ import javax.swing.*; public class TabsUtil { - public static final int TAB_VERTICAL_PADDING = 3; + public static final int TAB_VERTICAL_PADDING = 2; public static final int TABS_BORDER = 1; private TabsUtil() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/BaseLabel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/BaseLabel.java index b1a9ace36ab6..98f97d14f67d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/BaseLabel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/BaseLabel.java @@ -53,7 +53,7 @@ class BaseLabel extends JLabel { private void updateFont() { Font f = UIUtil.getLabelFont(); - Font baseFont = f.deriveFont(f.getStyle(), Math.max(11, f.getSize() - 1)); + Font baseFont = f.deriveFont(f.getStyle(), Math.max(11, f.getSize() - 2)); if (myBold) { setFont(baseFont.deriveFont(Font.BOLD)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java index c68fd27fe509..e6e2a8771718 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/content/ToolWindowContentUi.java @@ -70,7 +70,6 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh ContentLayout myComboLayout = new ComboContentLayout(this); private ToolWindowContentUiType myType = ToolWindowContentUiType.TABBED; - private DefaultActionGroup ourGroup; private static DefaultActionGroup myGroup; public ToolWindowContentUi(ToolWindowImpl window) { From a3626238341a86848d1723073eb1806f1f94e994 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 22 Nov 2011 22:54:38 +0400 Subject: [PATCH 35/45] return if generating of android structure failed --- .../org/jetbrains/android/newProject/AndroidModuleBuilder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index 904d7d0a03a6..b515b1cf7964 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -289,6 +289,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { if (contentRoot.findChild(SdkConstants.FN_ANDROID_MANIFEST_XML) == null) { AndroidUtils.printMessageToConsole(project, "The project wasn't generated by 'android' tool.", ConsoleViewContentType.ERROR_OUTPUT); + return; } ApplicationManager.getApplication().runWriteAction(new Runnable() { From 62f302a182d5e65d6d50b712e79e7e580d129a26 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 22 Nov 2011 22:57:25 +0400 Subject: [PATCH 36/45] android logcat: fix double filtering --- .../jetbrains/android/logcat/AndroidLogcatToolWindowView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java index 05fb6df1b761..a1a5079dee9f 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java @@ -234,6 +234,10 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { myFiltersList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; + } + final String filterName = (String)myFiltersList.getSelectedValue(); final ConfiguredFilter filter = filterName != null ? compileConfiguredFilter(filterName) : null; From 9cf8dbff857b7ab81ac9ab559fb3b3c178ad5616 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 23 Nov 2011 14:14:55 +0400 Subject: [PATCH 37/45] fix printMessage return value --- .../src/com/intellij/diagnostic/logging/LogConsoleBase.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java index 9fe65cf86f29..15aeb82e00ce 100644 --- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java +++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleBase.java @@ -409,6 +409,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L myConsole.print(fragment.getText(), consoleViewType); } } + return true; } else { final LogFilterModel.MyProcessingResult processingResult = myModel.processLine(line); @@ -422,11 +423,12 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L myConsole.print(messagePrefix, type); } myConsole.print(line + "\n", type); + return true; } } } + return false; } - return true; } @NotNull From e658a47c41ffd2bcc610a1c0f19a27ef957a033b Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Nov 2011 10:53:23 +0100 Subject: [PATCH 38/45] todos: select node in builder should build and expand the node (IDEA-77199 ) --- .../src/com/intellij/ide/todo/TodoPanel.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java index 8bdff105e2bc..9c9d047842d5 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java @@ -503,17 +503,7 @@ abstract class TodoPanel extends SimpleToolWindowPanel implements OccurenceNavig @Nullable private OccurenceInfo goToPointer(TodoItemNode pointer) { if (pointer == null) return null; - DefaultMutableTreeNode node = myTodoTreeBuilder.getNodeForElement(pointer); - if (node == null) { - myTodoTreeBuilder.buildNodeForElement(pointer); - node = myTodoTreeBuilder.getNodeForElement(pointer); - if (node == null) { - // TODO[vova] it seems that this check isn't required any more bacause it was side effect of SCR#7063 - // TODO[vova] try to remove this check in Aurora - return null; - } - } - TreeUtil.selectPath(myTree, new TreePath(node.getPath())); + myTodoTreeBuilder.select(pointer); return new OccurenceInfo( new OpenFileDescriptor(myProject, pointer.getValue().getTodoItem().getFile().getVirtualFile(), pointer.getValue().getRangeMarker().getStartOffset()), From f3a21318816bea134fe6e01112527aa2731bfbd0 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Nov 2011 10:54:28 +0100 Subject: [PATCH 39/45] todos: select node in builder should build and expand the node (IDEA-77199 ) --- platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java index 9c9d047842d5..c87c226cd8ef 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java @@ -51,7 +51,6 @@ import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.OpenSourceUtil; import com.intellij.util.PlatformIcons; import com.intellij.util.ui.UIUtil; -import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; From ddbcdda15945cd05bed042c54124ee40207c3870 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 23 Nov 2011 11:13:31 +0100 Subject: [PATCH 40/45] plugins: update existing descriptor if it exists (IDEA-77448 ) --- .../ide/plugins/ActionInstallPlugin.java | 2 +- .../ide/plugins/InstalledPluginsManagerMain.java | 2 +- .../ide/plugins/InstalledPluginsTableModel.java | 16 +++++++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java index 7f1a1df6ac93..b3b3e68ee128 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java @@ -104,7 +104,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } final InstalledPluginsTableModel installedPluginsModel = (InstalledPluginsTableModel)installed.getPluginsModel(); for (PluginNode node : list) { - installedPluginsModel.appendDescriptor(node); + installedPluginsModel.appendOrUpdateDescriptor(node); } installed.setRequireShutdown(true); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java index b3248aafaee9..3bb9aebc9941 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java @@ -91,7 +91,7 @@ public class InstalledPluginsManagerMain extends PluginManagerMain { return; } PluginDownloader.install(file, file.getName()); - ((InstalledPluginsTableModel)pluginsModel).appendDescriptor(pluginDescriptor); + ((InstalledPluginsTableModel)pluginsModel).appendOrUpdateDescriptor(pluginDescriptor); select(pluginDescriptor); setRequireShutdown(true); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index 011c686fa62d..cd64322fe318 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -84,11 +84,17 @@ public class InstalledPluginsTableModel extends PluginTableModel { setSortKey(new RowSorter.SortKey(getNameColumn(), SortOrder.ASCENDING)); } - public void appendDescriptor(IdeaPluginDescriptor descriptor) { - myInstalled.add(descriptor); - view.add(descriptor); - setEnabled(descriptor, true); - fireTableDataChanged(); + public void appendOrUpdateDescriptor(IdeaPluginDescriptor descriptor) { + final PluginId descrId = descriptor.getPluginId(); + final IdeaPluginDescriptor existing = PluginManager.getPlugin(descrId); + if (existing != null) { + updateExistingPluginInfo(descriptor, existing); + } else { + myInstalled.add(descriptor); + view.add(descriptor); + setEnabled(descriptor, true); + fireTableDataChanged(); + } } public static int getCheckboxColumn() { From b143ac659c0f89a1c12dcaee41a26a38fcad6a7b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 23 Nov 2011 11:24:32 +0100 Subject: [PATCH 41/45] Stricter logging for IDEA-77314 --- .../com/intellij/util/io/SafeFileOutputStream.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java index c804d70068b7..5790a8e29d05 100644 --- a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java +++ b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java @@ -27,6 +27,7 @@ import java.io.*; */ public class SafeFileOutputStream extends OutputStream { private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.SafeFileOutputStream"); + private final File myTargetFile; private final boolean myPreserveAttributes; private final OutputStream myBackDoorStream; @@ -53,7 +54,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b); } catch (IOException e) { - LOG.info(e); + LOG.warn(e); failed = true; throw e; } @@ -64,7 +65,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b); } catch (IOException e) { - LOG.info(e); + LOG.warn(e); failed = true; throw e; } @@ -76,7 +77,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.write(b, off, len); } catch (IOException e) { - LOG.info(e); + LOG.warn(e); failed = true; throw e; } @@ -88,7 +89,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.flush(); } catch (IOException e) { - LOG.info(e); + LOG.warn(e); failed = true; throw e; } @@ -100,7 +101,7 @@ public class SafeFileOutputStream extends OutputStream { myBackDoorStream.close(); } catch (IOException e) { - LOG.info(e); + LOG.warn(e); FileUtil.delete(backdoorFile()); throw e; } From dd111c563a249e915374da3a11078fd4ce21a706 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 23 Nov 2011 15:32:34 +0400 Subject: [PATCH 42/45] new ui: selected tab underline is redone for horizontal labs + brighter inactive tabs --- .../src/com/intellij/ui/tabs/TabsUtil.java | 4 +- .../intellij/ui/tabs/impl/JBEditorTabs.java | 88 +++++++++++-------- .../com/intellij/ui/tabs/impl/TabLabel.java | 7 +- .../ui/tabs/impl/table/TableLayout.java | 11 ++- 4 files changed, 66 insertions(+), 44 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java b/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java index 8857856e9e24..2867db54a040 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/TabsUtil.java @@ -24,7 +24,9 @@ public class TabsUtil { public static final int TAB_VERTICAL_PADDING = 2; - public static final int TABS_BORDER = 1; + public static final int TABS_BORDER = 1; + + public static final int ACTIVE_TAB_UNDERLINE_HEIGHT = 4; private TabsUtil() { } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java index fa976ff25a98..e90c37554186 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.tabs.JBTabsPosition; import com.intellij.ui.tabs.TabInfo; +import com.intellij.ui.tabs.TabsUtil; import com.intellij.util.ui.SameColor; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -69,16 +70,24 @@ public class JBEditorTabs extends JBTabsImpl { int _height = effectiveBounds.height - insets.top - insets.bottom; + if ((!isSingleRow() && label.getBounds().y > 0 /* for multiline */) || (isSingleRow() && isHorizontalTabs())) { + if (isSingleRow() && getPosition() == JBTabsPosition.bottom) { + _y += TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + } else { + _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + } + } + Color tabColor = label.getInfo().getTabColor(); if (tabColor != null) { //g2d.setPaint(new LinearGradientPaint(_x, _y, _x, _y + effectiveBounds.height, new float[] {.3f, .6f, 1f}, new Color[] {new SameColor(170), new SameColor(150), new SameColor(90)})); - g2d.setPaint(new GradientPaint(_x, _y, new SameColor(170), _x, _y + effectiveBounds.height, new SameColor(150))); + g2d.setPaint(new GradientPaint(_x, _y, new SameColor(200), _x, _y + effectiveBounds.height, new SameColor(130))); g2d.fillRect(_x, _y, _width, _height); g2d.setColor(new Color(tabColor.getRed(), tabColor.getGreen(), tabColor.getBlue(), 150)); g2d.fillRect(_x, _y, _width, _height); } else { - g2d.setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 140), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 90))); + g2d.setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 180), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 100))); g2d.fillRect(_x, _y, _width, _height); } @@ -130,7 +139,9 @@ public class JBEditorTabs extends JBTabsImpl { int y = r2.y + insets.top; int height = maxLength - insets.top - insets.bottom; if (getTabsPosition() == JBTabsPosition.bottom) { - y = r2.height - height - insets.top; + y = r2.height - height - insets.top + TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + } else { + height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; } rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height); @@ -163,22 +174,20 @@ public class JBEditorTabs extends JBTabsImpl { int _x = r.x; int _y = r.y; int _height = r.height; - - //g2d.setColor(Color.WHITE); - //g2d.draw( - // selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY() - // - selectedShape.labelPath.deltaY(3), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(3))); + if (getPosition() == JBTabsPosition.left || getPosition() == JBTabsPosition.right) { + g2d.setColor(new Color(0, 0, 0, 45)); + g2d.draw( + selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY() + - selectedShape.labelPath.deltaY(4), selectedShape.path.getMaxX(), + selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(4))); - g2d.setColor(new Color(0, 0, 0, 45)); - g2d.draw( - selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY() - - selectedShape.labelPath.deltaY(4), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(4))); - - g2d.setColor(new Color(0, 0, 0, 15)); - g2d.draw( - selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY() - - selectedShape.labelPath.deltaY(5), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(5))); + g2d.setColor(new Color(0, 0, 0, 15)); + g2d.draw( + selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY() + - selectedShape.labelPath.deltaY(5), selectedShape.path.getMaxX(), + selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(5))); + } Color tabColor = label.getInfo().getTabColor(); if (tabColor != null) { @@ -201,26 +210,31 @@ public class JBEditorTabs extends JBTabsImpl { selectedShape.labelPath.deltaY(1), selectedShape.labelPath.getMaxX() - selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(4))); - - // side shadow - g2d.setColor(new Color(0, 0, 0, 30)); - g2d.draw(selectedShape.labelPath - .transformLine(selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getY() + - selectedShape.labelPath.deltaY(1), - selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() - - selectedShape.labelPath.deltaY(4))); - - boolean horizontal = getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom; - - g2d.draw(selectedShape.labelPath - .transformLine(selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), selectedShape.labelPath.getY() + - selectedShape.labelPath.deltaY(1), - selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), selectedShape.labelPath.getMaxY() - - selectedShape.labelPath.deltaY(4))); + + if (!isHorizontalTabs()) { + // side shadow + g2d.setColor(new Color(0, 0, 0, 30)); + g2d.draw(selectedShape.labelPath + .transformLine(selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getY() + + selectedShape.labelPath.deltaY(1), + selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() - + selectedShape.labelPath.deltaY(4))); + + boolean horizontal = getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom; + + g2d.draw(selectedShape.labelPath + .transformLine(selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), + selectedShape.labelPath.getY() + + selectedShape.labelPath.deltaY(1), + selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), + selectedShape.labelPath.getMaxY() - + selectedShape.labelPath.deltaY(4))); + } g2d.setColor(new Color(0, 0, 0, 50)); g2d.draw(selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY(), - selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY())); + selectedShape.path.getMaxX(), + selectedShape.labelPath.getMaxY())); } @Override @@ -235,7 +249,7 @@ public class JBEditorTabs extends JBTabsImpl { shape.insets = shape.path.transformInsets(getLayoutInsets()); shape.labelPath = shape.path.createTransform(getSelectedLabel().getBounds()); - shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(3); + shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1); shape.labelTopY = shape.labelPath.getY() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? shape.labelPath.deltaY(1) : 0) ; shape.labelLeftX = shape.labelPath.getX() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? 0 : shape.labelPath.deltaX( @@ -253,8 +267,8 @@ public class JBEditorTabs extends JBTabsImpl { int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right); shape.path.lineTo(lastX, shape.labelBottomY); - shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(3)); - shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(3)); + shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); + shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); shape.path.closePath(); shape.fillPath = shape.path.copy(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index 6d958b1affe1..628d5b9c8063 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -29,6 +29,7 @@ import com.intellij.ui.SimpleColoredText; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.tabs.JBTabsPosition; import com.intellij.ui.tabs.TabInfo; +import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.UiDecorator; import com.intellij.util.PairConsumer; import com.intellij.util.ui.Centerizer; @@ -223,11 +224,11 @@ public class TabLabel extends JPanel { } private int getNonSelectedOffset() { - return myTabs.isEditorTabs() ? 0 : 2; + return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 2; } private int getSelectedOffset() { - return myTabs.isEditorTabs() ? 0 : 1; + return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 1; } @Override @@ -236,7 +237,7 @@ public class TabLabel extends JPanel { final JBTabsPosition pos = myTabs.getTabsPosition(); switch (pos) { - case top: case bottom: size.height += getSelectedOffset(); break; + case top: case bottom: size.height += myTabs.isEditorTabs() ? TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT : getSelectedOffset(); break; case left: case right: size.width += getSelectedOffset(); break; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index 9468df0f63dd..c1d7fae5c1e4 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -16,6 +16,7 @@ package com.intellij.ui.tabs.impl.table; import com.intellij.ui.tabs.TabInfo; +import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.LayoutPassInfo; import com.intellij.ui.tabs.impl.TabLabel; @@ -118,6 +119,9 @@ public class TableLayout extends TabLayout { final Insets insets = myTabs.getLayoutInsets(); int eachY = insets.top; int eachX; + int row = 0; + final int tabUnderlineFix = myTabs.isEditorTabs() ? TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT : 0; + for (TableRow eachRow : data.table) { eachX = insets.left; @@ -142,14 +146,15 @@ public class TableLayout extends TabLayout { width = data.toFitRec.width + insets.left - eachX; } - - myTabs.layout(label, eachX, eachY, width, myTabs.myHeaderFitSize.height); + myTabs.layout(label, eachX, eachY, width, row < data.table.size() - 1 ? myTabs.myHeaderFitSize.height - tabUnderlineFix : myTabs.myHeaderFitSize.height); label.setAligmentToCenter(deltaToFit > 0); boolean lastCell = i == eachRow.myColumns.size() - 1; eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength()); } - eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength(); + eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0); + + row++; } if (myTabs.getSelectedInfo() != null) { From e91b9a3e9f4f6dee70fe298606df665b83058718 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 23 Nov 2011 12:33:12 +0100 Subject: [PATCH 43/45] Stricter logging for IDEA-77314 --- .../src/com/intellij/util/io/SafeFileOutputStream.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java index 5790a8e29d05..4eaa949a306a 100644 --- a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java +++ b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java @@ -106,9 +106,13 @@ public class SafeFileOutputStream extends OutputStream { throw e; } + if (failed) { + throw new IOException("Failed to save to backup file (" + backdoorFile() + "). Original file (" + myTargetFile + ") left unchanged."); + } + final int permissions = myPreserveAttributes ? FileSystemUtil.getPermissions(myTargetFile) : -1; - if (failed || !FileUtil.delete(myTargetFile)) { - throw new IOException("Failed to save to " + myTargetFile + ". No data were harmed. Attempt result left at " + backdoorFile()); + if (!FileUtil.delete(myTargetFile) && myTargetFile.exists()) { + throw new IOException("Failed to save to " + myTargetFile + ". The file left unchanged. Attempt result stored to " + backdoorFile()); } FileUtil.rename(backdoorFile(), myTargetFile); From 027d228e34d2798a974589d1f76b27e4900b5a99 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 23 Nov 2011 13:09:52 +0300 Subject: [PATCH 44/45] EA-31539 - assert: CaretModelImpl.moveToOffset Debug info is added --- .../openapi/editor/impl/CaretModelImpl.java | 85 ++++++++++++++----- .../openapi/editor/impl/EditorImpl.java | 9 +- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 23f96b40b3c2..b1276690d020 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.List; @@ -186,21 +187,21 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, public void moveToOffset(int offset, boolean locateBeforeSoftWrap) { assertIsDispatchThread(); validateCallContext(); - moveToLogicalPosition(myEditor.offsetToLogicalPosition(offset), locateBeforeSoftWrap); - if (!ignoreWrongMoves && !myEditor.offsetToLogicalPosition(myOffset).equals(myEditor.offsetToLogicalPosition(offset))) { - StringBuilder documentInfo = new StringBuilder(); - Document document = myEditor.getDocument(); - for (int line = 0; line < document.getLineCount(); line++) { - documentInfo.append(line).append(": ").append(document.getLineStartOffset(line)).append("-") - .append(document.getLineEndOffset(line)).append(", "); - } - if (documentInfo.length() > 0) { - documentInfo.setLength(documentInfo.length() - 1); - } + final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset); + moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null); + if (!ignoreWrongMoves && !myEditor.offsetToLogicalPosition(myOffset).equals(logicalPosition)) { + StringBuilder debugBuffer = new StringBuilder(); + moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, debugBuffer); + int textStart = Math.max(0, Math.min(offset, myOffset) - 1); + final DocumentEx document = myEditor.getDocument(); + int textEnd = Math.min(document.getTextLength() - 1, Math.max(offset, myOffset) + 1); + CharSequence text = document.getCharsSequence().subSequence(textStart, textEnd); LOG.error( - "caret moved to wrong offset. Requested: offset=" + offset + ", logical position=" + myEditor.offsetToLogicalPosition(offset) + "caret moved to wrong offset. Requested: offset=" + offset + ", logical position=" + logicalPosition + " but actual: offset=" + myOffset + ", logical position=" + myLogicalCaret + "(" + myEditor.offsetToLogicalPosition(myOffset) + "). " + myEditor.dumpState() + + "\n interested text [" + textStart + "; " + textEnd + "): '" + text + "'" + + "\n debug trace: " + debugBuffer ); } } @@ -361,11 +362,16 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, @Override public void moveToLogicalPosition(@NotNull LogicalPosition pos) { - moveToLogicalPosition(pos, false); + moveToLogicalPosition(pos, false, null); } - private void moveToLogicalPosition(LogicalPosition pos, boolean locateBeforeSoftWrap) { + private void moveToLogicalPosition(@NotNull LogicalPosition pos, boolean locateBeforeSoftWrap, @Nullable StringBuilder debugBuffer) { assertIsDispatchThread(); + if (debugBuffer != null) { + debugBuffer.append(String.format( + "Start moveToLogicalPosition(). Locate before soft wrap: %b, position: %s", locateBeforeSoftWrap, pos + )); + } myDesiredX = -1; validateCallContext(); int column = pos.column; @@ -377,10 +383,16 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, Document doc = myEditor.getDocument(); if (column < 0) { + if (debugBuffer != null) { + debugBuffer.append("Resetting target logical column to zero as it is negative (" + column + ")"); + } column = 0; softWrapColumns = 0; } if (line < 0) { + if (debugBuffer != null) { + debugBuffer.append("Resetting target logical line to zero as it is negative (" + line + ")"); + } line = 0; softWrapLinesBefore = 0; softWrapLinesCurrent = 0; @@ -388,9 +400,17 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, int lineCount = doc.getLineCount(); if (lineCount == 0) { + if (debugBuffer != null) { + debugBuffer.append("Resetting target logical line to zero as the document is empty"); + } line = 0; } else if (line > lineCount - 1) { + if (debugBuffer != null) { + debugBuffer.append(String.format( + "Resetting target logical line (%d) to %d as it is greater than total document lines number", line, lineCount - 1 + )); + } line = lineCount - 1; softWrapLinesBefore = 0; softWrapLinesCurrent = 0; @@ -400,12 +420,21 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, if (!editorSettings.isVirtualSpace() && line < lineCount && !myEditor.getSelectionModel().hasBlockSelection()) { int lineEndOffset = doc.getLineEndOffset(line); - int lineEndColumnNumber = myEditor.offsetToLogicalPosition(lineEndOffset).column; + final LogicalPosition endLinePosition = myEditor.offsetToLogicalPosition(lineEndOffset); + int lineEndColumnNumber = endLinePosition.column; if (column > lineEndColumnNumber) { + int oldColumn = column; column = lineEndColumnNumber; if (softWrapColumns != 0) { softWrapColumns -= column - lineEndColumnNumber; } + if (debugBuffer != null) { + debugBuffer.append(String.format( + "Resetting target logical column (%d) to %d because caret is not allowed to be located after line end (offset: %d, " + + "logical position: %s). Current soft wrap columns value: %d", + oldColumn, lineEndColumnNumber, lineEndOffset, endLinePosition, softWrapColumns + )); + } } } @@ -424,12 +453,17 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, logicalPositionToUse = new LogicalPosition(line, column); } setCurrentLogicalCaret(logicalPositionToUse); - final int offset = myEditor.logicalPositionToOffset(myLogicalCaret); + if (debugBuffer != null) { + debugBuffer.append(String.format("Resulting logical position to use: %s. It's mapped to offset %d", myLogicalCaret, offset)); + } FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset); if (collapsedAt != null && offset > collapsedAt.getStartOffset()) { + if (debugBuffer != null) { + debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt); + } Runnable runnable = new Runnable() { @Override public void run() { @@ -447,6 +481,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret); myOffset = myEditor.logicalPositionToOffset(myLogicalCaret); + if (debugBuffer != null) { + debugBuffer.append(String.format("Storing offset %d (mapped from logical position %s)", myOffset, myLogicalCaret)); + } LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength()); myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0))); @@ -458,7 +495,13 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) { int lineToUse = myVisibleCaret.line - 1; if (lineToUse >= 0) { - moveToVisualPosition(new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse))); + final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse)); + if (debugBuffer != null) { + debugBuffer.append(String.format( + "Adjusting caret position by moving it before soft wrap. Moving to visual position %s", visualPosition + )); + } + moveToVisualPosition(visualPosition); return; } } @@ -561,7 +604,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, finishUpdate(); DocumentEventImpl event = (DocumentEventImpl)e; - final Document document = myEditor.getDocument(); + final DocumentEx document = myEditor.getDocument(); boolean performSoftWrapAdjustment = e.getNewLength() > 0 // We want to put caret just after the last added symbol // There is a possible case that the user removes text just before the soft wrap. We want to keep caret // on a visual line with soft wrap start then. @@ -576,7 +619,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, final int line; try { line = event.translateLineViaDiff(myLogicalCaret.line); - moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment); + moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null); } catch (FilesTooBigForDiffException e1) { LOG.info(e1); @@ -585,7 +628,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } } else { - if (document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate()) return; + if (document.isInBulkUpdate()) return; int startOffset = e.getOffset(); int oldEndOffset = startOffset + e.getOldLength(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 28f0d87f11a8..0f734a719b31 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2499,8 +2499,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } public String dumpState() { - return "use soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off") + ", soft wraps data: " + getSoftWrapModel() - + "\n\nfolding data: " + getFoldingModel() + "\n\ndocument info: " + myDocument.dumpState(); + return "prefix: '" + (myPrefixText == null ? "none" : new String(myPrefixText)) + + "', allow caret inside tab: " + mySettings.isCaretInsideTabs() + + ", allow caret after line end: " + mySettings.isVirtualSpace() + + ", soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off") + + ", soft wraps data: " + getSoftWrapModel() + + "\n\nfolding data: " + getFoldingModel() + + "\n\ndocument info: " + myDocument.dumpState(); } private class CachedFontContent { From 77d8890d0c55ed8af78b39f5a404fe6b3e111324 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 23 Nov 2011 15:35:22 +0300 Subject: [PATCH 45/45] IDEA-77099 IDEA hangs after double "Fold Code Block" action 1. Corrected editor processing when fold model is in progress; 2. Corresponding test is added; --- .../codeInsight/folding/JavaFoldingTest.groovy | 16 ++++++++++++++++ .../intellij/openapi/editor/impl/EditorImpl.java | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy index d1f635da2d34..638ccbecab47 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy @@ -60,6 +60,22 @@ class Foo { List a; Map b; } assertEquals 0, foldRegion.startOffset assertEquals text.indexOf("import") - 1, foldRegion.endOffset } + + public void testSubsequentCollapseBlock() { + def text = """\ +class Test { + void test(int i) { + if (i > 1) { + i++; + } + } +} +""" + configure text + myFixture.performEditorAction 'CollapseBlock' + myFixture.performEditorAction 'CollapseBlock' + assertEquals(text.indexOf('}', text.indexOf('i++')), myFixture.editor.caretModel.offset) + } private def configure(String text) { myFixture.configureByText("a.java", text) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 0f734a719b31..60a9d8783f57 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -3330,6 +3330,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi while (start <= end) { i = (start + end) / 2; FoldRegion region = topLevelCollapsed[i]; + if (!region.isValid()) { + // Folding model is inconsistent (update in progress). + return null; + } int regionVisualLine = offsetToVisualLine(region.getEndOffset() - 1); if (regionVisualLine < visualPos.line) { start = i + 1;