mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
[java] (IDEA-279250) replace with javadoc intention changed to inspection (ReplaceWithJavadocInspection) + tests changed
GitOrigin-RevId: 4b27beeecd36dcedaa92483176128186747b7e5b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c101e4337c
commit
caddae14f6
@@ -1742,6 +1742,10 @@
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="MissingJavadoc" bundle="messages.JavaBundle" key="inspection.missingJavadoc.display.name"
|
||||
groupKey="group.names.javadoc.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.javaDoc.MissingJavadocInspection"/>
|
||||
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ReplaceWithJavadoc" bundle="messages.JavaBundle" key="inspection.replace.javadoc.display.name"
|
||||
groupKey="group.names.javadoc.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.javaDoc.ReplaceWithJavadocInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="JavadocDeclaration" bundle="messages.JavaBundle" key="inspection.javadocDeclaration.display.name"
|
||||
groupKey="group.names.javadoc.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.javaDoc.JavadocDeclarationInspection" alternativeId="javadoc"/>
|
||||
@@ -2286,4 +2290,4 @@
|
||||
<webServerRootsProvider implementation="org.jetbrains.builtInWebServer.ArtifactWebServerRootsProvider" order="last"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection.javaDoc
|
||||
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.java.JavaBundle
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.javadoc.PsiDocComment
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.annotations.Contract
|
||||
import java.util.*
|
||||
import java.util.function.Predicate
|
||||
import java.util.stream.Collectors
|
||||
import java.util.stream.Stream
|
||||
|
||||
class ReplaceWithJavadocInspection : LocalInspectionTool() {
|
||||
|
||||
companion object {
|
||||
private val LOGGER = Logger.getInstance(
|
||||
ReplaceWithJavadocInspection::class.java.name)
|
||||
}
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return object : JavaElementVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (element !is PsiComment) return
|
||||
if (element is PsiDocComment) return
|
||||
|
||||
val parent: PsiElement = element.getParent()
|
||||
|
||||
if (parent !is PsiMember || parent is PsiAnonymousClass) return
|
||||
val type: PsiElement? = PsiTreeUtil.getPrevSiblingOfType(element, PsiModifierList::class.java)
|
||||
if (type != null) return
|
||||
|
||||
val fix = ReplaceWithJavadocFix()
|
||||
holder.registerProblem(element, JavaBundle.message("inspection.replace.with.javadoc.comment"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReplaceWithJavadocFix : LocalQuickFix {
|
||||
override fun getFamilyName(): String {
|
||||
return JavaBundle.message("inspection.replace.with.javadoc")
|
||||
}
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val element = descriptor.psiElement as? PsiComment ?: return
|
||||
val method = element.parent ?: return
|
||||
|
||||
val child = method.firstChild as? PsiComment ?: return
|
||||
|
||||
val psiFacade = JavaPsiFacade.getInstance(element.project)
|
||||
val factory = psiFacade.elementFactory
|
||||
|
||||
// the set will contain all the comment nodes that are directly before the method's modifier list
|
||||
val commentNodes = mutableSetOf<PsiComment>()
|
||||
|
||||
val javadocText = prepareJavadocComment(child, commentNodes)
|
||||
val javadoc = factory.createDocCommentFromText(javadocText)
|
||||
|
||||
if (commentNodes.isEmpty()) {
|
||||
LOGGER.error("The set of visited node comments is empty")
|
||||
return
|
||||
}
|
||||
|
||||
if (commentNodes.size > 1) {
|
||||
// remove all the comment nodes except the first one
|
||||
commentNodes.stream().skip(1).forEach { obj: PsiComment -> obj.delete() }
|
||||
}
|
||||
|
||||
val item = ContainerUtil.getFirstItem(commentNodes)
|
||||
item.replace(javadoc)
|
||||
}
|
||||
|
||||
@Contract(mutates = "param2")
|
||||
private fun prepareJavadocComment(comment: PsiComment, visited: MutableSet<PsiComment>): String {
|
||||
val commentContent: Collection<String> = siblingsComments(comment, visited)
|
||||
val sb = StringBuilder("/**\n")
|
||||
for (string in commentContent) {
|
||||
val line = string.trim { it <= ' ' }
|
||||
if (line.isEmpty()) continue
|
||||
sb.append("* ")
|
||||
sb.append(line)
|
||||
sb.append("\n")
|
||||
}
|
||||
if (comment is PsiDocComment) {
|
||||
val tags = comment.tags
|
||||
if (tags.size > 0) {
|
||||
val start = tags[0].startOffsetInParent
|
||||
val end = tags[tags.size - 1].textRangeInParent.endOffset
|
||||
sb.append("* ")
|
||||
sb.append(comment.getText(), start, end)
|
||||
sb.append("\n")
|
||||
}
|
||||
}
|
||||
sb.append("*/")
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content of the comment nodes that are right siblings to the comment node
|
||||
*
|
||||
* @param comment a comment node to get siblings for
|
||||
* @param visited a set of visited comment nodes
|
||||
* @return the list of strings which consists of the content of the comment nodes that are either left or right siblings.
|
||||
*/
|
||||
@Contract(mutates = "param2")
|
||||
private fun siblingsComments(comment: PsiComment,
|
||||
visited: MutableSet<in PsiComment>): List<String> {
|
||||
val result = ArrayList<String>()
|
||||
var node: PsiElement? = comment
|
||||
do {
|
||||
if (node is PsiComment) {
|
||||
val commentNode = node
|
||||
visited.add(commentNode)
|
||||
result.addAll(getCommentTextLines(commentNode))
|
||||
}
|
||||
node = node!!.nextSibling
|
||||
}
|
||||
while (node != null && node !is PsiModifierList)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content of a comment as a list of strings.
|
||||
*
|
||||
* @param comment [PsiComment] to examine
|
||||
* @return the content of a comment as a list of strings where each line is an element of the list.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private fun getCommentTextLines(comment: PsiComment): Collection<String> {
|
||||
val lines: Stream<String>
|
||||
lines = if (comment is PsiDocComment) {
|
||||
Arrays.stream(comment.descriptionElements)
|
||||
.map { obj: PsiElement -> obj.text }
|
||||
}
|
||||
else {
|
||||
Arrays.stream(extractLines(comment))
|
||||
}
|
||||
return lines
|
||||
.map { obj: String -> obj.trim { it <= ' ' } }
|
||||
.filter(Predicate.not { obj: String -> obj.isEmpty() })
|
||||
.map { line: String ->
|
||||
if (line.startsWith("*")) line.substring(1)
|
||||
else line
|
||||
}
|
||||
.map { line: String? ->
|
||||
StringUtil.replace(
|
||||
line!!, "*/", "*/")
|
||||
}
|
||||
.collect(Collectors.toList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content from either a C-style block comment or an end-of-line comment as an array of lines
|
||||
*
|
||||
* @param comment [PsiComment] to examine
|
||||
* @return the content of a comment as an array of lines
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private fun extractLines(comment: PsiComment): Array<String> {
|
||||
assert(comment !is PsiDocComment) { "The method can't be called for a javadoc comment." }
|
||||
val commentText = comment.text
|
||||
if (comment.tokenType === JavaTokenType.END_OF_LINE_COMMENT) {
|
||||
return arrayOf(commentText.substring("//".length))
|
||||
}
|
||||
val start = "/*".length
|
||||
val end = commentText.length - "*/".length
|
||||
val content = commentText.substring(start, end)
|
||||
return content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports a regular comment that belongs to a field, method, or class that can be replaced with a Javadoc comment.
|
||||
|
||||
<p><b>Example:</b></p>
|
||||
<pre><code>
|
||||
public class Main {
|
||||
/*
|
||||
* Hello,
|
||||
*/
|
||||
// World!
|
||||
void f() {
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>After the quick-fix is applied:</p>
|
||||
<pre><code>
|
||||
public class Main {
|
||||
/**
|
||||
* Hello,
|
||||
* World!
|
||||
*/
|
||||
void f() {
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +1,9 @@
|
||||
// "Replace with javadoc" "false"
|
||||
import java.util.Iterator;
|
||||
|
||||
class Main {
|
||||
{
|
||||
new Iterable<Integer>() {
|
||||
// <caret>comment
|
||||
// comment
|
||||
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
@@ -1,9 +1,8 @@
|
||||
// "Replace with javadoc" "false"
|
||||
|
||||
class Main {
|
||||
|
||||
public static final void main
|
||||
(String[] args)// 1<caret>
|
||||
(String[] args)// 1
|
||||
/* 2 */
|
||||
{
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
// "Replace with javadoc" "false"
|
||||
|
||||
class Main {
|
||||
|
||||
public static final void main// 1
|
||||
// 2<caret>
|
||||
// 2
|
||||
(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
class Main {
|
||||
|
||||
public static final void // 1
|
||||
// 2
|
||||
main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
class Main {
|
||||
|
||||
public static final /* 1 */ void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
class Main {
|
||||
|
||||
public /* 1 */ static final void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
class Test {
|
||||
/**
|
||||
* Test. Don't report type param 'X' as duplicate of param 'X'.
|
||||
@@ -7,4 +6,4 @@ class Test {
|
||||
* @param <X> my type
|
||||
*/
|
||||
<X> X getValue(String X) {return null;}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
class Test {
|
||||
/**
|
||||
* Test.
|
||||
@@ -8,4 +7,4 @@ class Test {
|
||||
* <warning descr="Duplicate @param tag for parameter '<X>'">@param</warning> <X> another type
|
||||
*/
|
||||
<X> X getValue(String X) {return null;}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// "Replace with javadoc" "false"
|
||||
|
||||
class Main {
|
||||
|
||||
public static final void // 1<caret>
|
||||
// 2
|
||||
main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Replace with javadoc" "false"
|
||||
|
||||
class Main {
|
||||
|
||||
public static final /* 1<caret> */ void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Replace with javadoc" "false"
|
||||
|
||||
class Main {
|
||||
|
||||
public /* 1<caret> */ static final void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection;
|
||||
import com.intellij.codeInspection.javaDoc.JavadocDeclarationInspection;
|
||||
import com.intellij.codeInspection.javaDoc.ReplaceWithJavadocInspection;
|
||||
import com.intellij.model.psi.PsiSymbolReference;
|
||||
import com.intellij.openapi.paths.UrlReference;
|
||||
import com.intellij.openapi.paths.WebReference;
|
||||
@@ -31,7 +32,7 @@ public class JavadocDeclarationHighlightingTest extends LightDaemonAnalyzerTestC
|
||||
super.setUp();
|
||||
myInspection = new JavadocDeclarationInspection();
|
||||
myInspection.IGNORE_THROWS_DUPLICATE = false;
|
||||
enableInspectionTools(myInspection, new JavaDocReferenceInspection());
|
||||
enableInspectionTools(myInspection, new JavaDocReferenceInspection(), new ReplaceWithJavadocInspection());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,6 +124,12 @@ public class JavadocDeclarationHighlightingTest extends LightDaemonAnalyzerTestC
|
||||
public void testOnlyEmptyLinesInSnippet() { doTest(); }
|
||||
public void testSnippetInstructionsWithUnhandledThrowable() { doTest(); }
|
||||
public void testJavaDocWithSpaces() { doTest(); }
|
||||
public void testCommentsAfterArguments() { doTest(); }
|
||||
public void testAnonymousClass() { doTest(); }
|
||||
public void testCommentsBeforeArguments() { doTest(); }
|
||||
public void testCommentsInModifierList() { doTest(); }
|
||||
public void testCommentsBeforeType() { doTest(); }
|
||||
public void testCommentsBeforeName() { doTest(); }
|
||||
|
||||
public void testIssueLinksInJavaDoc() {
|
||||
IssueNavigationConfiguration navigationConfiguration = IssueNavigationConfiguration.getInstance(getProject());
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2000-2022 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.codeInspection.javaDoc.ReplaceWithJavadocInspection
|
||||
import com.intellij.java.JavaBundle
|
||||
import com.siyeh.ig.IGQuickFixesTestCase
|
||||
|
||||
class ReplaceWithJavadocInspectionFixTest : IGQuickFixesTestCase() {
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
myFixture.enableInspections(ReplaceWithJavadocInspection())
|
||||
myRelativePath = "javadoc/replace_with_javadoc"
|
||||
myDefaultHint = JavaBundle.message("inspection.replace.with.javadoc")
|
||||
}
|
||||
|
||||
fun testJavadocWithTags() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testMergeJavadocWIthEndOfLineAndBlock() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEndOfLine() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEmptyEndOfLine() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testEmptyBlockComment() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testCommentsBeforeAndAfterModifierListTypeAndParams() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testBlockComment() {
|
||||
doTest()
|
||||
}
|
||||
}
|
||||
@@ -468,6 +468,7 @@ inspection.suspicious.ternary.in.varargs.quickfix=Wrap in array initializer
|
||||
inspection.insert.literal.underscores.display.name=Unreadable numeric literal
|
||||
inspection.insert.literal.underscores.family.name=Insert underscores into numeric literal
|
||||
inspection.missingJavadoc.display.name=Missing Javadoc
|
||||
inspection.replace.javadoc.display.name=Comment replaceable with Javadoc
|
||||
inspection.missingJavadoc.label.minimalVisibility=Minimal visibility:
|
||||
inspection.missingJavadoc.label.requiredTags=Required tags:
|
||||
inspection.javadocDeclaration.display.name=Javadoc declaration problems
|
||||
@@ -509,6 +510,8 @@ inspection.javadoc.problem.wrong.tag=Wrong tag {0}
|
||||
inspection.javadoc.ref.display.name=Declaration has problems in Javadoc references
|
||||
inspection.javadoc.blank.lines.display.name=Blank line should be replaced with <p> to break lines
|
||||
inspection.javadoc.blank.lines.message=Blank line will be ignored
|
||||
inspection.replace.with.javadoc=Replace with Javadoc comment
|
||||
inspection.replace.with.javadoc.comment=Comment can be converted to Javadoc
|
||||
inspection.javadoc.blank.lines.fix.name=Insert <p>
|
||||
inspection.javadoc.blank.lines.fix.family.name=Replace blank lines with <p>
|
||||
inspection.javadoc.link.as.plain.text.display.name=Link specified as plain text
|
||||
@@ -1759,4 +1762,4 @@ remove.var.keyword.text=Remove 'var'
|
||||
intention.family.name.upgrade.jdk=Upgrade JDK
|
||||
intention.name.upgrade.jdk.to=Upgrade JDK to {0}+
|
||||
intention.family.name.box.primitive.in.conditional.branch=Box primitive value in conditional branch
|
||||
progress.title.detecting.jdk=Detecting JDK
|
||||
progress.title.detecting.jdk=Detecting JDK
|
||||
|
||||
@@ -167,12 +167,6 @@
|
||||
<categoryKey>intention.category.comments</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.comment.ReplaceWithJavadocIntention</className>
|
||||
<bundleName>messages.JavaBundle</bundleName>
|
||||
<categoryKey>intention.category.comments</categoryKey>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.comment.MoveCommentToSeparateLineIntention</className>
|
||||
<bundleName>messages.JavaBundle</bundleName>
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.siyeh.ipp.comment;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ipp.base.Intention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Converts C-style block comments or end-of-line comments that belong to an element of the {@link PsiMember} type to javadoc.
|
||||
*/
|
||||
public class ReplaceWithJavadocIntention extends Intention {
|
||||
private static final Logger LOGGER = Logger.getInstance(ReplaceWithJavadocIntention.class.getName());
|
||||
|
||||
@Override
|
||||
protected void processIntention(@NotNull PsiElement element) {
|
||||
if (!(element instanceof PsiComment)) return;
|
||||
|
||||
final PsiElement method = element.getParent();
|
||||
if (method == null) return;
|
||||
|
||||
final PsiElement child = method.getFirstChild();
|
||||
if (!(child instanceof PsiComment)) return;
|
||||
final PsiComment firstCommentOfMethod = (PsiComment)child;
|
||||
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(element.getProject());
|
||||
final PsiElementFactory factory = psiFacade.getElementFactory();
|
||||
|
||||
// the set will contain all the comment nodes that are directly before the method's modifier list
|
||||
final Set<PsiComment> commentNodes = new HashSet<>();
|
||||
|
||||
final String javadocText = prepareJavadocComment(firstCommentOfMethod, commentNodes);
|
||||
final PsiDocComment javadoc = factory.createDocCommentFromText(javadocText);
|
||||
|
||||
if (commentNodes.isEmpty()) {
|
||||
LOGGER.error("The set of visited node comments is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (commentNodes.size() > 1) {
|
||||
// remove all the comment nodes except the first one
|
||||
commentNodes.stream().skip(1).forEach(PsiElement::delete);
|
||||
}
|
||||
|
||||
final PsiComment item = ContainerUtil.getFirstItem(commentNodes);
|
||||
item.replace(javadoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content of the comment nodes that are right siblings to the comment node
|
||||
*
|
||||
* @param comment a comment node to get siblings for
|
||||
* @param visited a set of visited comment nodes
|
||||
* @return the list of strings which consists of the content of the comment nodes that are either left or right siblings.
|
||||
*/
|
||||
@Contract(mutates = "param2")
|
||||
private static @NotNull List<@NotNull String> siblingsComments(@NotNull PsiComment comment,
|
||||
@NotNull Set<? super @NotNull PsiComment> visited) {
|
||||
final List<String> result = new ArrayList<>();
|
||||
PsiElement node = comment;
|
||||
do {
|
||||
if (node instanceof PsiComment) {
|
||||
final PsiComment commentNode = (PsiComment)node;
|
||||
|
||||
visited.add(commentNode);
|
||||
result.addAll(getCommentTextLines(commentNode));
|
||||
}
|
||||
node = node.getNextSibling();
|
||||
}
|
||||
while (node != null && !(node instanceof PsiModifierList));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the collection of strings into a string in the javadoc format:
|
||||
* <ul>
|
||||
* <li>The resulting string starts with <code>/**</code></li>
|
||||
* <li>Each line from the collection is precluded with '<code>*</code>'</li>
|
||||
* <li>The resulting string ends with <code>*/</code></li>
|
||||
* </ul>
|
||||
* @return the string in the javadoc format.
|
||||
*/
|
||||
@Contract(mutates = "param2")
|
||||
private static @NotNull String prepareJavadocComment(PsiComment comment, @NotNull Set<@NotNull PsiComment> visited) {
|
||||
final @NotNull Collection<String> commentContent = siblingsComments(comment, visited);
|
||||
final StringBuilder sb = new StringBuilder("/**\n");
|
||||
|
||||
for (String string : commentContent) {
|
||||
final String line = string.trim();
|
||||
if (line.isEmpty()) continue;
|
||||
sb.append("* ");
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
if (comment instanceof PsiDocComment) {
|
||||
PsiDocComment javadoc = (PsiDocComment)comment;
|
||||
final PsiDocTag[] tags = javadoc.getTags();
|
||||
if (tags.length > 0) {
|
||||
final int start = tags[0].getStartOffsetInParent();
|
||||
final int end = tags[tags.length - 1].getTextRangeInParent().getEndOffset();
|
||||
sb.append("* ");
|
||||
sb.append(comment.getText(), start, end);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
sb.append("*/");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content of a comment as a list of strings.
|
||||
*
|
||||
* @param comment {@link PsiComment} to examine
|
||||
* @return the content of a comment as a list of strings where each line is an element of the list.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private static List<String> getCommentTextLines(@NotNull PsiComment comment) {
|
||||
final Stream<String> lines;
|
||||
if (comment instanceof PsiDocComment) {
|
||||
final PsiDocComment docComment = (PsiDocComment)comment;
|
||||
|
||||
lines = Arrays.stream(docComment.getDescriptionElements())
|
||||
.map(PsiElement::getText);
|
||||
}
|
||||
else {
|
||||
lines = Arrays.stream(extractLines(comment));
|
||||
}
|
||||
return lines
|
||||
.map(String::trim)
|
||||
.filter(Predicate.not(String::isEmpty))
|
||||
.map(line -> line.startsWith("*") ? line.substring(1) : line)
|
||||
.map(line -> StringUtil.replace(line, "*/", "*/"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the content from either a C-style block comment or an end-of-line comment as an array of lines
|
||||
*
|
||||
* @param comment {@link PsiComment} to examine
|
||||
* @return the content of a comment as an array of lines
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
private static String @NotNull[] extractLines(@NotNull PsiComment comment) {
|
||||
assert !(comment instanceof PsiDocComment) : "The method can't be called for a javadoc comment.";
|
||||
|
||||
final String commentText = comment.getText();
|
||||
if (comment.getTokenType() == JavaTokenType.END_OF_LINE_COMMENT) {
|
||||
return new String[] { commentText.substring("//".length()) };
|
||||
}
|
||||
|
||||
final int start = "/*".length();
|
||||
final int end = commentText.length() - "*/".length();
|
||||
|
||||
final String content = commentText.substring(start, end);
|
||||
return content.split("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that returns true when a {@link PsiElement} is of the {@link PsiComment}(excluding {@link PsiDocComment}) type
|
||||
* which belong to a {@link PsiMember} type to convert it to javadoc.
|
||||
*
|
||||
* @return predicate to check if a comment can be converted to a javadoc.
|
||||
*/
|
||||
@Override
|
||||
protected @NotNull PsiElementPredicate getElementPredicate() {
|
||||
return element -> {
|
||||
if (!(element instanceof PsiComment)) return false;
|
||||
if (element instanceof PsiDocComment) return false;
|
||||
|
||||
final PsiComment comment = (PsiComment)element;
|
||||
|
||||
final PsiElement parent = comment.getParent();
|
||||
if (!(parent instanceof PsiMember) || parent instanceof PsiAnonymousClass) return false;
|
||||
|
||||
// the comment node might have a method as its parent,
|
||||
// but the comment itself can be defined before/after the modifier list/type/name/parameters of the method
|
||||
// Such comments are not candidates to be converted to javadoc
|
||||
final PsiElement type = PsiTreeUtil.getPrevSiblingOfType(comment, PsiModifierList.class);
|
||||
|
||||
return type == null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
public class Main {
|
||||
<spot>/**
|
||||
* Hello,
|
||||
* World!
|
||||
*/</spot>
|
||||
void f() {
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
public class Main {
|
||||
<spot>/*
|
||||
* Hello,
|
||||
*/
|
||||
// World!</spot>
|
||||
void f() {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Converts a regular comment that belongs to a field, method, or class into a Javadoc comment.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.siyeh.ipp.comment;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public class ReplaceWithJavadocIntentionTest extends LightQuickFixParameterizedTestCase {
|
||||
|
||||
@Override
|
||||
protected @NonNls String getBasePath() {
|
||||
return "/comment/to_javadoc";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user