From 9bcf11ec95fa5fdc32bed03430e03351927cb345 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Thu, 5 May 2016 14:29:13 +0300 Subject: [PATCH] EnterInLineCommentHandler refactoring --- .../editorActions/EnterHandler.java | 36 +++++++++++++---- .../enter/EnterInLineCommentHandler.java | 39 +++++++++++++------ .../source/codeStyle/CodeFormatterFacade.java | 2 +- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java index 7f45571c9591..bc0575ab358e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java @@ -28,6 +28,7 @@ import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lexer.Lexer; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DataContextWrapper; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; @@ -35,8 +36,10 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; @@ -48,7 +51,6 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; -import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IncorrectOperationException; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; @@ -58,6 +60,7 @@ public class EnterHandler extends BaseEnterHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.EnterHandler"); private final EditorActionHandler myOriginalHandler; + private final static Key CONTEXT_LANGUAGE = Key.create("EnterHandler.Language"); public EnterHandler(EditorActionHandler originalHandler) { super(true); @@ -76,7 +79,7 @@ public class EnterHandler extends BaseEnterHandler { PostprocessReformattingAspect.getInstance(project).disablePostprocessFormattingInside(new Runnable() { @Override public void run() { - executeWriteActionInner(editor, caret, dataContext, project); + executeWriteActionInner(editor, caret, getExtendedContext(dataContext, project, caret), project); } }); } @@ -120,7 +123,6 @@ public class EnterHandler extends BaseEnterHandler { final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); documentManager.commitDocument(document); - Commenter langCommenter = LanguageCommenters.INSTANCE.forLanguage(PsiUtilCore.getLanguageAtOffset(file, caretOffset)); boolean forceIndent = false; boolean forceSkipIndent = false; @@ -168,7 +170,7 @@ public class EnterHandler extends BaseEnterHandler { } final DoEnterAction action = new DoEnterAction( - file, editor, document, dataContext, caretOffset, !insertSpace, caretAdvanceRef.get(), project, langCommenter + file, editor, document, dataContext, caretOffset, !insertSpace, caretAdvanceRef.get(), project ); action.setForceIndent(forceIndent); action.run(); @@ -178,6 +180,15 @@ public class EnterHandler extends BaseEnterHandler { } } } + + @NotNull + private static DataContext getExtendedContext(@NotNull DataContext originalContext, + @NotNull Project project, + @NotNull Caret caret) { + DataContext context = originalContext instanceof UserDataHolder ? originalContext : new DataContextWrapper(originalContext); + ((UserDataHolder)context).putUserData(CONTEXT_LANGUAGE, PsiUtilBase.getLanguageInEditor(caret, project)); + return context; + } public static boolean isCommentComplete(PsiComment comment, CodeDocumentationAwareCommenter commenter, Editor editor) { for (CommentCompleteHandler handler : Extensions.getExtensions(CommentCompleteHandler.EP_NAME)) { @@ -301,14 +312,13 @@ public class EnterHandler extends BaseEnterHandler { private final boolean myInsertSpace; private final Editor myEditor; private final Project myProject; - private Commenter myCommenter; private int myCaretAdvance; private boolean myForceIndent = false; private static final String LINE_SEPARATOR = "\n"; public DoEnterAction(PsiFile file, Editor view, Document document, DataContext dataContext, int offset, boolean insertSpace, - int caretAdvance, Project project, Commenter commenter) + int caretAdvance, Project project) { myEditor = view; myFile = file; @@ -318,7 +328,6 @@ public class EnterHandler extends BaseEnterHandler { myInsertSpace = insertSpace; myCaretAdvance = caretAdvance; myProject = project; - myCommenter = commenter; } public void setForceIndent(boolean forceIndent) { @@ -334,8 +343,10 @@ public class EnterHandler extends BaseEnterHandler { i = CharArrayUtil.shiftBackwardUntil(chars, i, LINE_SEPARATOR) + 1; if (i < 0) i = 0; int lineStart = CharArrayUtil.shiftForward(chars, i, " \t"); + Language language = myDataContext instanceof UserDataHolder ? CONTEXT_LANGUAGE.get((UserDataHolder)myDataContext):null; + Commenter langCommenter = language != null ? LanguageCommenters.INSTANCE.forLanguage(language) : null; CodeDocumentationUtil.CommentContext commentContext - = CodeDocumentationUtil.tryParseCommentContext(myCommenter, chars, myOffset, lineStart); + = CodeDocumentationUtil.tryParseCommentContext(langCommenter, chars, myOffset, lineStart); PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(getProject()); if (commentContext.docStart) { @@ -722,4 +733,13 @@ public class EnterHandler extends BaseEnterHandler { return docAsterisk; } } + + + @Nullable + public static Language getLanguage(@NotNull DataContext dataContext) { + if (dataContext instanceof UserDataHolder) { + return CONTEXT_LANGUAGE.get((UserDataHolder)dataContext); + } + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInLineCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInLineCommentHandler.java index f09d79813653..19f7e0618f36 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInLineCommentHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterInLineCommentHandler.java @@ -16,15 +16,21 @@ package com.intellij.codeInsight.editorActions.enter; +import com.intellij.codeInsight.editorActions.EnterHandler; import com.intellij.lang.*; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; +import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IElementType; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; @@ -32,29 +38,31 @@ public class EnterInLineCommentHandler extends EnterHandlerDelegateAdapter { @Override public Result preprocessEnter(@NotNull final PsiFile file, @NotNull final Editor editor, @NotNull final Ref caretOffsetRef, @NotNull final Ref caretAdvance, @NotNull final DataContext dataContext, final EditorActionHandler originalHandler) { + final Language language = EnterHandler.getLanguage(dataContext); + if (language == null) return Result.Continue; + final Commenter languageCommenter = LanguageCommenters.INSTANCE.forLanguage(language); + final CodeDocumentationAwareCommenter commenter = languageCommenter instanceof CodeDocumentationAwareCommenter + ? (CodeDocumentationAwareCommenter)languageCommenter : null; + if (commenter == null) return Result.Continue; int caretOffset = caretOffsetRef.get().intValue(); - PsiElement psiAtOffset = file.findElementAt(caretOffset); - if (psiAtOffset != null && psiAtOffset.getTextOffset() < caretOffset) { - ASTNode token = psiAtOffset.getNode(); + if (isInLineComment(editor, caretOffset, commenter.getLineCommentTokenType())) { Document document = editor.getDocument(); - CharSequence text = document.getText(); - final Language language = psiAtOffset.getLanguage(); - final Commenter languageCommenter = LanguageCommenters.INSTANCE.forLanguage(language); - final CodeDocumentationAwareCommenter commenter = languageCommenter instanceof CodeDocumentationAwareCommenter - ? (CodeDocumentationAwareCommenter)languageCommenter:null; - if (commenter != null && token.getElementType() == commenter.getLineCommentTokenType() ) { + PsiDocumentManager.getInstance(file.getProject()).commitDocument(document); + PsiElement psiAtOffset = file.findElementAt(caretOffset); + if (psiAtOffset != null && psiAtOffset.getTextOffset() < caretOffset) { + CharSequence text = document.getText(); final int offset = CharArrayUtil.shiftForward(text, caretOffset, " \t"); - if (offset < document.getTextLength() && text.charAt(offset) != '\n') { String prefix = commenter.getLineCommentPrefix(); - assert prefix != null: "Line Comment type is set but Line Comment Prefix is null!"; + assert prefix != null : "Line Comment type is set but Line Comment Prefix is null!"; if (!StringUtil.startsWith(text, offset, prefix)) { if (text.charAt(caretOffset) != ' ' && !prefix.endsWith(" ")) { prefix += " "; } document.insertString(caretOffset, prefix); return Result.Default; - } else { + } + else { int afterPrefix = offset + prefix.length(); if (afterPrefix < document.getTextLength() && text.charAt(afterPrefix) != ' ') { document.insertString(afterPrefix, " "); @@ -68,4 +76,11 @@ public class EnterInLineCommentHandler extends EnterHandlerDelegateAdapter { } return Result.Continue; } + + private static boolean isInLineComment(@NotNull Editor editor, int offset, IElementType lineCommentType) { + if (offset < 1) return false; + EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter(); + HighlighterIterator iterator = highlighter.createIterator(offset - 1); + return iterator.getTokenType() == lineCommentType; + } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java index bcee3dbd0612..c7bd4fd558d4 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java @@ -439,7 +439,7 @@ public class CodeFormatterFacade { return; } editorFactory = EditorFactory.getInstance(); - editor = editorFactory.createEditor(document, file.getProject()); + editor = editorFactory.createEditor(document, file.getProject(), file.getVirtualFile(), false); } try { final Editor editorToUse = editor;