diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 63b60e03cdf9..aa3186b45d49 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -16,7 +16,6 @@ import com.intellij.lang.documentation.DocumentationSettings; import com.intellij.lang.documentation.DocumentationSettings.InlineCodeHighlightingMode; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.lang.java.JavaDocumentationProvider; -import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; @@ -1912,7 +1911,12 @@ public class JavaDocInfoGenerator { throw new AssertionError(node.toString()); } if (node.regex() != null) { - content = content.replaceAll(node.regex(), replacement.apply("$0")); + try { + content = content.replaceAll(node.regex(), replacement.apply("$0")); + } + catch (IllegalArgumentException | IndexOutOfBoundsException e) { + buffer.append(getSpanForUnresolvedItem()).append("[").append(e.getMessage()).append("]\n"); + } } else if (node.substring() != null) { content = content.replace(node.substring(), replacement.apply(node.substring())); @@ -1926,7 +1930,7 @@ public class JavaDocInfoGenerator { @Override public void visitError(@NotNull ErrorMarkup errorMarkup) { - buffer.append(getSpanForUnresolvedItem()).append("[").append(errorMarkup.message()).append("]"); + buffer.append(getSpanForUnresolvedItem()).append("[").append(errorMarkup.message()).append("]\n"); } }); } diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/SnippetMarkup.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/SnippetMarkup.java index 9bd90dc923e3..f54236dd526d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/SnippetMarkup.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/SnippetMarkup.java @@ -516,7 +516,9 @@ public class SnippetMarkup { regions.push(start.region()); } else if (node instanceof EndRegion end) { if (end.region() == null) { - active.remove(regions.pop()); + if (!regions.isEmpty()) { + active.remove(regions.pop()); + } } else { regions.remove(end.region()); active.remove(end.region()); diff --git a/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.html b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.html new file mode 100644 index 000000000000..a5a773a945e2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.html @@ -0,0 +1,15 @@ +
class Malformed
+
public void malformed() { 
+[@replace: missing 'replacement' attribute]
+[Unsupported attribute: 'hello']
+[Markup tag or attribute expected]
+[@replace: missing 'replacement' attribute]
+[@link: missing 'target' attribute]
+[Unknown type 'none'; only 'link' and 'linkplain' are supported]
+[Dangling meta character '?' near index 0
+???
+^]
+  System.out.println("hello"); 
+}
+
+

\ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.java b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.java new file mode 100644 index 000000000000..c9c077f64865 --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/Malformed.java @@ -0,0 +1,5 @@ +/** + * {@snippet class=Region region=malformed} + */ +class Malformed { +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/snippet-files/Region.java b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/snippet-files/Region.java index b56a79bea76d..311903e81604 100644 --- a/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/snippet-files/Region.java +++ b/java/java-tests/testData/codeInsight/javadocIG/externalSnippet/snippet-files/Region.java @@ -27,4 +27,12 @@ public class Region { System.out.println("abc"); // @replace substring=a replacement=x @replace regex="b(.?)" replacement="$1z" @highlight substring=out } // @end + + // @start region=malformed + public void malformed() { + // @replace @highlight hello=world @unknown + // @replace @highlight @link type=none + System.out.println("hello"); // @replace regex="???" replacement="xyz" + } + // @end } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index b11b82bfbfe3..4b2389c14b3f 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -150,11 +150,15 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase { public void testExternalSnippetTextFile() { createProjectStructure(getTestDataPath() + TEST_DATA_FOLDER + "externalSnippet"); verifyJavadocFor("TextFile"); - } + } public void testExternalSnippetUnresolved() { createProjectStructure(getTestDataPath() + TEST_DATA_FOLDER + "externalSnippet"); verifyJavadocFor("Unresolved"); } + public void testExternalSnippetMalformed() { + createProjectStructure(getTestDataPath() + TEST_DATA_FOLDER + "externalSnippet"); + verifyJavadocFor("Malformed"); + } public void testUnknownInlineTag() { doTestClass(); } public void testUnknownInlineMultilineTag() { doTestClass(); } public void testUnknownTag() { doTestMethod(); }