From 8d87e3013c9f760e9f110ef067bec7263b6c9b08 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 16:13:49 +0300 Subject: [PATCH 01/16] IDEA-97142 IDEA-138653 diff: add action to switch current side, scrolling to the 'related' position --- .../actions/impl/FocusOppositePaneAction.java | 17 +++++++++----- .../diff/tools/binary/BinaryDiffViewer.java | 2 +- .../diff/tools/simple/SimpleDiffViewer.java | 4 ++-- .../diff/tools/util/BaseSyncScrollable.java | 4 ++-- .../diff/tools/util/SyncScrollSupport.java | 11 +++++++++- .../util/twoside/TwosideTextDiffViewer.java | 22 ++++++++++++++++++- .../src/messages/ActionsBundle.properties | 5 ++++- .../src/idea/Keymap_Default.xml | 6 +++++ .../src/idea/PlatformActions.xml | 4 +++- .../openapi/keymap/KeymapsTestCase.java | 2 ++ 10 files changed, 62 insertions(+), 15 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/actions/impl/FocusOppositePaneAction.java b/platform/diff-impl/src/com/intellij/diff/actions/impl/FocusOppositePaneAction.java index 84e99cc783b9..3415e681255f 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/impl/FocusOppositePaneAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/impl/FocusOppositePaneAction.java @@ -15,18 +15,23 @@ */ package com.intellij.diff.actions.impl; -import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.actionSystem.ShortcutSet; +import com.intellij.openapi.actionSystem.EmptyAction; import com.intellij.openapi.project.DumbAware; import org.jetbrains.annotations.NotNull; import javax.swing.*; public class FocusOppositePaneAction extends AnAction implements DumbAware { + protected final boolean myScrollToPosition; + public FocusOppositePaneAction() { + this(false); + } + + public FocusOppositePaneAction(boolean scrollToPosition) { + myScrollToPosition = scrollToPosition; setEnabledInModalContext(true); } @@ -35,8 +40,8 @@ public class FocusOppositePaneAction extends AnAction implements DumbAware { throw new UnsupportedOperationException(); } - public void setupAction(@NotNull JComponent component, @NotNull Disposable disposable) { - ShortcutSet shortcutSet = CustomShortcutSet.fromString("control TAB"); // TODO: allow to change shortcut - registerCustomShortcutSet(shortcutSet, component, disposable); + public void setupAction(@NotNull JComponent component) { + String action = myScrollToPosition ? "Diff.FocusOppositePaneAndScroll" : "Diff.FocusOppositePane"; + EmptyAction.setupAction(this, action, component); } } \ No newline at end of file diff --git a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java index 51fc0d7f4da7..f682a5ed86a6 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffViewer.java @@ -108,7 +108,7 @@ public class BinaryDiffViewer extends ListenerDiffViewerBase { myStatusPanel = new MyStatusPanel(); - new MyFocusOppositePaneAction().setupAction(myPanel, this); + new MyFocusOppositePaneAction().setupAction(myPanel); installEditorListeners(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index 57774f6f6d99..97b302c7ad69 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -819,12 +819,12 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { return getTextSettings().isEnableSyncScroll(); } - public int transfer(@NotNull Side side, int line) { + public int transfer(@NotNull Side baseSide, int line) { if (myDiffChanges.isEmpty()) { return line; } - return super.transfer(side, line); + return super.transfer(baseSide, line); } @Override diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/BaseSyncScrollable.java b/platform/diff-impl/src/com/intellij/diff/tools/util/BaseSyncScrollable.java index f02380b50839..e546c5f298e0 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/BaseSyncScrollable.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/BaseSyncScrollable.java @@ -29,8 +29,8 @@ public abstract class BaseSyncScrollable implements SyncScrollSupport.SyncScroll */ protected abstract void processHelper(@NotNull ScrollHelper helper); - public int transfer(@NotNull Side side, int line) { - ScrollHelper helper = new ScrollHelper(side, line); + public int transfer(@NotNull Side baseSide, int line) { + ScrollHelper helper = new ScrollHelper(baseSide, line); processHelper(helper); int master1 = helper.getMaster1(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java b/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java index dbaffab0a4eb..68788e3b9030 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/SyncScrollSupport.java @@ -35,7 +35,7 @@ public class SyncScrollSupport { boolean isSyncScrollEnabled(); @CalledInAwt - int transfer(@NotNull Side side, int line); + int transfer(@NotNull Side baseSide, int line); } public static class TwosideSyncScrollSupport { @@ -73,6 +73,15 @@ public class SyncScrollSupport { myDuringSyncScroll = false; } } + + @NotNull + public SyncScrollable getScrollable() { + return myScrollable; + } + + public boolean isDuringSyncScroll() { + return myDuringSyncScroll; + } } public static class ThreesideSyncScrollSupport { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java index 96689115da21..0e37c71bbb47 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java @@ -109,7 +109,8 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { myPanel = new TwosideTextDiffPanel(this, myContentPanel, this, context); - new MyFocusOppositePaneAction().setupAction(myPanel, this); + new MyFocusOppositePaneAction(true).setupAction(myPanel); + new MyFocusOppositePaneAction(false).setupAction(myPanel); myEditorSettingsAction = new MySetEditorSettingsAction(); myEditorSettingsAction.applyDefaults(); @@ -315,6 +316,14 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { // Abstract // + @CalledInAwt + @NotNull + protected LogicalPosition transferPosition(@NotNull Side baseSide, @NotNull LogicalPosition position) { + if (mySyncScrollListener == null) return position; + int line = mySyncScrollListener.getScrollable().transfer(baseSide, position.line); + return new LogicalPosition(line, position.column); + } + @CalledInAwt protected void scrollToLine(@NotNull Side side, int line) { Editor editor = side.select(myEditor1, myEditor2); @@ -388,10 +397,21 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { // private class MyFocusOppositePaneAction extends FocusOppositePaneAction { + public MyFocusOppositePaneAction(boolean scrollToPosition) { + super(scrollToPosition); + } + @Override public void actionPerformed(@NotNull AnActionEvent e) { if (myEditor1 == null || myEditor2 == null) return; + if (myScrollToPosition) { + EditorEx currentEditor = myCurrentSide.select(myEditor1, myEditor2); + EditorEx targetEditor = myCurrentSide.other().select(myEditor1, myEditor2); + LogicalPosition position = transferPosition(myCurrentSide, currentEditor.getCaretModel().getLogicalPosition()); + targetEditor.getCaretModel().moveToLogicalPosition(position); + } + myCurrentSide = myCurrentSide.other(); myPanel.requestFocus(); getCurrentEditor().getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 090327bf29ee..ba924d074f3c 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -1221,7 +1221,10 @@ action.VcsHistory.ShowAllAffected.description=Show all changes made in the chose action.AddFrameworkSupport.text=Add Framework Support... -action.Diff.FocusOppositePane.text=Select opposite pane in diff view +action.Diff.FocusOppositePane.text=Select Opposite Diff Pane +action.Diff.FocusOppositePane.description=Select opposite pane in diff view +action.Diff.FocusOppositePaneAndScroll.text=Select Position In Opposite Diff Pane +action.Diff.FocusOppositePaneAndScroll.description=Select the same position in opposite pane in diff view action.Diff.PrevChange.text=Compare Previous File action.Diff.NextChange.text=Compare Next File action.Diff.SelectedChange.text=Choose File To Compare diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 5ce4479f0491..1e5154284f9e 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -547,6 +547,12 @@ + + + + + + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 30ed1acea257..339d402bca62 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -162,7 +162,9 @@ - + + + diff --git a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java index 4dd45a7df4ba..172811192142 100644 --- a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java +++ b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java @@ -132,6 +132,8 @@ public abstract class KeymapsTestCase extends PlatformTestCase { { "shift control U", "ShelveChanges.UnshelveWithDialog", "EditorToggleCase"}, { "control E", "RecentFiles", "Vcs.ShowMessageHistory"}, { "control alt Z", "Vcs.RollbackChangedLines", "ChangesView.Revert"}, + { "control TAB", "Switcher", "Diff.FocusOppositePane"}, + { "shift control TAB", "Switcher", "Diff.FocusOppositePaneAndScroll"}, }); put("Mac OS X 10.5+", new String[][] { { "F5", "CopyElement", "Console.TableResult.Reload", "UML.ApplyCurrentLayout"}, From e4ee9f6d04c77d23188fa88507dbeb4847266e44 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 17:11:06 +0300 Subject: [PATCH 02/16] diff: cleanup - remove duplicated field --- .../openapi/vcs/changes/CacheChangeProcessor.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java index 314c0dcf3f8a..2df8cad37e62 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java @@ -43,8 +43,6 @@ import java.util.List; public abstract class CacheChangeProcessor extends DiffRequestProcessor { private static final Logger LOG = Logger.getInstance(CacheChangeProcessor.class); - @NotNull private final Project myProject; - @NotNull private final SoftHardCacheMap> myRequestCache = new SoftHardCacheMap>(5, 5); @@ -54,12 +52,10 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor { public CacheChangeProcessor(@NotNull Project project) { super(project); - myProject = project; } public CacheChangeProcessor(@NotNull Project project, @NotNull String place) { super(project, place); - myProject = project; } // @@ -133,7 +129,7 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor { @NotNull @CalledInBackground private DiffRequest loadRequest(@NotNull Change change, @NotNull ProgressIndicator indicator) { - ChangeDiffRequestProducer presentable = ChangeDiffRequestProducer.create(myProject, change); + ChangeDiffRequestProducer presentable = ChangeDiffRequestProducer.create(getProject(), change); if (presentable == null) return new ErrorDiffRequest("Can't show diff"); try { return presentable.process(getContext(), indicator); @@ -162,6 +158,12 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor { myRequestCache.clear(); } + @NotNull + @Override + public Project getProject() { + return super.getProject(); + } + // // Navigation // From 737d7b8ecfc647c1dae0674f88692f4b32e13ac0 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 17:34:46 +0300 Subject: [PATCH 03/16] diff: detect FileType in "Compare clipboard with selection" from diff viewer --- .../com/intellij/diff/DiffContentFactory.java | 3 ++ .../intellij/diff/DiffContentFactoryImpl.java | 7 +++++ .../CompareClipboardWithSelectionAction.java | 28 +++++++++++++++++-- .../diff/tools/util/DiffDataKeys.java | 2 ++ .../tools/util/base/TextDiffViewerBase.java | 3 +- .../threeside/ThreesideTextDiffViewer.java | 12 ++++++-- .../util/twoside/TwosideTextDiffViewer.java | 14 +++++++--- 7 files changed, 57 insertions(+), 12 deletions(-) diff --git a/platform/diff-api/src/com/intellij/diff/DiffContentFactory.java b/platform/diff-api/src/com/intellij/diff/DiffContentFactory.java index ffe4824fed78..98e5745c2b8d 100644 --- a/platform/diff-api/src/com/intellij/diff/DiffContentFactory.java +++ b/platform/diff-api/src/com/intellij/diff/DiffContentFactory.java @@ -52,6 +52,9 @@ public abstract class DiffContentFactory { @NotNull public abstract DocumentContent create(@Nullable Project project, @NotNull Document document); + @NotNull + public abstract DocumentContent create(@Nullable Project project, @NotNull Document document, @Nullable FileType fileType); + @NotNull public abstract DocumentContent create(@Nullable Project project, @NotNull Document document, @Nullable VirtualFile file); diff --git a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java index f342f7a378d7..a98a4c8dae75 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java @@ -77,7 +77,14 @@ public class DiffContentFactoryImpl extends DiffContentFactory { @Override @NotNull public DocumentContent create(@Nullable Project project, @NotNull Document document) { + return create(project, document, (FileType)null); + } + + @Override + @NotNull + public DocumentContent create(@Nullable Project project, @NotNull Document document, @Nullable FileType fileType) { VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (file == null) return new DocumentContentImpl(document, fileType, null, null, null); return create(project, document, file); } diff --git a/platform/diff-impl/src/com/intellij/diff/actions/CompareClipboardWithSelectionAction.java b/platform/diff-impl/src/com/intellij/diff/actions/CompareClipboardWithSelectionAction.java index 560728a6f6a1..1474e012cda2 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/CompareClipboardWithSelectionAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/CompareClipboardWithSelectionAction.java @@ -17,9 +17,12 @@ package com.intellij.diff.actions; import com.intellij.diff.DiffContentFactory; import com.intellij.diff.DiffRequestFactory; +import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.requests.SimpleDiffRequest; +import com.intellij.diff.tools.util.DiffDataKeys; import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -28,6 +31,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; @@ -49,6 +54,22 @@ public class CompareClipboardWithSelectionAction extends BaseShowDiffAction { return null; } + @Nullable + private static FileType getEditorFileType(@NotNull AnActionEvent e) { + DiffContent content = e.getData(DiffDataKeys.CURRENT_CONTENT); + if (content != null && content.getContentType() != null) return content.getContentType(); + + DiffRequest request = e.getData(DiffDataKeys.DIFF_REQUEST); + if (request != null && request instanceof ContentDiffRequest) { + for (DiffContent diffContent : ((ContentDiffRequest)request).getContents()) { + FileType type = diffContent.getContentType(); + if (type != null && type != UnknownFileType.INSTANCE) return type; + } + } + + return null; + } + @Override protected boolean isAvailable(@NotNull AnActionEvent e) { Editor editor = getEditor(e); @@ -60,9 +81,10 @@ public class CompareClipboardWithSelectionAction extends BaseShowDiffAction { protected DiffRequest getDiffRequest(@NotNull AnActionEvent e) { Project project = e.getRequiredData(CommonDataKeys.PROJECT); Editor editor = getEditor(e); + FileType editorFileType = getEditorFileType(e); assert editor != null; - DocumentContent content2 = createContent(project, editor); + DocumentContent content2 = createContent(project, editor, editorFileType); DocumentContent content1 = DiffContentFactory.getInstance().createClipboardContent(content2); String title1 = DiffBundle.message("diff.content.clipboard.content.title"); @@ -78,8 +100,8 @@ public class CompareClipboardWithSelectionAction extends BaseShowDiffAction { } @NotNull - private static DocumentContent createContent(@NotNull Project project, @NotNull Editor editor) { - DocumentContent content = DiffContentFactory.getInstance().create(project, editor.getDocument()); + private static DocumentContent createContent(@NotNull Project project, @NotNull Editor editor, @Nullable FileType type) { + DocumentContent content = DiffContentFactory.getInstance().create(project, editor.getDocument(), type); SelectionModel selectionModel = editor.getSelectionModel(); if (selectionModel.hasSelection()) { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java index e9c274e3ace5..94f2fe6c1537 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java @@ -17,6 +17,7 @@ package com.intellij.diff.tools.util; import com.intellij.diff.DiffContext; import com.intellij.diff.FrameDiffTool; +import com.intellij.diff.contents.DiffContent; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.editor.Editor; @@ -24,6 +25,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor; public interface DiffDataKeys { DataKey CURRENT_EDITOR = DataKey.create("diff_current_editor"); + DataKey CURRENT_CONTENT = DataKey.create("diff_current_content"); DataKey DIFF_REQUEST = DataKey.create("diff_request"); DataKey DIFF_CONTEXT = DataKey.create("diff_context"); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerBase.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerBase.java index 2ecd2fbca6f8..28753c454b6c 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerBase.java @@ -26,7 +26,6 @@ import com.intellij.diff.util.DiffUtil; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.event.EditorMouseEvent; import com.intellij.openapi.editor.ex.EditorEx; @@ -114,7 +113,7 @@ public abstract class TextDiffViewerBase extends ListenerDiffViewerBase { @NotNull protected List createEditorPopupActions() { return ContainerUtil.list( - ActionManager.getInstance().getAction("CompareClipboardWithSelection") // TODO: pass FileType to DataContext for highlighting + ActionManager.getInstance().getAction("CompareClipboardWithSelection") ); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java index 244f81e4a138..076134271e1d 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java @@ -262,6 +262,11 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase { return myCurrentSide.select(myEditors); } + @NotNull + public DocumentContent getCurrentContent() { + return myCurrentSide.select(myActualContents); + } + @NotNull @Override protected List getEditors() { @@ -306,10 +311,8 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase { protected OpenFileDescriptor getOpenFileDescriptor() { EditorEx editor = getCurrentEditor(); - DocumentContent content = getCurrentSide().select(myActualContents); - int offset = editor.getCaretModel().getOffset(); - return content.getOpenFileDescriptor(offset); + return getCurrentContent().getOpenFileDescriptor(offset); } public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) { @@ -392,6 +395,9 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase { if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { return getCurrentEditor(); } + else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) { + return getCurrentContent(); + } return super.getData(dataId); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java index 0e37c71bbb47..6ae251d9c390 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java @@ -302,6 +302,12 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { return getCurrentSide().isLeft() ? myEditor1 : myEditor2; } + @NotNull + public DocumentContent getCurrentContent() { + //noinspection ConstantConditions + return getCurrentSide().isLeft() ? myActualContent1 : myActualContent2; + } + @Nullable protected EditorEx getEditor1() { return myEditor1; @@ -359,11 +365,8 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { protected OpenFileDescriptor getOpenFileDescriptor() { EditorEx editor = getCurrentEditor(); - DocumentContent content = getCurrentSide().select(myActualContent1, myActualContent2); - assert content != null; - int offset = editor.getCaretModel().getOffset(); - return content.getOpenFileDescriptor(offset); + return getCurrentContent().getOpenFileDescriptor(offset); } public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) { @@ -443,6 +446,9 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { return getCurrentEditor(); } + else if (DiffDataKeys.CURRENT_CONTENT.is(dataId)) { + return getCurrentContent(); + } return super.getData(dataId); } From 525549b545d44b3bb873f810f3722be66676db35 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 18:04:02 +0300 Subject: [PATCH 04/16] diff: javadoc --- platform/diff-impl/src/com/intellij/diff/DiffContextEx.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/diff-impl/src/com/intellij/diff/DiffContextEx.java b/platform/diff-impl/src/com/intellij/diff/DiffContextEx.java index 026fa3201f0a..2e6550d7b9f0 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffContextEx.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffContextEx.java @@ -16,5 +16,10 @@ package com.intellij.diff; public abstract class DiffContextEx extends DiffContext { + /* + * Reopen current DiffRequest. + * perform the same procedure as on switching between DiffRequests or between DiffViewers. + * this can be used, if some change in request or settings was made, and we need to reopen DiffViewer to apply them. + */ public abstract void reloadDiffRequest(); } From 257755654aafcde6330a0e869abafc4cefcd3b78 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 18:19:23 +0300 Subject: [PATCH 05/16] diff: cleanup - remove code duplication --- .../src/com/intellij/diff/DiffContentFactoryImpl.java | 2 +- platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java index a98a4c8dae75..8acca83b1b90 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffContentFactoryImpl.java @@ -47,7 +47,7 @@ public class DiffContentFactoryImpl extends DiffContentFactory { @NotNull public static DiffContentFactoryImpl getInstanceImpl() { - return (DiffContentFactoryImpl)ServiceManager.getService(DiffContentFactory.class); + return (DiffContentFactoryImpl)DiffContentFactory.getInstance(); } @Override diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index f940fd7ed82d..290d7833903f 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -203,10 +203,7 @@ public class DiffUtil { if (editor == null) return; editor.getCaretModel().removeSecondaryCarets(); editor.getCaretModel().moveToLogicalPosition(position); - ScrollingModel scrollingModel = editor.getScrollingModel(); - scrollingModel.disableAnimation(); - scrollingModel.scrollToCaret(ScrollType.CENTER); - scrollingModel.enableAnimation(); + scrollToCaret(editor); } public static void scrollToLineAnimated(@Nullable final Editor editor, int line) { From 45b76a94ac123f86b280e2ec1f6c5257104d313d Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 18:26:15 +0300 Subject: [PATCH 06/16] diff: cleanup - rename 'highlightFiles' --- .../contents/FileAwareDocumentContent.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java index 463e2d327237..37b7b441c341 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java @@ -21,22 +21,22 @@ import java.nio.charset.Charset; public class FileAwareDocumentContent extends DocumentContentImpl { @Nullable private final Project myProject; - @Nullable private final VirtualFile myLocalFile; + @Nullable private final VirtualFile myHighlightFile; public FileAwareDocumentContent(@Nullable Project project, @NotNull Document document, @Nullable FileType fileType, - @Nullable VirtualFile localFile, + @Nullable VirtualFile highlightFile, @Nullable LineSeparator separator, @Nullable Charset charset) { - super(document, fileType, localFile, separator, charset); + super(document, fileType, highlightFile, separator, charset); myProject = project; - myLocalFile = localFile; + myHighlightFile = highlightFile; } public OpenFileDescriptor getOpenFileDescriptor(int offset) { - if (myProject == null || myLocalFile == null) return null; - return new OpenFileDescriptor(myProject, myLocalFile, offset); + if (myProject == null || myHighlightFile == null) return null; + return new OpenFileDescriptor(myProject, myHighlightFile, offset); } @NotNull @@ -45,8 +45,8 @@ public class FileAwareDocumentContent extends DocumentContentImpl { } @NotNull - public static FileAwareDocumentContent create(@Nullable Project project, @NotNull String content, @NotNull VirtualFile file) { - return new Builder(project).init(file).create(content).build(); + public static FileAwareDocumentContent create(@Nullable Project project, @NotNull String content, @NotNull VirtualFile highlightFile) { + return new Builder(project).init(highlightFile).create(content).build(); } @NotNull @@ -55,8 +55,8 @@ public class FileAwareDocumentContent extends DocumentContentImpl { } @NotNull - public static FileAwareDocumentContent create(@Nullable Project project, @NotNull byte[] content, @NotNull VirtualFile file) { - return new Builder(project).init(file).create(content).build(); + public static FileAwareDocumentContent create(@Nullable Project project, @NotNull byte[] content, @NotNull VirtualFile highlightFile) { + return new Builder(project).init(highlightFile).create(content).build(); } private static class Builder { @@ -84,10 +84,10 @@ public class FileAwareDocumentContent extends DocumentContentImpl { } @NotNull - private Builder init(@NotNull VirtualFile file) { - myLocalFile = file; - myFileType = file.getFileType(); - myCharset = file.getCharset(); + private Builder init(@NotNull VirtualFile highlightFile) { + myLocalFile = highlightFile; + myFileType = highlightFile.getFileType(); + myCharset = highlightFile.getCharset(); return this; } From f68a910fbd8f821a49e931a588abf91c1bf63bba Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 18:28:47 +0300 Subject: [PATCH 07/16] diff: do not check VitrualFile - FilePath will access it itself --- .../intellij/diff/contents/FileAwareDocumentContent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java index 37b7b441c341..95bab6782a4e 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java @@ -77,9 +77,9 @@ public class FileAwareDocumentContent extends DocumentContentImpl { @NotNull private Builder init(@NotNull FilePath path) { - myLocalFile = LocalFileSystem.getInstance().findFileByPath(path.getPath()); - myFileType = myLocalFile != null ? myLocalFile.getFileType() : path.getFileType(); - myCharset = myLocalFile != null ? myLocalFile.getCharset() : path.getCharset(myProject); + path.refresh(); + myFileType = path.getFileType(); + myCharset = path.getCharset(myProject); return this; } From 7673ea89ce854b3f3b90de30c3efc6eb1c2070e8 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 10 Apr 2015 19:17:47 +0300 Subject: [PATCH 08/16] [core] fix action callback not done when no other content available --- .../com/intellij/ui/content/impl/ContentManagerImpl.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java index 2e4e9c85bb39..cf7900e5d167 100644 --- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java @@ -294,10 +294,8 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene } int newSize = myContents.size(); - - ActionCallback result = new ActionCallback(); - if (newSize > 0 && trackSelection) { + ActionCallback result = new ActionCallback(); if (indexToSelect > -1) { final Content toSelect = mySelectionHistory.size() > 0 ? mySelectionHistory.get(0) : myContents.get(indexToSelect); if (!isSelected(toSelect)) { @@ -310,12 +308,12 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene } } } + return result; } else { mySelection.clear(); + return ActionCallback.DONE; } - - return result; } finally { if (ApplicationManager.getApplication().isDispatchThread()) { From 4a4e05dc9d254d93fcd986ff3e0f5512db9956e7 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 10 Apr 2015 19:30:32 +0300 Subject: [PATCH 09/16] diff: fix "Jump To Source" from diff for change from VCS set highlightFile from FilePath --- .../intellij/diff/contents/FileAwareDocumentContent.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java index 95bab6782a4e..2a8b693a9755 100644 --- a/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java +++ b/platform/diff-impl/src/com/intellij/diff/contents/FileAwareDocumentContent.java @@ -11,7 +11,6 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.LineSeparator; import org.jetbrains.annotations.NotNull; @@ -63,7 +62,7 @@ public class FileAwareDocumentContent extends DocumentContentImpl { private final Project myProject; private Document myDocument; private FileType myFileType; - private VirtualFile myLocalFile; + private VirtualFile myHighlightFile; private LineSeparator mySeparator; private Charset myCharset; @@ -78,6 +77,7 @@ public class FileAwareDocumentContent extends DocumentContentImpl { @NotNull private Builder init(@NotNull FilePath path) { path.refresh(); + myHighlightFile = path.getVirtualFile(); myFileType = path.getFileType(); myCharset = path.getCharset(myProject); return this; @@ -85,7 +85,7 @@ public class FileAwareDocumentContent extends DocumentContentImpl { @NotNull private Builder init(@NotNull VirtualFile highlightFile) { - myLocalFile = highlightFile; + myHighlightFile = highlightFile; myFileType = highlightFile.getFileType(); myCharset = highlightFile.getCharset(); return this; @@ -111,7 +111,7 @@ public class FileAwareDocumentContent extends DocumentContentImpl { @NotNull public FileAwareDocumentContent build() { if (FileTypes.UNKNOWN.equals(myFileType)) myFileType = PlainTextFileType.INSTANCE; - return new FileAwareDocumentContent(myProject, myDocument, myFileType, myLocalFile, mySeparator, myCharset); + return new FileAwareDocumentContent(myProject, myDocument, myFileType, myHighlightFile, mySeparator, myCharset); } } } From 34567094caa5f1b81beb0886c683a8a0c26bdfad Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 27 Mar 2015 19:20:52 +0300 Subject: [PATCH 10/16] Added simple way of detecting if line starts with continuation indent: we check whether before current line there was opened and not closed left parenthesis --- .../continuationIndents_DoNotCount.java | 537 ++++++++++++++++++ ...Indents_InMethodParameters_DoNotCount.java | 301 ++++++++++ .../autodetect/JavaAutoDetectIndentTest.java | 9 + .../ContinuationIndentDetector.java | 101 ++++ .../codeStyle/autodetect/LineIndentInfo.java | 4 +- .../autodetect/LineIndentInfoBuilder.java | 9 +- .../ContinuationIndentDetectorTest.java | 138 +++++ 7 files changed, 1096 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/psi/autodetect/continuationIndents_DoNotCount.java create mode 100644 java/java-tests/testData/psi/autodetect/continuationIndents_InMethodParameters_DoNotCount.java create mode 100644 platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java create mode 100644 platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java diff --git a/java/java-tests/testData/psi/autodetect/continuationIndents_DoNotCount.java b/java/java-tests/testData/psi/autodetect/continuationIndents_DoNotCount.java new file mode 100644 index 000000000000..a2714c6652c6 --- /dev/null +++ b/java/java-tests/testData/psi/autodetect/continuationIndents_DoNotCount.java @@ -0,0 +1,537 @@ +/* + * Copyright 2000-2013 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; + +import com.intellij.lang.FileASTNode; +import com.intellij.openapi.application.ex.PathManagerEx; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.source.JavaLightStubBuilder; +import com.intellij.psi.stubs.StubElement; +import com.intellij.testFramework.LightIdeaTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.security.SecureRandom; + +public class Test { + private static final StubBuilder NEW_BUILDER = new JavaLightStubBuilder(); + + @Override + public void setUp() throws Exception { + super.setUp(); + doTest("@interface A { int i() default 42; }\n class C { void m(int p) throws E { } }", null); // warm up + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST); + } + + public void testEmpty() { + doTest("/**/", + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n"); + } + + public void testFileHeader() { + doTest("package p;\n" + + "import a/*comment to skip*/.b;\n" + + "import static c.d.*;\n" + + "import static java.util.Arrays.sort;", + + "PsiJavaFileStub [p]\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " IMPORT_STATEMENT:PsiImportStatementStub[a.b]\n" + + " IMPORT_STATIC_STATEMENT:PsiImportStatementStub[static c.d.*]\n" + + " IMPORT_STATIC_STATEMENT:PsiImportStatementStub[static java.util.Arrays.sort]\n"); + } + + public void testClassDeclaration() { + doTest("package p;" + + "class A implements I, J { }\n" + + "class B extends a/*skip*/.A { class I { } }\n" + + "@java.lang.Deprecated interface I { }\n" + + "/** @deprecated just don't use */ @interface N { }", + + "PsiJavaFileStub [p]\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=A fqn=p.A]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:I, J]\n" + + " CLASS:PsiClassStub[name=B fqn=p.B]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " TYPE_PARAMETER:PsiTypeParameter[K]\n" + + " EXTENDS_BOUND_LIST:PsiRefListStub[EXTENDS_BOUNDS_LIST:]\n" + + " TYPE_PARAMETER:PsiTypeParameter[V]\n" + + " EXTENDS_BOUND_LIST:PsiRefListStub[EXTENDS_BOUNDS_LIST:X]\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:a/*skip*/.A]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " CLASS:PsiClassStub[name=I fqn=p.B.I]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " CLASS:PsiClassStub[interface deprecatedA name=I fqn=p.I]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" + + " ANNOTATION:PsiAnnotationStub[@java.lang.Deprecated]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " CLASS:PsiClassStub[interface annotation deprecated name=N fqn=p.N]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n"); + } + + public void testMethods() { + doTest("public @interface Anno {\n" + + " int i() default 42;\n" + + " public static String s();\n" + + "}\n" + + "private class C {\n" + + " public C() throws Exception { }\n" + + " public abstract void m(final int i, int[] a1, int a2[], int[] a3[]);\n" + + " private static int v2a(int... v) [] { return v; }\n" + + "}\n" + + "interface I {\n" + + " void m1();\n" + + " default void m2() { }\n" + + "}", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[interface annotation name=Anno fqn=Anno]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1025]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " ANNOTATION_METHOD:PsiMethodStub[annotation i:int default=42]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1025]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " ANNOTATION_METHOD:PsiMethodStub[annotation s:String]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1033]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=2]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " METHOD:PsiMethodStub[cons C:null]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:Exception]\n" + + " METHOD:PsiMethodStub[m:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1025]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " PARAMETER:PsiParameterStub[i:int]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4112]\n" + + " PARAMETER:PsiParameterStub[a1:int[]]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " PARAMETER:PsiParameterStub[a2:int[]]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " PARAMETER:PsiParameterStub[a3:int[][]]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " METHOD:PsiMethodStub[varargs v2a:int[]]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=10]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " PARAMETER:PsiParameterStub[v:int...]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " CLASS:PsiClassStub[interface name=I fqn=I]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " METHOD:PsiMethodStub[m1:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1025]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " METHOD:PsiMethodStub[m2:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=513]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n"); + } + + public void testFields() { + doTest("static class C {\n" + + " strictfp float f;\n" + + " int j[] = {0}, k;\n" + + " static String s = \"-\";\n" + + "}\n" + + "public class D {\n" + + " private volatile boolean b;\n" + + " public final double x;\n" + + "}", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4104]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " FIELD:PsiFieldStub[f:float]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=6144]\n" + + " FIELD:PsiFieldStub[j:int[]={0}]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " FIELD:PsiFieldStub[k:int]\n" + + " FIELD:PsiFieldStub[s:String=\"-\"]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4104]\n" + + " CLASS:PsiClassStub[name=D fqn=D]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " FIELD:PsiFieldStub[b:boolean]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=66]\n" + + " FIELD:PsiFieldStub[x:double]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=17]\n"); + } + + public void testAnonymousClasses() { + doTest("class C { {\n" + + " new O.P() { };\n" + + " X.new Y() { };\n" + + " f(p -> new R() { });\n" + + "} }", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " CLASS_INITIALIZER:PsiClassInitializerStub\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=O.P]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Y inqualifnew]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=R]\n"); + } + + public void testEnums() { + doTest("enum E {\n" + + " E1() { };\n" + + " abstract void m();\n" + + "}\n" + + "public enum U { U1, U2 }", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[enum name=E fqn=E]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " ENUM_CONSTANT:PsiFieldStub[enumconst E1:E]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=25]\n" + + " ENUM_CONSTANT_INITIALIZER:PsiClassStub[anonymous enumInit name=null fqn=null baseref=E]\n" + + " METHOD:PsiMethodStub[m:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=5120]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " CLASS:PsiClassStub[enum name=U fqn=U]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=17]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " ENUM_CONSTANT:PsiFieldStub[enumconst U1:U]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=25]\n" + + " ENUM_CONSTANT:PsiFieldStub[enumconst U2:U]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=25]\n"); + } + + public void testLocalVariables() { + doTest("class C {\n" + + " void m() {\n" + + " int local = 0;\n" + + " Object r = new Runnable() {\n" + + " public void run() { }\n" + + " };\n" + + " for (int loop = 0; loop < 10; loop++) ;\n" + + " try (Resource r = new Resource()) { }\n" + + " try (Resource r = new Resource() {\n" + + " @Override public void close() { }\n" + + " }) { }\n" + + " }\n" + + "}", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " METHOD:PsiMethodStub[m:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Runnable]\n" + + " METHOD:PsiMethodStub[run:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Resource]\n" + + " METHOD:PsiMethodStub[close:void]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1]\n" + + " ANNOTATION:PsiAnnotationStub[@Override]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n"); + } + + public void testNonListParameters() { + doTest("class C {\n" + + " {\n" + + " for (int i : arr) ;\n" + + " for (String s : new Iterable() {\n" + + " @Override public Iterator iterator() { return null; }\n" + + " }) ;\n" + + " try { }\n" + + " catch (Throwable t) { }\n" + + " catch (E1|E2 e) { }\n" + + " }\n" + + "}", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " CLASS_INITIALIZER:PsiClassInitializerStub\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANONYMOUS_CLASS:PsiClassStub[anonymous name=null fqn=null baseref=Iterable]\n" + + " METHOD:PsiMethodStub[iterator:Iterator]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=1]\n" + + " ANNOTATION:PsiAnnotationStub[@Override]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n"); + } + + public void testAnnotations() { + doTest("@Deprecated\n" + + "@SuppressWarnings(\"UnusedDeclaration\")\n" + + "class Foo { }", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[deprecatedA name=Foo fqn=Foo]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANNOTATION:PsiAnnotationStub[@Deprecated]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@SuppressWarnings(\"UnusedDeclaration\")]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " NAME_VALUE_PAIR:PsiNameValuePairStubImpl\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n"); + } + + public void testTypeAnnotations() { + doTest("import j.u.@A C;\n" + + "import @A j.u.D;\n" + + "\n" + + "class C<@A T extends @A C> implements @A I<@A T> {\n" + + " @TA T<@A T1, @A ? extends @A T2> f;\n" + + " @TA T m(/*@A C this,*/ @TA int p) throws @A E {\n" + + " o.<@A1 C>m();\n" + + " new @A2 C();\n" + + " C.@A3 B v = (@A4 C)v.new @A5 C();\n" + + " m(@A6 C::m);\n" + + " @A7 T @A8[] @A9[] a = new @A7 T @A8[0] @A9[0];\n" + + " }\n" + + " int @A [] v() @A [] { }\n" + + "}", + + "PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " IMPORT_STATEMENT:PsiImportStatementStub[j.u.C]\n" + + " IMPORT_STATEMENT:PsiImportStatementStub[j.u.D]\n" + + " CLASS:PsiClassStub[name=C fqn=C]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " TYPE_PARAMETER:PsiTypeParameter[T]\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " EXTENDS_BOUND_LIST:PsiRefListStub[EXTENDS_BOUNDS_LIST:@A C]\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:@A I<@A T>]\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " FIELD:PsiFieldStub[f:T<@A T1, @A ? extends @A T2>]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANNOTATION:PsiAnnotationStub[@TA]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " METHOD:PsiMethodStub[m:T]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANNOTATION:PsiAnnotationStub[@TA]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " PARAMETER:PsiParameterStub[p:int]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " ANNOTATION:PsiAnnotationStub[@TA]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:@A E]\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A1]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A2]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A3]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A4]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A5]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A6]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A7]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A8]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A9]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A7]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A8]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " ANNOTATION:PsiAnnotationStub[@A9]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " METHOD:PsiMethodStub[v:int[][]]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " PARAMETER_LIST:PsiParameterListStub\n" + + " ANNOTATION:PsiAnnotationStub[@A]\n" + + " ANNOTATION_PARAMETER_LIST:PsiAnnotationParameterListStubImpl\n" + + " THROWS_LIST:PsiRefListStub[THROWS_LIST:]\n"); + } + + public void testSOEProof() { + final StringBuilder sb = new StringBuilder(); + final SecureRandom random = new SecureRandom(); + sb.append("class SOE_test {\n BigInteger BIG = new BigInteger(\n"); + int i; + for (i = 0; i < 100000; i++) { + sb.append(" \"").append(Math.abs(random.nextInt())).append("\" +\n"); + } + sb.append(" \"\");\n}"); + + final PsiJavaFile file = (PsiJavaFile)createLightFile("SOE_test.java", sb.toString()); + long t = System.currentTimeMillis(); + final StubElement tree = NEW_BUILDER.buildStubTree(file); + t = System.currentTimeMillis() - t; + assertEquals("PsiJavaFileStub []\n" + + " IMPORT_LIST:PsiImportListStub\n" + + " CLASS:PsiClassStub[name=SOE_test fqn=SOE_test]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + + " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + + " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + + " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + + " FIELD:PsiFieldStub[BIG:BigInteger=;INITIALIZER_NOT_STORED;]\n" + + " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n", + DebugUtil.stubTreeToString(tree)); + System.out.println("SOE depth=" + i + ", time=" + t + "ms"); + } + + public void testPerformance() throws Exception { + final String path = PathManagerEx.getTestDataPath() + "/psi/stub/StubPerformanceTest.java"; + String text = FileUtil.loadFile(new File(path)); + final PsiJavaFile file = (PsiJavaFile)createLightFile("test.java", text); + + PlatformTestUtil.startPerformanceTest("Source file size: " + text.length(), 2000, new ThrowableRunnable() { + @Override + public void run() throws Exception { + NEW_BUILDER.buildStubTree(file); + } + }).cpuBound().assertTiming(); + } + + private static void doTest(@NonNls final String source, @NonNls @Nullable final String tree) { + final PsiJavaFile file = (PsiJavaFile)createLightFile("test.java", source); + final FileASTNode fileNode = file.getNode(); + assertNotNull(fileNode); + assertFalse(fileNode.isParsed()); + + long t1 = System.nanoTime(); + final StubElement lighterTree = NEW_BUILDER.buildStubTree(file); + t1 = Math.max((System.nanoTime() - t1)/1000, 1); + assertFalse(fileNode.isParsed()); + + file.getNode().getChildren(null); // force switch to AST + + long t2 = System.nanoTime(); + final StubElement lighterTree2 = NEW_BUILDER.buildStubTree(file); // build over AST + t2 = Math.max((System.nanoTime() - t2)/1000, 1); + + file.accept(new PsiRecursiveElementWalkingVisitor() { + @Override + public void visitElement(PsiElement element) { + assert !(element instanceof PsiErrorElement) : element; + super.visitElement(element); + } + }); + + final String lightStr = DebugUtil.stubTreeToString(lighterTree); + final String lightStr2 = DebugUtil.stubTreeToString(lighterTree2); + if (tree != null) { + System.out.println("light=" + t1 + "mks, heavy=" + t2 + "mks"); + if (!tree.isEmpty()) { + assertEquals("light tree differs", tree, lightStr); + assertEquals("light tree (2nd) differs", tree, lightStr2); + } + } + } +} diff --git a/java/java-tests/testData/psi/autodetect/continuationIndents_InMethodParameters_DoNotCount.java b/java/java-tests/testData/psi/autodetect/continuationIndents_InMethodParameters_DoNotCount.java new file mode 100644 index 000000000000..1a42f6d92b00 --- /dev/null +++ b/java/java-tests/testData/psi/autodetect/continuationIndents_InMethodParameters_DoNotCount.java @@ -0,0 +1,301 @@ +import java.util.Arrays; +import java.util.List; + +public final class TimeContentItemHelper { + + public static List TIME_PERIOD_1_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD1_1, + TimePeriods.TIME_PERIOD1_2, + TimePeriods.TIME_PERIOD1_3, + TimePeriods.TIME_PERIOD1_4, + TimePeriods.TIME_PERIOD1_5, + TimePeriods.TIME_PERIOD1_6 + ); + + public static List TIME_PERIOD_2_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD2_1, + TimePeriods.TIME_PERIOD2_2, + TimePeriods.TIME_PERIOD2_3, + TimePeriods.TIME_PERIOD2_4, + TimePeriods.TIME_PERIOD2_5, + TimePeriods.TIME_PERIOD2_6 + ); + + public static List TIME_PERIOD_3_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD3_1, + TimePeriods.TIME_PERIOD3_2, + TimePeriods.TIME_PERIOD3_3, + TimePeriods.TIME_PERIOD3_4, + TimePeriods.TIME_PERIOD3_5, + TimePeriods.TIME_PERIOD3_6 + ); + + public static List TIME_PERIOD_4_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD4_1, + TimePeriods.TIME_PERIOD4_2, + TimePeriods.TIME_PERIOD4_3, + TimePeriods.TIME_PERIOD4_4, + TimePeriods.TIME_PERIOD4_5, + TimePeriods.TIME_PERIOD4_6 + ); + + public static List TIME_PERIOD_5_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD5_1, + TimePeriods.TIME_PERIOD5_2, + TimePeriods.TIME_PERIOD5_3, + TimePeriods.TIME_PERIOD5_4, + TimePeriods.TIME_PERIOD5_5, + TimePeriods.TIME_PERIOD5_6 + ); + + public static List TIME_PERIOD_6_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_PERIOD6_1, + TimePeriods.TIME_PERIOD6_2, + TimePeriods.TIME_PERIOD6_3, + TimePeriods.TIME_PERIOD6_4, + TimePeriods.TIME_PERIOD6_5, + TimePeriods.TIME_PERIOD6_6 + ); + + public static List> TIME_PERIOD_CONTENT_ITEM_KEY_MATRIX = Arrays.asList( + TIME_PERIOD_1_CONTENT_ITEM_KEYS, + TIME_PERIOD_2_CONTENT_ITEM_KEYS, + TIME_PERIOD_3_CONTENT_ITEM_KEYS, + TIME_PERIOD_4_CONTENT_ITEM_KEYS, + TIME_PERIOD_5_CONTENT_ITEM_KEYS, + TIME_PERIOD_6_CONTENT_ITEM_KEYS + ); + + public static List TIME_AVERAGE_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE1, + TimePeriods.TIME_AVERAGE2, + TimePeriods.TIME_AVERAGE3, + TimePeriods.TIME_AVERAGE4, + TimePeriods.TIME_AVERAGE5, + TimePeriods.TIME_AVERAGE6 + ); + + public static List TIME_ROOM_DESCRIPTION_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_DESCRIPTION1, + TimePeriods.TIME_AVERAGE_DESCRIPTION2, + TimePeriods.TIME_AVERAGE_DESCRIPTION3, + TimePeriods.TIME_AVERAGE_DESCRIPTION4, + TimePeriods.TIME_AVERAGE_DESCRIPTION5, + TimePeriods.TIME_AVERAGE_DESCRIPTION6 + ); + + public static List TIME_1_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE1_1, + TimePeriods.TIME_AVERAGE_PRICE1_2, + TimePeriods.TIME_AVERAGE_PRICE1_3, + TimePeriods.TIME_AVERAGE_PRICE1_4, + TimePeriods.TIME_AVERAGE_PRICE1_5, + TimePeriods.TIME_AVERAGE_PRICE1_6 + ); + + public static List TIME_2_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE2_1, + TimePeriods.TIME_AVERAGE_PRICE2_2, + TimePeriods.TIME_AVERAGE_PRICE2_3, + TimePeriods.TIME_AVERAGE_PRICE2_4, + TimePeriods.TIME_AVERAGE_PRICE2_5, + TimePeriods.TIME_AVERAGE_PRICE2_6 + ); + + public static List TIME_3_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE3_1, + TimePeriods.TIME_AVERAGE_PRICE3_2, + TimePeriods.TIME_AVERAGE_PRICE3_3, + TimePeriods.TIME_AVERAGE_PRICE3_4, + TimePeriods.TIME_AVERAGE_PRICE3_5, + TimePeriods.TIME_AVERAGE_PRICE3_6 + ); + + public static List TIME_4_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE4_1, + TimePeriods.TIME_AVERAGE_PRICE4_2, + TimePeriods.TIME_AVERAGE_PRICE4_3, + TimePeriods.TIME_AVERAGE_PRICE4_4, + TimePeriods.TIME_AVERAGE_PRICE4_5, + TimePeriods.TIME_AVERAGE_PRICE4_6 + ); + + public static List TIME_5_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE5_1, + TimePeriods.TIME_AVERAGE_PRICE5_2, + TimePeriods.TIME_AVERAGE_PRICE5_3, + TimePeriods.TIME_AVERAGE_PRICE5_4, + TimePeriods.TIME_AVERAGE_PRICE5_5, + TimePeriods.TIME_AVERAGE_PRICE5_6 + ); + + public static List TIME_6_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_AVERAGE_PRICE6_1, + TimePeriods.TIME_AVERAGE_PRICE6_2, + TimePeriods.TIME_AVERAGE_PRICE6_3, + TimePeriods.TIME_AVERAGE_PRICE6_4, + TimePeriods.TIME_AVERAGE_PRICE6_5, + TimePeriods.TIME_AVERAGE_PRICE6_6 + ); + + public static List> TIME_CONTENT_ITEM_KEY_MATRIX = Arrays.asList( + TIME_1_CONTENT_ITEM_KEYS, + TIME_2_CONTENT_ITEM_KEYS, + TIME_3_CONTENT_ITEM_KEYS, + TIME_4_CONTENT_ITEM_KEYS, + TIME_5_CONTENT_ITEM_KEYS, + TIME_6_CONTENT_ITEM_KEYS + ); + + public static List TIME_NOTE_LABELS_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_NOTE_LABEL_1, + TimePeriods.TIME_NOTE_LABEL_2, + TimePeriods.TIME_NOTE_LABEL_3, + TimePeriods.TIME_NOTE_LABEL_4, + TimePeriods.TIME_NOTE_LABEL_5, + TimePeriods.TIME_NOTE_LABEL_6, + TimePeriods.TIME_NOTE_LABEL_7, + TimePeriods.TIME_NOTE_LABEL_8, + TimePeriods.TIME_NOTE_LABEL_9, + TimePeriods.TIME_NOTE_LABEL_10 + ); + + public static List TIME_NOTES_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIME_NOTE_1, + TimePeriods.TIME_NOTE_2, + TimePeriods.TIME_NOTE_3, + TimePeriods.TIME_NOTE_4, + TimePeriods.TIME_NOTE_5, + TimePeriods.TIME_NOTE_6, + TimePeriods.TIME_NOTE_7, + TimePeriods.TIME_NOTE_8, + TimePeriods.TIME_NOTE_9, + TimePeriods.TIME_NOTE_10 + ); + + public static List TIME_CONTENT_ITEM_KEYS = Arrays.asList( + TimePeriods.TIMES_ENABLED, + TimePeriods.TIMES_COUNT_OF_TIMES, + TimePeriods.TIMES_COUNT_OF_TIME_PERIODS, + TimePeriods.TIMES_COUNT_OF_AVERAGES, + TimePeriods.TIME_NAME1, + TimePeriods.TIME_NAME2, + TimePeriods.TIME_NAME3, + TimePeriods.TIME_NAME4, + TimePeriods.TIME_NAME5, + TimePeriods.TIME_NAME6, + TimePeriods.TIME_PERIOD1_1, + TimePeriods.TIME_PERIOD1_2, + TimePeriods.TIME_PERIOD1_3, + TimePeriods.TIME_PERIOD1_4, + TimePeriods.TIME_PERIOD1_5, + TimePeriods.TIME_PERIOD1_6, + TimePeriods.TIME_PERIOD2_1, + TimePeriods.TIME_PERIOD2_2, + TimePeriods.TIME_PERIOD2_3, + TimePeriods.TIME_PERIOD2_4, + TimePeriods.TIME_PERIOD2_5, + TimePeriods.TIME_PERIOD2_6, + TimePeriods.TIME_PERIOD3_1, + TimePeriods.TIME_PERIOD3_2, + TimePeriods.TIME_PERIOD3_3, + TimePeriods.TIME_PERIOD3_4, + TimePeriods.TIME_PERIOD3_5, + TimePeriods.TIME_PERIOD3_6, + TimePeriods.TIME_PERIOD4_1, + TimePeriods.TIME_PERIOD4_2, + TimePeriods.TIME_PERIOD4_3, + TimePeriods.TIME_PERIOD4_4, + TimePeriods.TIME_PERIOD4_5, + TimePeriods.TIME_PERIOD4_6, + TimePeriods.TIME_PERIOD5_1, + TimePeriods.TIME_PERIOD5_2, + TimePeriods.TIME_PERIOD5_3, + TimePeriods.TIME_PERIOD5_4, + TimePeriods.TIME_PERIOD5_5, + TimePeriods.TIME_PERIOD5_6, + TimePeriods.TIME_PERIOD6_1, + TimePeriods.TIME_PERIOD6_2, + TimePeriods.TIME_PERIOD6_3, + TimePeriods.TIME_PERIOD6_4, + TimePeriods.TIME_PERIOD6_5, + TimePeriods.TIME_PERIOD6_6, + TimePeriods.TIME_AVERAGE1, + TimePeriods.TIME_AVERAGE2, + TimePeriods.TIME_AVERAGE3, + TimePeriods.TIME_AVERAGE4, + TimePeriods.TIME_AVERAGE5, + TimePeriods.TIME_AVERAGE6, + TimePeriods.TIME_AVERAGE_PRICE1_1, + TimePeriods.TIME_AVERAGE_PRICE1_2, + TimePeriods.TIME_AVERAGE_PRICE1_3, + TimePeriods.TIME_AVERAGE_PRICE1_4, + TimePeriods.TIME_AVERAGE_PRICE1_5, + TimePeriods.TIME_AVERAGE_PRICE1_6, + TimePeriods.TIME_AVERAGE_PRICE2_1, + TimePeriods.TIME_AVERAGE_PRICE2_2, + TimePeriods.TIME_AVERAGE_PRICE2_3, + TimePeriods.TIME_AVERAGE_PRICE2_4, + TimePeriods.TIME_AVERAGE_PRICE2_5, + TimePeriods.TIME_AVERAGE_PRICE2_6, + TimePeriods.TIME_AVERAGE_PRICE3_1, + TimePeriods.TIME_AVERAGE_PRICE3_2, + TimePeriods.TIME_AVERAGE_PRICE3_3, + TimePeriods.TIME_AVERAGE_PRICE3_4, + TimePeriods.TIME_AVERAGE_PRICE3_5, + TimePeriods.TIME_AVERAGE_PRICE3_6, + TimePeriods.TIME_AVERAGE_PRICE4_1, + TimePeriods.TIME_AVERAGE_PRICE4_2, + TimePeriods.TIME_AVERAGE_PRICE4_3, + TimePeriods.TIME_AVERAGE_PRICE4_4, + TimePeriods.TIME_AVERAGE_PRICE4_5, + TimePeriods.TIME_AVERAGE_PRICE4_6, + TimePeriods.TIME_AVERAGE_PRICE5_1, + TimePeriods.TIME_AVERAGE_PRICE5_2, + TimePeriods.TIME_AVERAGE_PRICE5_3, + TimePeriods.TIME_AVERAGE_PRICE5_4, + TimePeriods.TIME_AVERAGE_PRICE5_5, + TimePeriods.TIME_AVERAGE_PRICE5_6, + TimePeriods.TIME_AVERAGE_PRICE6_1, + TimePeriods.TIME_AVERAGE_PRICE6_2, + TimePeriods.TIME_AVERAGE_PRICE6_3, + TimePeriods.TIME_AVERAGE_PRICE6_4, + TimePeriods.TIME_AVERAGE_PRICE6_5, + TimePeriods.TIME_AVERAGE_PRICE6_6, + TimePeriods.TIME_AVERAGE_DESCRIPTION1, + TimePeriods.TIME_AVERAGE_DESCRIPTION2, + TimePeriods.TIME_AVERAGE_DESCRIPTION3, + TimePeriods.TIME_AVERAGE_DESCRIPTION4, + TimePeriods.TIME_AVERAGE_DESCRIPTION5, + TimePeriods.TIME_AVERAGE_DESCRIPTION6, + TimePeriods.TIME_NOTE_LABEL_1, + TimePeriods.TIME_NOTE_LABEL_2, + TimePeriods.TIME_NOTE_LABEL_3, + TimePeriods.TIME_NOTE_LABEL_4, + TimePeriods.TIME_NOTE_LABEL_5, + TimePeriods.TIME_NOTE_LABEL_6, + TimePeriods.TIME_NOTE_LABEL_7, + TimePeriods.TIME_NOTE_LABEL_8, + TimePeriods.TIME_NOTE_LABEL_9, + TimePeriods.TIME_NOTE_LABEL_10, + TimePeriods.TIME_NOTE_1, + TimePeriods.TIME_NOTE_2, + TimePeriods.TIME_NOTE_3, + TimePeriods.TIME_NOTE_4, + TimePeriods.TIME_NOTE_5, + TimePeriods.TIME_NOTE_6, + TimePeriods.TIME_NOTE_7, + TimePeriods.TIME_NOTE_8, + TimePeriods.TIME_NOTE_9, + TimePeriods.TIME_NOTE_10 + ); + + public static boolean check(TimePeriods key) { + int keyI = key.getIntValue(); + if (keyI < 0) { + return false; + } else { + return true; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java b/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java index e3600a290bea..5f75745352e5 100644 --- a/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java @@ -36,4 +36,13 @@ public class JavaAutoDetectIndentTest extends AbstractIndentAutoDetectionTest { public void testNotIndentedComment() { doTestIndentSize(3); } + + public void testContinuationIndents_DoNotCount() { + doTestIndentSize(2); + } + + public void testContinuationIndents_InMethodParameters_DoNotCount() { + doTestIndentSize(4); + } + } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java new file mode 100644 index 000000000000..efc82583cb42 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +class ContinuationIndentDetector { + private List myBrackets = ContainerUtil.newArrayList(); + + private final CharSequence myText; + private final int myLength; + private boolean myStackCorrupted = false; + + public ContinuationIndentDetector(@NotNull CharSequence text) { + myText = text; + myLength = text.length(); + } + + public void feedLineStartingAt(int startOffset) { + if (myStackCorrupted) return; + + int lineEndOffset = getLineEndOffset(startOffset); + + for (int i = startOffset; i < lineEndOffset; i++) { + char c = myText.charAt(i); + Bracket bracket = Bracket.forChar(c); + if (bracket == null) continue; + + if (bracket.isOpening()) { + myBrackets.add(bracket); + } + else { + if (myBrackets.isEmpty()) { + myStackCorrupted = true; + } + myBrackets.remove(myBrackets.size() - 1); + } + } + } + + public boolean isContinuationIndent(int lineStartOffset) { + if (myStackCorrupted || myBrackets.isEmpty()) { + return false; + } + int textStartOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, " \t"); + + for (int i = myBrackets.size() - 1; i >= 0; i--) { + if (myBrackets.get(i) == Bracket.LPARENTH && myText.charAt(textStartOffset) != ')') return true; + } + + return false; + } + + private int getLineEndOffset(int lineStartOffset) { + int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength); + return lineEndOffset < 0 ? myLength : lineEndOffset; + } + + private enum Bracket { + LBRACE('{', true), + LPARENTH('(', true), + RBRACE('}', false), + RPARENTH(')', false); + + private final char myChar; + private boolean myIsOpeningBracket; + + Bracket(char c, boolean isOpeningBracket) { + myIsOpeningBracket = isOpeningBracket; + myChar = c; + } + + boolean isOpening() { + return myIsOpeningBracket; + } + + static Bracket forChar(char c) { + for (Bracket bracket : Bracket.values()) { + if (bracket.myChar == c) return bracket; + } + return null; + } + } +} diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java index d85a4cbcaa0e..2532a6df3629 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfo.java @@ -21,6 +21,7 @@ public class LineIndentInfo { public static final LineIndentInfo EMPTY_LINE = new LineIndentInfo(LineType.EMPTY_LINE, -1); public static final LineIndentInfo LINE_WITH_COMMENT = new LineIndentInfo(LineType.LINE_WITH_COMMENT, -1); public static final LineIndentInfo LINE_WITH_TABS = new LineIndentInfo(LineType.LINE_WITH_TABS, -1); + public static final LineIndentInfo LINE_WITH_CONTINUATION_INDENT = new LineIndentInfo(LineType.LINE_WITH_CONTINUATION_INDENT, -1); private final int myIndentSize; private final LineType myType; @@ -51,6 +52,7 @@ public class LineIndentInfo { EMPTY_LINE, LINE_WITH_COMMENT, LINE_WITH_TABS, - LINE_WITH_WHITESPACE_INDENT + LINE_WITH_WHITESPACE_INDENT, + LINE_WITH_CONTINUATION_INDENT } } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java index 6df9580e9e88..5532f64f9f20 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java @@ -31,10 +31,12 @@ public class LineIndentInfoBuilder { private final CharSequence myText; private final int myLength; private final Commenter myCommenter; + private ContinuationIndentDetector myContinuationIndentDetector; public LineIndentInfoBuilder(@NotNull CharSequence text, @Nullable Language language) { myText = text; myLength = text.length(); + myContinuationIndentDetector = new ContinuationIndentDetector(text); myCommenter = language != null ? LanguageCommenters.INSTANCE.forLanguage(language) : null; } @@ -68,11 +70,14 @@ public class LineIndentInfoBuilder { return LineIndentInfo.LINE_WITH_COMMENT; } else if (CharArrayUtil.indexOf(myText, "\t", lineStartOffset, textStartOffset) > 0) { + myContinuationIndentDetector.feedLineStartingAt(lineStartOffset); return LineIndentInfo.LINE_WITH_TABS; } else { - int indentSize = textStartOffset - lineStartOffset; - return LineIndentInfo.newWhiteSpaceIndent(indentSize); + boolean isContinuationIndent = myContinuationIndentDetector.isContinuationIndent(lineStartOffset); + myContinuationIndentDetector.feedLineStartingAt(lineStartOffset); + return isContinuationIndent ? LineIndentInfo.LINE_WITH_CONTINUATION_INDENT + : LineIndentInfo.newWhiteSpaceIndent(textStartOffset - lineStartOffset); } } diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java new file mode 100644 index 000000000000..6e18c400ccf2 --- /dev/null +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.codeStyle.autodetect; + +import com.intellij.util.containers.ContainerUtil; +import junit.framework.TestCase; + +import java.util.List; +import java.util.Set; + + +public class ContinuationIndentDetectorTest extends TestCase { + private ContinuationIndentDetector myContinuationIndentDetector; + private List myLineStartOffsets; + + public void configure(String text) { + myContinuationIndentDetector = new ContinuationIndentDetector(text); + myLineStartOffsets = calculateLineStartOffsets(text); + } + + public void testContinuationIndentInsideParenth() { + configure( + "test(\n" + + " \"aaaaa\" + \n" + + " \"bbbbb\");\n" + + "int a = 2;" + ); + + doTest(1, 2); + } + + public void testNoContinuationIndent_OnLineStartingWithRightParenth() { + configure( + "test(\n" + + " \"aaaaa\" + \n" + + " \"bbbbb\"\n" + + ");" + ); + + doTest(1, 2); + } + + public void testNoContinuationIndents_BetweenBraces() { + configure( + "import java.lang.Override;\n" + + "import java.lang.Runnable;\n" + + "\n" + + "class T {\n" + + " \n" + + " void test() {\n" + + " int a;\n" + + " int b;\n" + + " Runnable runnable = new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " System.out.println(\"AAA!\");\n" + + " }\n" + + " }\n" + + " }\n" + + " \n" + + "}" + ); + doTest(); + } + + public void testMixedBraces() { + configure( + "import java.lang.Runnable;\n" + + "\n" + + "class R {\n" + + "\n" + + "\n" + + " void test() {\n" + + " kuu(new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + " },\n" + + " new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + " }\n" + + " );\n" + + " }\n" + + "\n" + + " void kuu(Runnable a, Runnable b) {\n" + + " }\n" + + "}" + ); + doTest(7, 8, 9, 10, 11, 12, 13, 14, 15); + } + + + private void doTest(Integer ...linesWithContinuationIndents) { + Set continuationLines = ContainerUtil.newHashSet(linesWithContinuationIndents); + + for (int currentLine = 0; currentLine < myLineStartOffsets.size(); currentLine++) { + Integer lineStartOffset = myLineStartOffsets.get(currentLine); + boolean isContinuation = myContinuationIndentDetector.isContinuationIndent(lineStartOffset); + if (continuationLines.contains(currentLine)) { + assertTrue("Line " + currentLine + " should start with continuation indent", isContinuation); + } + else { + assertTrue("Line " + currentLine + " should not start with continuation indent" ,!isContinuation); + } + myContinuationIndentDetector.feedLineStartingAt(lineStartOffset); + } + } + + + private List calculateLineStartOffsets(String text) { + List lineStartOffsets = ContainerUtil.newArrayList(); + lineStartOffsets.add(0); + + int lineStart = 0; + int lineFeed; + while ((lineFeed = text.indexOf('\n', lineStart)) > 0) { + lineStart = lineFeed + 1; + lineStartOffsets.add(lineStart); + } + + return lineStartOffsets; + } +} From 189fa2c501992f39feda9649647d346d54f34a8e Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 30 Mar 2015 17:01:09 +0300 Subject: [PATCH 11/16] refactoring, added tests, on line starting with closing parenthesis. Excluding braces, closed at line start from opened braces, when checking if line starts with continuation indent. Line starts with continuation indent if there is at least one opened parenthesis in the stack of opened ones. --- .../ContinuationIndentDetector.java | 95 +++++++++++++------ .../ContinuationIndentDetectorTest.java | 38 ++++++-- 2 files changed, 97 insertions(+), 36 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java index efc82583cb42..8bb92ec7b105 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -16,17 +16,18 @@ package com.intellij.psi.codeStyle.autodetect; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Stack; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import java.util.List; class ContinuationIndentDetector { - private List myBrackets = ContainerUtil.newArrayList(); + private Stack myOpenedBrackets = ContainerUtil.newStack(); private final CharSequence myText; private final int myLength; - private boolean myStackCorrupted = false; + private boolean myIncorrectBracketsOrder = false; public ContinuationIndentDetector(@NotNull CharSequence text) { myText = text; @@ -34,38 +35,52 @@ class ContinuationIndentDetector { } public void feedLineStartingAt(int startOffset) { - if (myStackCorrupted) return; + if (myIncorrectBracketsOrder) return; - int lineEndOffset = getLineEndOffset(startOffset); - - for (int i = startOffset; i < lineEndOffset; i++) { - char c = myText.charAt(i); - Bracket bracket = Bracket.forChar(c); + for (int i = startOffset; i < getLineEndOffset(startOffset); i++) { + Bracket bracket = Bracket.forChar(myText.charAt(i)); if (bracket == null) continue; + processBracket(bracket); + } + } - if (bracket.isOpening()) { - myBrackets.add(bracket); + private void processBracket(@NotNull Bracket bracket) { + if (bracket.isOpening()) { + myOpenedBrackets.add(bracket); + } + else { + if (!myOpenedBrackets.isEmpty() && bracket.isClosing(myOpenedBrackets.peek())) { + myOpenedBrackets.pop(); } else { - if (myBrackets.isEmpty()) { - myStackCorrupted = true; - } - myBrackets.remove(myBrackets.size() - 1); + myIncorrectBracketsOrder = true; } } } public boolean isContinuationIndent(int lineStartOffset) { - if (myStackCorrupted || myBrackets.isEmpty()) { - return false; - } - int textStartOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, " \t"); + if (myIncorrectBracketsOrder) return false; + List openedBrackets = excludeBracketsClosedAtLineStart(lineStartOffset); + return openedBrackets.contains(Bracket.LPARENTH); + } - for (int i = myBrackets.size() - 1; i >= 0; i--) { - if (myBrackets.get(i) == Bracket.LPARENTH && myText.charAt(textStartOffset) != ')') return true; + @NotNull + private List excludeBracketsClosedAtLineStart(int lineStartOffset) { + int nonWhiteSpaceCharOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, " \t"); + + for (int i = myOpenedBrackets.size() - 1; i >= 0 && nonWhiteSpaceCharOffset < myText.length(); i--) { + Bracket lastOpenedBracket = myOpenedBrackets.get(i); + char nonWhiteSpaceChar = myText.charAt(nonWhiteSpaceCharOffset); + + Bracket bracket = Bracket.forChar(nonWhiteSpaceChar); + if (bracket == null || !bracket.isClosing(lastOpenedBracket)) { + return myOpenedBrackets.subList(0, i + 1); + } + + nonWhiteSpaceCharOffset = CharArrayUtil.shiftForward(myText, nonWhiteSpaceCharOffset, " \t"); } - return false; + return ContainerUtil.emptyList(); } private int getLineEndOffset(int lineStartOffset) { @@ -74,21 +89,43 @@ class ContinuationIndentDetector { } private enum Bracket { - LBRACE('{', true), - LPARENTH('(', true), - RBRACE('}', false), - RPARENTH(')', false); + LBRACE('{') { + @Override + boolean isOpening() { + return true; + } + }, + LPARENTH('(') { + @Override + boolean isOpening() { + return true; + } + }, + RBRACE('}') { + @Override + public boolean isClosing(Bracket bracket) { + return bracket == LBRACE; + } + }, + RPARENTH(')') { + @Override + public boolean isClosing(Bracket bracket) { + return bracket == LPARENTH; + } + }; private final char myChar; - private boolean myIsOpeningBracket; - Bracket(char c, boolean isOpeningBracket) { - myIsOpeningBracket = isOpeningBracket; + Bracket(char c) { myChar = c; } + public boolean isClosing(Bracket bracket) { + return false; + } + boolean isOpening() { - return myIsOpeningBracket; + return false; } static Bracket forChar(char c) { diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java index 6e18c400ccf2..4567dbddb828 100644 --- a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java @@ -39,7 +39,7 @@ public class ContinuationIndentDetectorTest extends TestCase { "int a = 2;" ); - doTest(1, 2); + doCheckLinesWithContinuationIndents(1, 2); } public void testNoContinuationIndent_OnLineStartingWithRightParenth() { @@ -50,7 +50,7 @@ public class ContinuationIndentDetectorTest extends TestCase { ");" ); - doTest(1, 2); + doCheckLinesWithContinuationIndents(1, 2); } public void testNoContinuationIndents_BetweenBraces() { @@ -73,7 +73,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " \n" + "}" ); - doTest(); + doCheckLinesWithContinuationIndents(); } public void testMixedBraces() { @@ -101,11 +101,36 @@ public class ContinuationIndentDetectorTest extends TestCase { " }\n" + "}" ); - doTest(7, 8, 9, 10, 11, 12, 13, 14, 15); + doCheckLinesWithContinuationIndents(7, 8, 9, 10, 11, 12, 13, 14, 15); } + public void testClosingBracesAtLineStart() { + configure("class Test {\n" + + " public static void main(String[] args) {\n" + + " tree.put(\"Web Development\", Pair.create(PlatformImplIcons.WebDevelopment, Arrays.asList(\n" + + " \"HTML:HtmlTools\",\n" + + " \"com.intellij.css\",\n" + + " \"JavaScript:JavaScript,JSIntentionPowerPack\",\n" + + " \"com.jetbrains.restClient\"\n" + + " )));\n" + + " }\n" + + "}"); + doCheckLinesWithContinuationIndents(3, 4, 5, 6); + } - private void doTest(Integer ...linesWithContinuationIndents) { + public void testInsideParenth() { + configure("@State(\n" + + " name = \"AndroidRemoteDataBaseManager\",\n" + + " storages = {\n" + + " @Storage(\n" + + " file = StoragePathMacros.APP_CONFIG + \"/androidRemoteDatabases.xml\"\n" + + " )}\n" + + ")\n" + + "class T {}"); + doCheckLinesWithContinuationIndents(1, 2, 3, 4, 5); + } + + private void doCheckLinesWithContinuationIndents(Integer... linesWithContinuationIndents) { Set continuationLines = ContainerUtil.newHashSet(linesWithContinuationIndents); for (int currentLine = 0; currentLine < myLineStartOffsets.size(); currentLine++) { @@ -121,7 +146,6 @@ public class ContinuationIndentDetectorTest extends TestCase { } } - private List calculateLineStartOffsets(String text) { List lineStartOffsets = ContainerUtil.newArrayList(); lineStartOffsets.add(0); @@ -135,4 +159,4 @@ public class ContinuationIndentDetectorTest extends TestCase { return lineStartOffsets; } -} +} \ No newline at end of file From f4e5a917283fc1c381475616e670e94d3d39421c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 30 Mar 2015 17:05:04 +0300 Subject: [PATCH 12/16] Continuation indent detector simplified, don't check if some symbols on line start are closing opened braces. --- .../ContinuationIndentDetector.java | 28 +++---------------- .../autodetect/LineIndentInfoBuilder.java | 2 +- .../ContinuationIndentDetectorTest.java | 10 +++---- 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java index 8bb92ec7b105..3638a8c0a237 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -20,8 +20,6 @@ import com.intellij.util.containers.Stack; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; -import java.util.List; - class ContinuationIndentDetector { private Stack myOpenedBrackets = ContainerUtil.newStack(); @@ -58,29 +56,11 @@ class ContinuationIndentDetector { } } - public boolean isContinuationIndent(int lineStartOffset) { - if (myIncorrectBracketsOrder) return false; - List openedBrackets = excludeBracketsClosedAtLineStart(lineStartOffset); - return openedBrackets.contains(Bracket.LPARENTH); - } - - @NotNull - private List excludeBracketsClosedAtLineStart(int lineStartOffset) { - int nonWhiteSpaceCharOffset = CharArrayUtil.shiftForward(myText, lineStartOffset, " \t"); - - for (int i = myOpenedBrackets.size() - 1; i >= 0 && nonWhiteSpaceCharOffset < myText.length(); i--) { - Bracket lastOpenedBracket = myOpenedBrackets.get(i); - char nonWhiteSpaceChar = myText.charAt(nonWhiteSpaceCharOffset); - - Bracket bracket = Bracket.forChar(nonWhiteSpaceChar); - if (bracket == null || !bracket.isClosing(lastOpenedBracket)) { - return myOpenedBrackets.subList(0, i + 1); - } - - nonWhiteSpaceCharOffset = CharArrayUtil.shiftForward(myText, nonWhiteSpaceCharOffset, " \t"); + public boolean isContinuationIndent() { + if (myIncorrectBracketsOrder) { + return false; } - - return ContainerUtil.emptyList(); + return myOpenedBrackets.contains(Bracket.LPARENTH); } private int getLineEndOffset(int lineStartOffset) { diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java index 5532f64f9f20..89fe8fa542c1 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/LineIndentInfoBuilder.java @@ -74,7 +74,7 @@ public class LineIndentInfoBuilder { return LineIndentInfo.LINE_WITH_TABS; } else { - boolean isContinuationIndent = myContinuationIndentDetector.isContinuationIndent(lineStartOffset); + boolean isContinuationIndent = myContinuationIndentDetector.isContinuationIndent(); myContinuationIndentDetector.feedLineStartingAt(lineStartOffset); return isContinuationIndent ? LineIndentInfo.LINE_WITH_CONTINUATION_INDENT : LineIndentInfo.newWhiteSpaceIndent(textStartOffset - lineStartOffset); diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java index 4567dbddb828..617a54b3c102 100644 --- a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java @@ -50,7 +50,7 @@ public class ContinuationIndentDetectorTest extends TestCase { ");" ); - doCheckLinesWithContinuationIndents(1, 2); + doCheckLinesWithContinuationIndents(1, 2, 3); } public void testNoContinuationIndents_BetweenBraces() { @@ -101,7 +101,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " }\n" + "}" ); - doCheckLinesWithContinuationIndents(7, 8, 9, 10, 11, 12, 13, 14, 15); + doCheckLinesWithContinuationIndents(7, 8, 9, 10, 11, 12, 13, 14, 15, 16); } public void testClosingBracesAtLineStart() { @@ -115,7 +115,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " )));\n" + " }\n" + "}"); - doCheckLinesWithContinuationIndents(3, 4, 5, 6); + doCheckLinesWithContinuationIndents(3, 4, 5, 6, 7); } public void testInsideParenth() { @@ -127,7 +127,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " )}\n" + ")\n" + "class T {}"); - doCheckLinesWithContinuationIndents(1, 2, 3, 4, 5); + doCheckLinesWithContinuationIndents(1, 2, 3, 4, 5, 6); } private void doCheckLinesWithContinuationIndents(Integer... linesWithContinuationIndents) { @@ -135,7 +135,7 @@ public class ContinuationIndentDetectorTest extends TestCase { for (int currentLine = 0; currentLine < myLineStartOffsets.size(); currentLine++) { Integer lineStartOffset = myLineStartOffsets.get(currentLine); - boolean isContinuation = myContinuationIndentDetector.isContinuationIndent(lineStartOffset); + boolean isContinuation = myContinuationIndentDetector.isContinuationIndent(); if (continuationLines.contains(currentLine)) { assertTrue("Line " + currentLine + " should start with continuation indent", isContinuation); } From 2af58291653bdc5770c5bd63d74577f719eabd2b Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 30 Mar 2015 17:30:04 +0300 Subject: [PATCH 13/16] Added registry flag for continuation indent detector --- .../codeStyle/autodetect/ContinuationIndentDetector.java | 7 ++++++- platform/util/resources/misc/registry.properties | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java index 3638a8c0a237..5d8f517dc979 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.codeStyle.autodetect; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import com.intellij.util.text.CharArrayUtil; @@ -57,12 +58,16 @@ class ContinuationIndentDetector { } public boolean isContinuationIndent() { - if (myIncorrectBracketsOrder) { + if (!shouldDetect() || myIncorrectBracketsOrder) { return false; } return myOpenedBrackets.contains(Bracket.LPARENTH); } + private boolean shouldDetect() { + return Registry.is("detect.indent.ignore.continuation.indented.lines"); + } + private int getLineEndOffset(int lineStartOffset) { int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength); return lineEndOffset < 0 ? myLength : lineEndOffset; diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c2dd64c84412..9a07909abaa1 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -535,6 +535,9 @@ editor.xcode.like.scrollbar.description=Enables auto-hideable Xcode-like editor editor.config.stop.at.project.root=true editor.config.stop.at.project.root.description=Stops searching for .editorconfig at project root (requires project reopening) +detect.indent.ignore.continuation.indented.lines=false +detect.indent.ignore.continuation.indented.lines.description=When detecting file indent, ignore continuation indented lines + JDK8042508.bug.fixed=false JDK8042508.bug.fixed.description=Disable check for type variable until javac bug is fixed From 315c2f82285fda82bde2aef0d9cb37633dd92a86 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 30 Mar 2015 17:53:00 +0300 Subject: [PATCH 14/16] Deleted registry keys, minor refactoring --- .../autodetect/ContinuationIndentDetector.java | 16 +++++----------- platform/util/resources/misc/registry.properties | 3 --- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java index 5d8f517dc979..74cb08bc3a23 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.codeStyle.autodetect; -import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import com.intellij.util.text.CharArrayUtil; @@ -36,7 +35,10 @@ class ContinuationIndentDetector { public void feedLineStartingAt(int startOffset) { if (myIncorrectBracketsOrder) return; - for (int i = startOffset; i < getLineEndOffset(startOffset); i++) { + int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", startOffset, myLength); + if (lineEndOffset < 0) lineEndOffset = myLength; + + for (int i = startOffset; i < lineEndOffset; i++) { Bracket bracket = Bracket.forChar(myText.charAt(i)); if (bracket == null) continue; processBracket(bracket); @@ -58,20 +60,12 @@ class ContinuationIndentDetector { } public boolean isContinuationIndent() { - if (!shouldDetect() || myIncorrectBracketsOrder) { + if (myIncorrectBracketsOrder) { return false; } return myOpenedBrackets.contains(Bracket.LPARENTH); } - private boolean shouldDetect() { - return Registry.is("detect.indent.ignore.continuation.indented.lines"); - } - - private int getLineEndOffset(int lineStartOffset) { - int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength); - return lineEndOffset < 0 ? myLength : lineEndOffset; - } private enum Bracket { LBRACE('{') { diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 9a07909abaa1..c2dd64c84412 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -535,9 +535,6 @@ editor.xcode.like.scrollbar.description=Enables auto-hideable Xcode-like editor editor.config.stop.at.project.root=true editor.config.stop.at.project.root.description=Stops searching for .editorconfig at project root (requires project reopening) -detect.indent.ignore.continuation.indented.lines=false -detect.indent.ignore.continuation.indented.lines.description=When detecting file indent, ignore continuation indented lines - JDK8042508.bug.fixed=false JDK8042508.bug.fixed.description=Disable check for type variable until javac bug is fixed From 0011519715d4842db304d4c8d02bc0d305031574 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 8 Apr 2015 14:50:34 +0300 Subject: [PATCH 15/16] Detect continuation indent only if last opened brace is "(" --- .../psi/codeStyle/autodetect/ContinuationIndentDetector.java | 4 ++-- .../codeStyle/autodetect/ContinuationIndentDetectorTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java index 74cb08bc3a23..6b27f04341e2 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetector.java @@ -60,10 +60,10 @@ class ContinuationIndentDetector { } public boolean isContinuationIndent() { - if (myIncorrectBracketsOrder) { + if (myIncorrectBracketsOrder || myOpenedBrackets.isEmpty()) { return false; } - return myOpenedBrackets.contains(Bracket.LPARENTH); + return myOpenedBrackets.peek() == Bracket.LPARENTH; } diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java index 617a54b3c102..4a7475a49f62 100644 --- a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/ContinuationIndentDetectorTest.java @@ -101,7 +101,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " }\n" + "}" ); - doCheckLinesWithContinuationIndents(7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + doCheckLinesWithContinuationIndents(11, 16); } public void testClosingBracesAtLineStart() { @@ -127,7 +127,7 @@ public class ContinuationIndentDetectorTest extends TestCase { " )}\n" + ")\n" + "class T {}"); - doCheckLinesWithContinuationIndents(1, 2, 3, 4, 5, 6); + doCheckLinesWithContinuationIndents(1, 2, 4, 5, 6); } private void doCheckLinesWithContinuationIndents(Integer... linesWithContinuationIndents) { From 53e202091fc9e6a721bfe0e59459446f9b9b178c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 10 Apr 2015 19:42:13 +0300 Subject: [PATCH 16/16] Made failing test passing. Changed detected indent size to 4, which is default (It means we detected nothing, which is not bad) Correct indent (2) is not detected because we determine continuation indent by last bracket in text, and this bracket could also be inside string literal, which is the case here. --- .../com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java b/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java index 5f75745352e5..4a8214e2c5cc 100644 --- a/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/autodetect/JavaAutoDetectIndentTest.java @@ -38,7 +38,9 @@ public class JavaAutoDetectIndentTest extends AbstractIndentAutoDetectionTest { } public void testContinuationIndents_DoNotCount() { - doTestIndentSize(2); + doTestIndentSize(4); + //actual indent is 2, and 4 is the default value + //todo: do not count brackets in string literals } public void testContinuationIndents_InMethodParameters_DoNotCount() {