From 0f31b1251bfdfbec25b01a3a0a705844cabcf4f7 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 9 Dec 2011 16:36:37 +0400 Subject: [PATCH 1/3] IDEA-78616 Soft wraps: Correct processing when tab size is changed 1. Soft wraps are recalculated if tad width is changed; 2. Corresponding test has been added; --- .../openapi/editor/impl/EditorImpl.java | 2 +- .../editor/impl/SoftWrapModelImpl.java | 27 ++++++++++++++++++- ...apApplianceOnDocumentModificationTest.java | 23 ++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) 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 238cc7a0472e..6ecddea85a1e 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 @@ -590,10 +590,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi boolean softWrapsUsedBefore = mySoftWrapModel.isSoftWrappingEnabled(); + mySettings.reinitSettings(); mySoftWrapModel.reinitSettings(); myCaretModel.reinitSettings(); mySelectionModel.reinitSettings(); - mySettings.reinitSettings(); ourCaretBlinkingCommand.setBlinkCaret(mySettings.isBlinkCaret()); ourCaretBlinkingCommand.setBlinkPeriod(mySettings.getCaretBlinkPeriod()); mySizeContainer.reset(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index 934dff74cecd..74c0dc309a23 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -25,6 +25,10 @@ import com.intellij.openapi.editor.ex.*; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.softwrap.*; import com.intellij.openapi.editor.impl.softwrap.mapping.*; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.reference.SoftReference; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,6 +96,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi /** Holds number of 'active' calls, i.e. number of methods calls of the current object within the current call stack. */ private int myActive; private boolean myUseSoftWraps; + private int myTabWidth = -1; /** * Standard IJ editor starts showing horizontal scroll bar event when text line ends couple of symbols before the right visual @@ -191,7 +196,13 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi boolean softWrapsUsedBefore = myUseSoftWraps; EditorSettings settings = myEditor.getSettings(); myUseSoftWraps = settings.isUseSoftWraps(); - if (myUseSoftWraps && (!softWrapsUsedBefore || settings.getAdditionalColumnsCount() > 0)) { + + int tabWidthBefore = myTabWidth; + myTabWidth = getCurrentTabWidth(); + + if ((myUseSoftWraps && (!softWrapsUsedBefore || settings.getAdditionalColumnsCount() > 0)) + || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore)) + { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myAdditionalColumnsCount = settings.getAdditionalColumnsCount(); @@ -203,6 +214,20 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } + /** + * @return tab width for the file used at the current editor (if it's possible to calculate the one); + * '-1' otherwise + */ + private int getCurrentTabWidth() { + final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(myEditor.getProject()); + final VirtualFile file = myEditor.getVirtualFile(); + if (file == null) { + return -1; + } + final CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(file.getFileType()); + return indentOptions.TAB_SIZE; + } + @Override public boolean isSoftWrappingEnabled() { if (!myUseSoftWraps || myEditor.isOneLineMode()) { diff --git a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index 1f6a4865e5c4..28ffb0cbe25e 100644 --- a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.impl.AbstractEditorProcessingOnDocumentModifi import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.testFramework.TestFileType; import gnu.trove.TIntHashSet; import gnu.trove.TIntProcedure; @@ -848,6 +849,28 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP assertEquals(visualPosition, getEditor().logicalToVisualPosition(logicalPosition)); assertEquals(logicalPosition, getEditor().visualToLogicalPosition(visualPosition)); } + + public void testSoftWrapsRecalculationOnTabWidthChange() throws IOException { + // Inspired by IDEA-78616 - the point is to recalculate soft wraps when tab width is changed. + String text = + "\t my text"; + + // Build soft wraps cache. + init(300, text); + + VisualPosition caretPositionBefore = getEditor().getCaretModel().getVisualPosition(); + + // Change tab size. + final CommonCodeStyleSettings.IndentOptions indentOptions = getCurrentCodeStyleSettings().getIndentOptions(); + assertNotNull(indentOptions); + indentOptions.TAB_SIZE++; + + ((EditorImpl)getEditor()).reinitSettings(); + assertEquals( + new VisualPosition(caretPositionBefore.line, caretPositionBefore.column + 1), + getEditor().getCaretModel().getVisualPosition() + ); + } private void init(final int visibleWidth, @NotNull String fileText) throws IOException { init(visibleWidth, fileText, TestFileType.TEXT); From 11d383c9964d5934f1f24be03106455f6700b136 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 9 Dec 2011 18:54:11 +0400 Subject: [PATCH 2/3] IDEA-74108 Editor always scrolled to the top when selected using 'Recent Files' action (Ctrl-e) EditorHistoryManager is notified by active editor change after it. The problem is that it's not possible to derive FileEditorProvider for the old editor when no tabs are shown. However, the provider is known during the event construction, so, it's just wrapped there. --- .../fileEditor/FileEditorManagerEvent.java | 54 +++++++++++++++---- .../fileEditor/impl/EditorHistoryManager.java | 26 ++++++--- .../impl/FileEditorManagerImpl.java | 45 ++++++++++------ 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerEvent.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerEvent.java index 390c16a32678..3509643e267d 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerEvent.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerEvent.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. @@ -16,44 +16,78 @@ package com.intellij.openapi.fileEditor; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.EventObject; public final class FileEditorManagerEvent extends EventObject { - private final VirtualFile myOldFile; - private final FileEditor myOldEditor; - private final VirtualFile myNewFile; - private final FileEditor myNewEditor; - public FileEditorManagerEvent(FileEditorManager source, - VirtualFile oldFile, - FileEditor oldEditor, - VirtualFile newFile, - FileEditor newEditor) { + private final VirtualFile myOldFile; + private final FileEditor myOldEditor; + private final VirtualFile myNewFile; + private final FileEditor myNewEditor; + private final FileEditorProvider myOldProvider; + private final FileEditorProvider myNewProvider; + + public FileEditorManagerEvent(@NotNull FileEditorManager source, + @Nullable VirtualFile oldFile, + @Nullable FileEditor oldEditor, + @Nullable VirtualFile newFile, + @Nullable FileEditor newEditor) + { + this(source, oldFile, oldEditor, null, newFile, newEditor, null); + } + + public FileEditorManagerEvent(@NotNull FileEditorManager source, + @Nullable VirtualFile oldFile, + @Nullable FileEditor oldEditor, + @Nullable FileEditorProvider oldProvider, + @Nullable VirtualFile newFile, + @Nullable FileEditor newEditor, + @Nullable FileEditorProvider newProvider) + { super(source); myOldFile = oldFile; myOldEditor = oldEditor; myNewFile = newFile; myNewEditor = newEditor; + myOldProvider = oldProvider; + myNewProvider = newProvider; } + @NotNull public FileEditorManager getManager(){ return (FileEditorManager)getSource(); } + @Nullable public VirtualFile getOldFile() { return myOldFile; } + @Nullable public VirtualFile getNewFile() { return myNewFile; } + @Nullable public FileEditor getOldEditor() { return myOldEditor; } + @Nullable public FileEditor getNewEditor() { return myNewEditor; } + + @Nullable + public FileEditorProvider getOldProvider() { + return myOldProvider; + } + + @Nullable + public FileEditorProvider getNewProvider() { + return myNewProvider; + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java index c9126d1b3371..a6d987f4f0ff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.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. @@ -34,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.ArrayUtil; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -143,14 +144,28 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme trimToSize(); } } - - private void updateHistoryEntry(final VirtualFile file, final boolean changeEntryOrderOnly){ + + private void updateHistoryEntry(@Nullable final VirtualFile file, final boolean changeEntryOrderOnly) { + updateHistoryEntry(file, null, null, changeEntryOrderOnly); + } + + private void updateHistoryEntry(@Nullable final VirtualFile file, + @Nullable final FileEditor fallbackEditor, + @Nullable FileEditorProvider fallbackProvider, + final boolean changeEntryOrderOnly) + { if (file == null){ return; } final FileEditorManagerEx editorManager = FileEditorManagerEx.getInstanceEx(myProject); final Pair editorsWithProviders = editorManager.getEditorsWithProviders(file); - final FileEditor[] editors = editorsWithProviders.getFirst(); + FileEditor[] editors = editorsWithProviders.getFirst(); + FileEditorProvider[] providers = editorsWithProviders.getSecond(); + if (editors.length <= 0 && fallbackEditor != null) { + editors = new FileEditor[] {fallbackEditor}; + providers = new FileEditorProvider[] {fallbackProvider}; + } + if (editors.length == 0) { // obviously not opened in any editor at the moment, // makes no sense to put the file in the history @@ -167,7 +182,6 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme } if (!changeEntryOrderOnly) { // update entry state - final FileEditorProvider [] providers = editorsWithProviders.getSecond(); //LOG.assertTrue(editors.length > 0); for (int i = editors.length - 1; i >= 0; i--) { final FileEditor editor = editors [i]; @@ -311,7 +325,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme } public void selectionChanged(final FileEditorManagerEvent event){ - updateHistoryEntry(event.getOldFile(), false); + updateHistoryEntry(event.getOldFile(), event.getOldEditor(), event.getOldProvider(), false); updateHistoryEntry(event.getNewFile(), true); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index e2877d3d6831..1406ba0523b2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.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. @@ -1318,26 +1318,20 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } public void fireSelectionChanged(final EditorComposite oldSelectedComposite, final EditorComposite newSelectedComposite) { - final VirtualFile oldSelectedFile = oldSelectedComposite != null ? oldSelectedComposite.getFile() : null; - final VirtualFile newSelectedFile = newSelectedComposite != null ? newSelectedComposite.getFile() : null; - - final FileEditor oldSelectedEditor = - oldSelectedComposite != null && !oldSelectedComposite.isDisposed() ? oldSelectedComposite.getSelectedEditor() : null; - final FileEditor newSelectedEditor = - newSelectedComposite != null && !newSelectedComposite.isDisposed() ? newSelectedComposite.getSelectedEditor() : null; - - final boolean filesEqual = oldSelectedFile == null ? newSelectedFile == null : oldSelectedFile.equals(newSelectedFile); - final boolean editorsEqual = oldSelectedEditor == null ? newSelectedEditor == null : oldSelectedEditor.equals(newSelectedEditor); + final Trinity oldData = extract(oldSelectedComposite); + final Trinity newData = extract(newSelectedComposite); + final boolean filesEqual = oldData.first == null ? newData.first == null : oldData.first.equals(newData.first); + final boolean editorsEqual = oldData.second == null ? newData.second == null : oldData.second.equals(newData.second); if (!filesEqual || !editorsEqual) { final FileEditorManagerEvent event = - new FileEditorManagerEvent(this, oldSelectedFile, oldSelectedEditor, newSelectedFile, newSelectedEditor); + new FileEditorManagerEvent(this, oldData.first, oldData.second, oldData.third, newData.first, newData.second, newData.third); final FileEditorManagerListener publisher = getProject().getMessageBus().syncPublisher(FileEditorManagerListener.FILE_EDITOR_MANAGER); - if (newSelectedEditor != null) { - final JComponent component = newSelectedEditor.getComponent(); + if (newData.first != null) { + final JComponent component = newData.second.getComponent(); final EditorWindowHolder holder = UIUtil.getParentOfType(EditorWindowHolder.class, component); if (holder != null) { - addSelectionRecord(newSelectedFile, holder.getEditorWindow()); + addSelectionRecord(newData.first, holder.getEditorWindow()); } } notifyPublisher(new Runnable() { @@ -1348,7 +1342,26 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec }); } } - + + @NotNull + private static Trinity extract(@Nullable EditorComposite composite) { + final VirtualFile file; + final FileEditor editor; + final FileEditorProvider provider; + if (composite == null || composite.isDisposed()) { + file = null; + editor = null; + provider = null; + } + else { + file = composite.getFile(); + final Pair pair = composite.getSelectedEditorWithProvider(); + editor = pair.first; + provider = pair.second; + } + return new Trinity(file, editor, provider); + } + public boolean isChanged(@NotNull final EditorComposite editor) { final FileStatusManager fileStatusManager = FileStatusManager.getInstance(myProject); if (fileStatusManager != null) { From 56723c4b173ca4e4cf29adf0fc5bf96ecc5c744b Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 9 Dec 2011 19:58:41 +0400 Subject: [PATCH 3/3] IDEA-78370 --- .../codeInspection/dataFlow/DfaMemoryStateImpl.java | 2 ++ .../inspection/dataFlow/IDEADEV78370/expected.xml | 3 +++ .../inspection/dataFlow/IDEADEV78370/src/NoWarnings.java | 8 ++++++++ .../intellij/codeInspection/DataFlowInspectionTest.java | 1 + 4 files changed, 14 insertions(+) create mode 100644 java/java-tests/testData/inspection/dataFlow/IDEADEV78370/expected.xml create mode 100644 java/java-tests/testData/inspection/dataFlow/IDEADEV78370/src/NoWarnings.java diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index f28f743b041f..e291c92f2bcd 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -257,6 +257,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState { } public void setVarValue(DfaVariableValue var, DfaValue value) { + if (var == value) return; + flushVariable(var); if (value instanceof DfaUnknownValue) return; diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/expected.xml b/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/expected.xml new file mode 100644 index 000000000000..ec272abeaa3a --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/expected.xml @@ -0,0 +1,3 @@ + + + diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/src/NoWarnings.java b/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/src/NoWarnings.java new file mode 100644 index 000000000000..ace2d06e1df9 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV78370/src/NoWarnings.java @@ -0,0 +1,8 @@ +import org.jetbrains.annotations.Nullable; + +public class NoWarnings { + int f(@Nullable String value) { + value = value == null ? "" : value; + return value.hashCode(); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index c2b1a252839e..dc0428ae3fa8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -81,6 +81,7 @@ public class DataFlowInspectionTest extends InspectionTestCase { public void testIDEADEV74518() throws Exception { doTest(); } public void testIDEADEV74518_2() throws Exception { doTest(); } public void testIDEADEV77819() throws Exception { doTest(); } + public void testIDEADEV78370() throws Exception { doTest(); } public void testRegressionByPti() throws Exception { doTest(); }