Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@yuriioliinyk4 yuriioliinyk4 marked this pull request as ready for review December 22, 2025 01:21
children = listOf(
Text(
"""
|/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test and the test below, WholeFileSnippet.java is used from resources, which contain copyright. The output of the test is whole file content including the copyright, which is expected. I’m concerned about whether this is okay, since the copyright header may be updated by a script in the future, which could break those tests. Should I change something here, or is it better to leave it as is?

}

val substring = attributes["substring"]?.htmlEscape()
val regex = attributes["regex"]?.htmlEscape()?.toRegex()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

htmlEscape is needed to apply here to match literal symbols such as [&, <, >, "], because htmlEscape function is applied to the raw line before applying any markup. But < and > can be used in regex constructs, for instance lookbehind. Should we adjust the logic to handle this, or leave it as is, given that such cases are quite rare and unlikely to occur?

Mentioned function:
public fun String.htmlEscape(): String = replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need htmlEscape here? It seems unnecessary, since the result is result.replace(regex) { match -> match.value.wrapInTag() } that is, the escaped value is not used in the returned value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

htmlEscape is needed to match literal symbol such as [&, <, >, "], because htmlEscape function is applied to the raw line before applying any markup.

Without htmlEscape on regex following examples wont work:
// @replace regex='".*"' replacement="..."
or
// @replace regex='"(.*)"' replacement='"I said, $1"'

because " in regex pattern wont be matched, since " in the line were changed to the &quot;

Copy link
Contributor

@vmishenev vmishenev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


val psiFiles = sourceRoots.parallelMap { sourceRoot ->
sourceRoot.absoluteFile.walkTopDown().mapNotNull {
sourceRoot.absoluteFile.walkTopDown().filter { !it.path.contains("/snippet-files") }.mapNotNull {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: if sourceRoot contains "snippet-files/", the whole source root will be filter out. Can you fix it?
nitpick: filterNot is better for readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see 61f298c

snippet: PsiSnippetDocTag
): String {
val value = snippet.valueElement ?: run {
logger.error("@snippet: unable to resolve snippet")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger.warn is more appropriate here. logger.error is intended for more fatal conditions. See the KDoc for logger.error.

Also, could you add some information about the snippet, for example, its location? (and in the messages below)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see 85d2ecc

}

if (parsedSnippet.isBlank()) {
logger.error("@snippet: unable to resolve snippet")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick:

logger.error("@snippet: unable to resolve snippet")
SNIPPET_NOT_RESOLVED

looks like a code duplication. Maybe it’s better to extract it into a function.

}

val substring = attributes["substring"]?.htmlEscape()
val regex = attributes["regex"]?.htmlEscape()?.toRegex()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need htmlEscape here? It seems unnecessary, since the result is result.replace(regex) { match -> match.value.wrapInTag() } that is, the escaped value is not used in the returned value.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements support for the @snippet Javadoc tag introduced in JEP 413 (Java 18). The snippet tag provides a modern alternative to @code and <pre> blocks, with better support for generics, annotations, external files, regions, and markup features like highlighting, replacing, and linking.

Key changes include:

  • Implementation of snippet parsing with support for inline snippets, external files from snippet-files, and files from the samples configuration path
  • Support for snippet regions using @start/@end markers
  • Support for markup tags (@highlight, @replace, @link) within snippets
  • Updates to parser signatures to pass DokkaSourceSet through the call chain to enable snippet path resolution

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
SnippetToHtmlConverter.kt New file implementing the core snippet parsing and conversion logic with support for all JEP 413 features
PsiElementToHtmlConverter.kt Integrates snippet converter into the Javadoc parsing pipeline
HtmlToDocTagConverter.kt Adds lang attribute handling for <pre> tags to support language-specific code blocks
PsiDocTagParser.kt Updated to pass DokkaContext and DokkaSourceSet through the parsing chain
JavadocParser.kt, JavaDocCommentParser.kt, DocCommentParser.kt Updated signatures to accept and propagate DokkaSourceSet parameter
DokkaPsiParser.kt Updated to pass sourceSet to documentation parsing methods
DefaultPsiToDocumentableTranslator.kt Added filtering to exclude snippet-files directory from analysis
KotlinDocCommentParser.kt, DescriptorKotlinDocCommentParser.kt, KDocProvider.kt Updated to propagate sourceSet through documentation parsing
DefaultSymbolToDocumentableTranslator.kt Updated to pass sourceSet to Javadoc parsing
SyntheticElementDocumentationProvider.kt Updated to accept and use sourceSet parameter
JavaAnalysisPlugin.kt Refactored to pass DokkaContext to PsiDocTagParser at creation time
JavadocParserTest.kt Package renamed from parsers to parsers.javadoc and minor test updates
SnippetTest.kt Comprehensive test suite covering all snippet features and edge cases
Test resources Sample snippet files for testing external snippet functionality
analysis-java-psi.api Public API updates reflecting signature changes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants