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(); } 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/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/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) { 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);