From 4682103c9dc681ce07d7c4b523499df408bc35a4 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Wed, 20 Aug 2025 17:05:28 +0200 Subject: [PATCH] fix lazy parsers for doc comments - forgot to close the root marker in the prev commit - use JavaDocLexer GitOrigin-RevId: 400206b6588a16b8ba2396c69b055bb491eda942 --- .../lang/java/parser/BasicJavaParserUtil.java | 18 +++++------ .../impl/source/BasicJavaDummyElement.java | 7 +++-- .../lazyParser/JavaDocCommentParser.kt | 12 +++++++- .../element/lazyParser/JavaDocTypeParser.kt | 5 +++- .../syntax/element/lazyParser/ParsingUtil.kt | 30 +++++++++++++++++++ 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/ParsingUtil.kt diff --git a/java/java-frontback-psi-impl/src/com/intellij/lang/java/parser/BasicJavaParserUtil.java b/java/java-frontback-psi-impl/src/com/intellij/lang/java/parser/BasicJavaParserUtil.java index 14887dfa3fd7..72487437a6fa 100644 --- a/java/java-frontback-psi-impl/src/com/intellij/lang/java/parser/BasicJavaParserUtil.java +++ b/java/java-frontback-psi-impl/src/com/intellij/lang/java/parser/BasicJavaParserUtil.java @@ -2,6 +2,7 @@ package com.intellij.lang.java.parser; import com.intellij.core.JavaPsiBundle; +import com.intellij.java.syntax.element.lazyParser.ParsingUtil; import com.intellij.java.syntax.lexer.JavaDocLexer; import com.intellij.java.syntax.lexer.JavaLexer; import com.intellij.lang.*; @@ -12,6 +13,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.Pair; +import com.intellij.platform.syntax.SyntaxElementType; import com.intellij.platform.syntax.lexer.Lexer; import com.intellij.platform.syntax.lexer.TokenList; import com.intellij.platform.syntax.parser.SyntaxTreeBuilder; @@ -26,6 +28,7 @@ import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.indexing.IndexingDataKeys; +import kotlin.Unit; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -313,16 +316,13 @@ public final class BasicJavaParserUtil { long startTime = System.nanoTime(); SyntaxTreeBuilder builder = psiBuilder.getSyntaxTreeBuilder(); - SyntaxTreeBuilder.Marker root = builder.mark(); - wrapper.parse(builder, level); - if (!builder.eof()) { - if (!eatAll) throw new AssertionError("Unexpected token: '" + builder.getTokenText() + "'"); - final SyntaxTreeBuilder.Marker extras = builder.mark(); - while (!builder.eof()) builder.advanceLexer(); - extras.error(JavaPsiBundle.message("unexpected.tokens")); - } ElementTypeConverter converter = ElementTypeConverters.getConverter(JavaLanguage.INSTANCE); - root.done(ElementTypeConverterKt.convertNotNull(converter, chameleon.getElementType())); + SyntaxElementType type = ElementTypeConverterKt.convertNotNull(converter, chameleon.getElementType()); + ParsingUtil.parseFragment(builder, type, eatAll, () -> { + wrapper.parse(builder, level); + return Unit.INSTANCE; + }); + ASTNode result = psiBuilder.getTreeBuilt().getFirstChildNode(); ParsingDiagnostics.registerParse(builder, chameleon.getElementType().getLanguage(), System.nanoTime() - startTime); return result; diff --git a/java/java-frontback-psi-impl/src/com/intellij/psi/impl/source/BasicJavaDummyElement.java b/java/java-frontback-psi-impl/src/com/intellij/psi/impl/source/BasicJavaDummyElement.java index 3b89ab32920b..324f5cbff956 100644 --- a/java/java-frontback-psi-impl/src/com/intellij/psi/impl/source/BasicJavaDummyElement.java +++ b/java/java-frontback-psi-impl/src/com/intellij/psi/impl/source/BasicJavaDummyElement.java @@ -1,6 +1,7 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.psi.impl.source; +import com.intellij.java.syntax.element.lazyParser.IncompleteFragmentParsingException; import com.intellij.lang.java.parser.BasicJavaParserUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.impl.source.tree.FileElement; @@ -53,7 +54,7 @@ public class BasicJavaDummyElement extends FileElement { try { return super.getFirstChildNode(); } - catch (AssertionError e) { + catch (IncompleteFragmentParsingException e) { myParserError = e; return null; // masquerade parser errors } @@ -64,7 +65,7 @@ public class BasicJavaDummyElement extends FileElement { try { return super.getLastChildNode(); } - catch (AssertionError e) { + catch (IncompleteFragmentParsingException e) { myParserError = e; return null; // masquerade parser errors } diff --git a/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocCommentParser.kt b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocCommentParser.kt index e74820f30292..ecdfd0b741fd 100644 --- a/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocCommentParser.kt +++ b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocCommentParser.kt @@ -2,9 +2,12 @@ package com.intellij.java.syntax.element.lazyParser import com.intellij.java.syntax.element.JavaDocSyntaxElementType +import com.intellij.java.syntax.lexer.JavaDocLexer import com.intellij.java.syntax.parser.JavaDocParser +import com.intellij.platform.syntax.LazyLexingContext import com.intellij.platform.syntax.LazyParser import com.intellij.platform.syntax.LazyParsingContext +import com.intellij.platform.syntax.lexer.Lexer import com.intellij.platform.syntax.parser.ProductionResult import com.intellij.platform.syntax.parser.prepareProduction import com.intellij.pom.java.LanguageLevel @@ -12,7 +15,9 @@ import com.intellij.pom.java.LanguageLevel internal class JavaDocCommentParser : LazyParser { override fun parse(parsingContext: LazyParsingContext): ProductionResult { val syntaxTreeBuilder = parsingContext.syntaxTreeBuilder - JavaDocParser(syntaxTreeBuilder, LanguageLevel.HIGHEST).parseDocCommentText() + parseFragment(syntaxTreeBuilder, JavaDocSyntaxElementType.DOC_COMMENT, false) { + JavaDocParser(syntaxTreeBuilder, languageLevel).parseDocCommentText() + } return prepareProduction(syntaxTreeBuilder) } @@ -25,4 +30,9 @@ internal class JavaDocCommentParser : LazyParser { newText.startsWith("/**") && newText.endsWith("*/") } + + override fun createLexer(lexingContext: LazyLexingContext): Lexer = + JavaDocLexer(languageLevel) + + private val languageLevel get() = LanguageLevel.HIGHEST } \ No newline at end of file diff --git a/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocTypeParser.kt b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocTypeParser.kt index 200e79769c62..b4283441d5ac 100644 --- a/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocTypeParser.kt +++ b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/JavaDocTypeParser.kt @@ -1,6 +1,7 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.syntax.element.lazyParser +import com.intellij.java.syntax.element.JavaDocSyntaxElementType import com.intellij.java.syntax.lexer.JavaLexer import com.intellij.java.syntax.lexer.JavaTypeEscapeLexer import com.intellij.java.syntax.parser.JavaDocParser @@ -16,7 +17,9 @@ import com.intellij.pom.java.LanguageLevel internal class JavaDocTypeParser : LazyParser { override fun parse(parsingContext: LazyParsingContext): ProductionResult { val syntaxTreeBuilder = parsingContext.syntaxTreeBuilder - JavaDocParser(syntaxTreeBuilder, languageLevel).parseJavadocType(JavaParser(languageLevel)) + parseFragment(syntaxTreeBuilder, JavaDocSyntaxElementType.DOC_TYPE_HOLDER, false) { + JavaDocParser(syntaxTreeBuilder, languageLevel).parseJavadocType(JavaParser(languageLevel)) + } return prepareProduction(syntaxTreeBuilder) } diff --git a/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/ParsingUtil.kt b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/ParsingUtil.kt new file mode 100644 index 000000000000..40acd473c012 --- /dev/null +++ b/java/java-syntax/src/com/intellij/java/syntax/element/lazyParser/ParsingUtil.kt @@ -0,0 +1,30 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@file:JvmName("ParsingUtil") + +package com.intellij.java.syntax.element.lazyParser + +import com.intellij.java.syntax.JavaSyntaxBundle +import com.intellij.platform.syntax.SyntaxElementType +import com.intellij.platform.syntax.parser.SyntaxTreeBuilder +import kotlin.jvm.JvmName + +inline fun parseFragment( + builder: SyntaxTreeBuilder, + type: SyntaxElementType, + eatAll: Boolean = false, + block: () -> Unit, +) { + val root = builder.mark() + block() + if (!builder.eof()) { + if (!eatAll) throw IncompleteFragmentParsingException("Unexpected token: '${builder.tokenText}'") + val extras = builder.mark() + while (!builder.eof()) { + builder.advanceLexer() + } + extras.error(JavaSyntaxBundle.message("unexpected.tokens")) + } + root.done(type) +} + +class IncompleteFragmentParsingException(message: String) : RuntimeException(message) \ No newline at end of file