mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[javadoc] IDEA-285556 Support language injection into snippet
Add a enter handler for snippets to insert leading asterisks if needed. Signed-off-by: Nikita Eshkeev <nikita.eshkeev@jetbrains.com> GitOrigin-RevId: 365eaf0c873f11673dd03cbbb7b4395410e0e110
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c9eefd16ec
commit
95e53ac831
@@ -977,6 +977,7 @@
|
||||
<testFinder implementation="com.intellij.testIntegration.JavaTestFinder"/>
|
||||
<filePasteProvider implementation="com.intellij.ide.JavaFilePasteProvider" order="before fileList"/>
|
||||
<enterHandlerDelegate implementation="com.intellij.javadoc.EnterInJavadocParamDescriptionHandler"/>
|
||||
<enterHandlerDelegate implementation="com.intellij.javadoc.JavadocSnippetEnterHandler"/>
|
||||
<editorNavigation implementation="com.intellij.javadoc.JavadocNavigationDelegate"/>
|
||||
<methodNavigationOffsetProvider implementation="com.intellij.codeInsight.navigation.JavaMethodNavigationOffsetProvider"/>
|
||||
<dom.customAnnotationChecker implementation="com.intellij.util.xml.impl.ExtendsClassChecker"/>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.javadoc;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtilEx;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
import com.intellij.psi.javadoc.PsiSnippetDocTag;
|
||||
import com.intellij.util.DocumentUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JavadocSnippetEnterHandler extends EnterHandlerDelegateAdapter {
|
||||
|
||||
@Override
|
||||
public Result postProcessEnter(@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
@NotNull DataContext dataContext) {
|
||||
if (!(file instanceof PsiJavaFile) || !file.isValid()) return Result.Continue;
|
||||
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
int caretOffset = caretModel.getOffset();
|
||||
|
||||
final PsiElement current = file.findElementAt(caretOffset);
|
||||
if (current == null) return Result.Continue;
|
||||
|
||||
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(file.getProject());
|
||||
final PsiSnippetDocTag host = ObjectUtils.tryCast(injectedLanguageManager.getInjectionHost(current), PsiSnippetDocTag.class);
|
||||
if (host == null) return Result.Continue;
|
||||
|
||||
final Document document = editor.getDocument();
|
||||
final String prefix = calcPrefix(host);
|
||||
|
||||
final int lineStartOffset = DocumentUtil.getLineStartOffset(caretOffset, document);
|
||||
document.insertString(lineStartOffset, prefix);
|
||||
|
||||
caretModel.moveToOffset(caretOffset + prefix.length());
|
||||
EditorModificationUtilEx.scrollToCaret(editor);
|
||||
|
||||
return Result.Continue;
|
||||
}
|
||||
|
||||
private static String calcPrefix(PsiSnippetDocTag host) {
|
||||
final PsiFile file = host.getContainingFile();
|
||||
final String text = file.getText();
|
||||
|
||||
int offset = host.getTextOffset();
|
||||
int asteriskOffset = offset;
|
||||
while (text.charAt(offset) != '\n' && offset > 0) {
|
||||
if (text.charAt(offset) == '*') asteriskOffset = offset;
|
||||
offset --;
|
||||
}
|
||||
|
||||
final String prefix = text.substring(offset + 1, asteriskOffset);
|
||||
|
||||
final JavaCodeStyleSettings settings = CodeStyle.getCustomSettings(file, JavaCodeStyleSettings.class);
|
||||
|
||||
return settings.JD_LEADING_ASTERISKS_ARE_ENABLED ? prefix + "*" : prefix;
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* void f() {
|
||||
* System.out.println();
|
||||
* }
|
||||
* void g() {}
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* void f() {
|
||||
* System.out.println();
|
||||
* <caret>
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* <caret>
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* public void f() {
|
||||
* <caret>
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
class Main {
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* void f() {
|
||||
* System.out.println();
|
||||
* }<caret>void g() {}
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* void f() {
|
||||
* System.out.println();<caret>
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
class Main {
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {<caret>}
|
||||
* }
|
||||
*/
|
||||
void f() {}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "_ignore" "true"
|
||||
|
||||
/**
|
||||
* A simple program.
|
||||
* {@snippet :
|
||||
* class HelloWorld {
|
||||
* public void f() {<caret>}
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
class Main {
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight.javadoc;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.ActionHint;
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JavadocSnippetEnterHandlerTest extends LightQuickFixParameterizedTestCase {
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/javadoc/snippet/enterhandler";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAction(@NotNull ActionHint actionHint, @NotNull String testFullPath, @NotNull String testName) {
|
||||
executeAction("EditorEnter");
|
||||
|
||||
checkResult(testName);
|
||||
}
|
||||
|
||||
private void checkResult(@NotNull final String testName) {
|
||||
final String expectedFilePath = getBasePath() + "/after" + testName;
|
||||
checkResultByFile("In file: " + expectedFilePath, expectedFilePath, false);
|
||||
}
|
||||
}
|
||||
+63
-14
@@ -6,13 +6,17 @@ import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.editorActions.CodeDocumentationUtil;
|
||||
import com.intellij.codeInsight.editorActions.EnterHandler;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
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.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,7 +37,6 @@ public class EnterBetweenBracesFinalHandler extends EnterHandlerDelegateAdapter
|
||||
if (!CodeInsightSettings.getInstance().SMART_INDENT_ON_ENTER) {
|
||||
return Result.Continue;
|
||||
}
|
||||
|
||||
Document document = editor.getDocument();
|
||||
CharSequence text = document.getCharsSequence();
|
||||
int caretOffset = caretOffsetRef.get().intValue();
|
||||
@@ -43,29 +46,76 @@ public class EnterBetweenBracesFinalHandler extends EnterHandlerDelegateAdapter
|
||||
return Result.Continue;
|
||||
}
|
||||
|
||||
final int line = document.getLineNumber(caretOffset);
|
||||
final int start = document.getLineStartOffset(line);
|
||||
final CodeDocumentationUtil.CommentContext commentContext =
|
||||
CodeDocumentationUtil.tryParseCommentContext(file, text, caretOffset, start);
|
||||
|
||||
// special case: enter inside "()" or "{}"
|
||||
String indentInsideJavadoc = helper.isInComment(file, editor, caretOffset) && commentContext.docAsterisk
|
||||
? CodeDocumentationUtil.getIndentInsideJavadoc(document, caretOffset)
|
||||
: null;
|
||||
final Data data = new Data(file, document, caretOffset);
|
||||
final String indentInsideJavadoc = data.getIndentInsideJavadoc(helper, editor);
|
||||
|
||||
originalHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
|
||||
|
||||
Project project = editor.getProject();
|
||||
if (indentInsideJavadoc != null &&
|
||||
project != null &&
|
||||
CodeStyleManager.getInstance(project).getDocCommentSettings(file).isLeadingAsteriskEnabled()) {
|
||||
document.insertString(editor.getCaretModel().getOffset(), "*" + indentInsideJavadoc);
|
||||
data.isLeadingAsteriskEnabled()) {
|
||||
editor.getDocument().insertString(editor.getCaretModel().getOffset(), "*" + indentInsideJavadoc);
|
||||
}
|
||||
|
||||
helper.formatAtOffset(file, editor, editor.getCaretModel().getOffset(), EnterHandler.getLanguage(dataContext));
|
||||
return indentInsideJavadoc == null ? Result.Continue : Result.DefaultForceIndent;
|
||||
}
|
||||
|
||||
private static final class Data {
|
||||
private final @NotNull PsiFile myFile;
|
||||
private final @NotNull Document myDocument;
|
||||
private final @NotNull CharSequence myText;
|
||||
private final int myOffset;
|
||||
|
||||
private Data(@NotNull PsiFile file,
|
||||
@NotNull Document document,
|
||||
int offset) {
|
||||
final PsiElement element = file.findElementAt(offset);
|
||||
|
||||
if (element != null) {
|
||||
final PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(element);
|
||||
if (injectionHost != null) {
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(element.getProject());
|
||||
final Document hostDocument = documentManager.getDocument(injectionHost.getContainingFile());
|
||||
if (hostDocument != null) {
|
||||
myDocument = hostDocument;
|
||||
myText = hostDocument.getCharsSequence();
|
||||
myFile = injectionHost.getContainingFile();
|
||||
myOffset = injectionHost.getTextOffset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myFile = file;
|
||||
myDocument = document;
|
||||
myText = document.getText();
|
||||
myOffset = offset;
|
||||
}
|
||||
|
||||
public @Nullable String getIndentInsideJavadoc(EnterBetweenBracesDelegate helper, Editor editor) {
|
||||
final CodeDocumentationUtil.CommentContext commentContext = getCommentContext();
|
||||
return isInComment(helper, editor) && commentContext.docAsterisk
|
||||
? CodeDocumentationUtil.getIndentInsideJavadoc(myDocument, myOffset)
|
||||
: null;
|
||||
}
|
||||
|
||||
private @NotNull CodeDocumentationUtil.CommentContext getCommentContext() {
|
||||
final int line = myDocument.getLineNumber(myOffset);
|
||||
final int start = myDocument.getLineStartOffset(line);
|
||||
return CodeDocumentationUtil.tryParseCommentContext(myFile, myText, myOffset, start);
|
||||
}
|
||||
|
||||
private boolean isInComment(final EnterBetweenBracesDelegate helper, Editor editor) {
|
||||
return helper.isInComment(myFile, editor, myOffset);
|
||||
}
|
||||
|
||||
private boolean isLeadingAsteriskEnabled() {
|
||||
return CodeStyleManager.getInstance(myFile.getProject()).getDocCommentSettings(myFile).isLeadingAsteriskEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isApplicable(@NotNull PsiFile file,
|
||||
@NotNull Editor editor,
|
||||
CharSequence documentText,
|
||||
@@ -79,8 +129,7 @@ public class EnterBetweenBracesFinalHandler extends EnterHandlerDelegateAdapter
|
||||
!helper.bracesAreInTheSameElement(file, editor, prevCharOffset, nextCharOffset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected EnterBetweenBracesDelegate getLanguageImplementation(@Nullable Language language) {
|
||||
protected static @NotNull EnterBetweenBracesDelegate getLanguageImplementation(@Nullable Language language) {
|
||||
if (language != null) {
|
||||
final EnterBetweenBracesDelegate helper = EnterBetweenBracesDelegate.EP_NAME.forLanguage(language);
|
||||
if (helper != null) {
|
||||
|
||||
Reference in New Issue
Block a user