vim-patch:85f054a: runtime(java): Recognise the CommonMark form (///) of Javadoc comments

Complement "g:java_ignore_javadoc" with "g:java_ignore_html"
and "g:java_ignore_markdown" to allow selectively disabling
the recognition of HTML and CommonMark respectively.

(Note that this is not a preview feature.)

======================== LIMITATION ========================

According to the syntactical details of JEP 467:

> Any leading whitespace and the three initial / characters
> are removed from each line.
>
> The lines are shifted left, by removing leading whitespace
> characters, until the non-blank line with the least
> leading whitespace has no remaining leading whitespace.
>
> Additional leading whitespace and any trailing whitespace
> in each line is preserved, because it may be significant.

the following example:
------------------------------------------------------------
///    A summary sentence.
///     A list:
///      - Item A.
///     - Item B.
///
///     Some code span, starting here `
///      1 + 2 ` and ending at the previous \`.
------------------------------------------------------------

should be interpreted as if it were written thus:
------------------------------------------------------------
///A summary sentence.
/// A list:
///  - Item A.
/// - Item B.
///
/// Some code span, starting here `
///  1 + 2 ` and ending at the previous \`.
------------------------------------------------------------

Since automatic line rewriting will not be pursued, parts of
such comments having significant whitespace may be ‘wrongly’
highlighted.  For convenience, a &fex function is defined to
‘correct’ it: g:javaformat#RemoveCommonMarkdownWhitespace()
(:help ft-java-plugin).

References:
https://openjdk.org/jeps/467
https://spec.commonmark.org/0.31.2

closes: vim/vim#15740

85f054aa3f

Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
Co-authored-by: Tim Pope <code@tpope.net>
This commit is contained in:
Christian Clason
2024-10-01 07:00:12 +02:00
parent ea9d61b80d
commit 2f2f434613
5 changed files with 277 additions and 31 deletions

View File

@@ -3,7 +3,7 @@
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
" Former Maintainer: Claudio Fleiner <claudio@fleiner.com>
" Repository: https://github.com/zzzyxwvut/java-vim.git
" Last Change: 2024 Sep 19
" Last Change: 2024 Sep 28
" Please check :help java.vim for comments on some of the options available.
@@ -156,6 +156,10 @@ else
let [s:ff.PeekTo, s:ff.PeekFrom, s:ff.GroupArgs] = repeat([s:ff.RightConstant], 3)
endif
let s:with_html = !exists("g:java_ignore_html")
let s:with_markdown = !exists("g:java_ignore_markdown")
lockvar s:with_html s:with_markdown
" Java module declarations (JLS-17, §7.7).
"
" Note that a "module-info" file will be recognised with an arbitrary
@@ -172,7 +176,7 @@ if fnamemodify(bufname("%"), ":t") =~ '^module-info\>\%(\.class\>\)\@!'
hi def link javaModuleStmt Statement
hi def link javaModuleExternal Include
if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
if !exists("g:java_ignore_javadoc") && (s:with_html || s:with_markdown) && g:main_syntax != 'jsp'
syn match javaDocProvidesTag contained "@provides\_s\+\S\+" contains=javaDocParam
syn match javaDocUsesTag contained "@uses\_s\+\S\+" contains=javaDocParam
hi def link javaDocProvidesTag Special
@@ -335,18 +339,52 @@ syn match javaCommentMarkupTagAttr contained "\<region\>" nextgroup=javaCommen
exec 'syn region javaCommentMarkupTagAttr contained transparent matchgroup=javaHtmlArg start=/\<\%(re\%(gex\|gion\|placement\)\|substring\|t\%(arget\|ype\)\)\%(\s*=\)\@=/ matchgroup=javaHtmlString end=/\%(=\s*\)\@' . s:ff.Peek('80', '') . '<=\%("[^"]\+"\|' . "\x27[^\x27]\\+\x27" . '\|\%([.-]\|\k\)\+\)/ nextgroup=javaCommentMarkupTagAttr,javaSpaceError skipwhite oneline'
syn match javaCommentError contained "/\*"me=e-1 display
if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
" The overridable "html*" default links must be defined _before_ the
" inclusion of the same default links from "html.vim".
hi def link htmlComment Special
hi def link htmlCommentPart Special
hi def link htmlArg Type
hi def link htmlString String
if !exists("g:java_ignore_javadoc") && (s:with_html || s:with_markdown) && g:main_syntax != 'jsp'
" The overridable "html*" and "markdown*" default links must be
" defined _before_ the inclusion of the same default links from
" "html.vim" and "markdown.vim".
if s:with_html || s:with_markdown
hi def link htmlComment Special
hi def link htmlCommentPart Special
hi def link htmlArg Type
hi def link htmlString String
endif
if s:with_markdown
hi def link markdownCode Special
hi def link markdownCodeBlock Special
hi def link markdownCodeDelimiter Special
hi def link markdownLinkDelimiter Comment
endif
syntax case ignore
" Note that javaDocSeeTag is valid in HTML and Markdown.
let s:ff.WithMarkdown = s:ff.RightConstant
" Include HTML syntax coloring for Javadoc comments.
syntax include @javaHtml syntax/html.vim
unlet b:current_syntax
if s:with_html
syntax include @javaHtml syntax/html.vim
unlet b:current_syntax
endif
" Include Markdown syntax coloring (v7.2.437) for Javadoc comments.
if s:with_markdown
try
syntax include @javaMarkdown syntax/markdown.vim
unlet b:current_syntax
let s:ff.WithMarkdown = s:ff.LeftConstant
catch /\<E48[45]:/
call s:ReportOnce(v:exception)
unlockvar s:with_markdown
let s:with_markdown = 0
lockvar s:with_markdown
hi clear markdownCode
hi clear markdownCodeBlock
hi clear markdownCodeDelimiter
hi clear markdownLinkDelimiter
endtry
endif
" HTML enables spell checking for all text that is not in a syntax
" item (:syntax spell toplevel); instead, limit spell checking to
@@ -357,10 +395,71 @@ if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
call s:ReportOnce(v:exception)
endtry
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,@javaDocTags,javaTodo,javaCommentError,javaSpaceError,@Spell fold
exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags'
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@summary\>\)\@=" matchgroup=javaCommentTitle end="}" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
if s:with_markdown
syn region javaMarkdownComment start="///" skip="^\s*///.*$" end="^" keepend contains=javaMarkdownCommentTitle,javaMarkdownShortcutLink,@javaMarkdown,@javaDocTags,javaTodo,@Spell nextgroup=javaMarkdownCommentTitle fold
syn match javaMarkdownCommentMask contained "^\s*///"
exec 'syn region javaMarkdownCommentTitle contained matchgroup=javaMarkdownComment start="\%(///.*\r\=\n\s*\)\@' . s:ff.Peek('80', '') . '<!///" matchgroup=javaMarkdownCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\n\%(\s*///\s*$\)\@=" end="\%(^\s*///\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 contains=javaMarkdownShortcutLink,@javaMarkdown,javaMarkdownCommentMask,javaTodo,@Spell,@javaDocTags'
exec 'syn region javaMarkdownCommentTitle contained matchgroup=javaMarkdownComment start="\%(///.*\r\=\n\s*\)\@' . s:ff.Peek('80', '') . '<!///\s*\%({@return\>\)\@=" matchgroup=javaMarkdownCommentTitle end="}\%(\s*\.*\)*" contains=javaMarkdownShortcutLink,@javaMarkdown,javaMarkdownCommentMask,javaTodo,@Spell,@javaDocTags,javaTitleSkipBlock'
exec 'syn region javaMarkdownCommentTitle contained matchgroup=javaMarkdownComment start="\%(///.*\r\=\n\s*\)\@' . s:ff.Peek('80', '') . '<!///\s*\%({@summary\>\)\@=" matchgroup=javaMarkdownCommentTitle end="}" contains=javaMarkdownShortcutLink,@javaMarkdown,javaMarkdownCommentMask,javaTodo,@Spell,@javaDocTags,javaTitleSkipBlock'
syn clear markdownId markdownLineStart markdownH1 markdownH2 markdownHeadingRule markdownRule markdownCode markdownCodeBlock markdownIdDeclaration
" REDEFINE THE MARKDOWN ITEMS ANCHORED WITH "^", OBSERVING THE
" DEFINITION ORDER.
syn match markdownLineStart contained "^\s*///\s*[<@]\@!" contains=@markdownBlock,javaMarkdownCommentTitle,javaMarkdownCommentMask nextgroup=@markdownBlock,htmlSpecialChar
" See https://spec.commonmark.org/0.31.2/#setext-headings.
syn match markdownH1 contained "^\s*/// \{,3}.\+\r\=\n\s*/// \{,3}=\+\s*$" contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink,javaMarkdownCommentMask
syn match markdownH2 contained "^\s*/// \{,3}.\+\r\=\n\s*/// \{,3}-\+\s*$" contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink,javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#atx-headings.
syn region markdownH1 contained matchgroup=markdownH1Delimiter start=" \{,3}#\s" end="#*\s*$" keepend contains=@markdownInline,markdownAutomaticLink oneline
syn region markdownH2 contained matchgroup=markdownH2Delimiter start=" \{,3}##\s" end="#*\s*$" keepend contains=@markdownInline,markdownAutomaticLink oneline
syn match markdownHeadingRule contained "^\s*/// \{,3}[=-]\+\s*$" contains=javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#thematic-breaks.
syn match markdownRule contained "^\s*/// \{,3}\*\s*\*\%(\s*\*\)\+\s*$" contains=javaMarkdownCommentMask
syn match markdownRule contained "^\s*/// \{,3}_\s*_\%(\s*_\)\+\s*$" contains=javaMarkdownCommentMask
syn match markdownRule contained "^\s*/// \{,3}-\s*-\%(\s*-\)\+\s*$" contains=javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#indented-code-blocks.
syn region markdownCodeBlock contained start="^\s*///\%( \{4,}\|\t\)" end="^\ze\s*///\%(\s*$\| \{,3}\S\)" keepend contains=javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#code-spans.
syn region markdownCode contained matchgroup=markdownCodeDelimiter start="\z(`\+\) \=" end=" \=\z1" keepend contains=markdownLineStart,javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#fenced-code-blocks.
syn region markdownCodeBlock contained start="^\s*/// \{,3}\z(```\+\)\%(.\{-}[^`]`\)\@!" end="^\s*/// \{,3}\z1`*" keepend contains=javaMarkdownCommentMask
syn region markdownCodeBlock contained start="^\s*/// \{,3}\z(\~\~\~\+\)" end="^\s*/// \{,3}\z1\~*" keepend contains=javaMarkdownCommentMask
" See https://spec.commonmark.org/0.31.2/#link-reference-definitions.
syn region markdownIdDeclaration contained matchgroup=markdownLinkDelimiter start="^\s*/// \{,3\}!\=\[" end="\]:" keepend contains=javaMarkdownCommentMask nextgroup=markdownUrl oneline skipwhite
" See https://spec.commonmark.org/0.31.2/#link-label.
syn region markdownId contained matchgroup=markdownIdDelimiter start="\[\%([\t ]\]\)\@!" end="\]" contains=javaMarkdownSkipBrackets,javaMarkdownCommentMask
" Note that escaped brackets can be unbalanced.
syn match javaMarkdownSkipBrackets contained transparent "\\\[\|\\\]"
" See https://spec.commonmark.org/0.31.2/#shortcut-reference-link.
syn region javaMarkdownShortcutLink contained matchgroup=markdownLinkTextDelimiter start="!\=\[^\@!\%(\_[^][]*\%(\[\_[^][]*\]\_[^][]*\)*]\%([[(]\)\@!\)\@=" end="\]\%([[(]\)\@!" contains=@markdownInline,markdownLineStart,javaMarkdownSkipBrackets,javaMarkdownCommentMask nextgroup=markdownLink,markdownId skipwhite
for s:name in ['markdownFootnoteDefinition', 'markdownFootnote']
if hlexists(s:name)
exec 'syn clear ' . s:name
endif
endfor
unlet s:name
" COMBAK: Footnotes are recognised by "markdown.vim", but are not
" in CommonMark. See https://pandoc.org/MANUAL.html#footnotes.
""""syn match markdownFootnoteDefinition contained "^\s*///\s*\[^[^\]]\+\]:" contains=javaMarkdownCommentMask
hi def link javaMarkdownComment Comment
hi def link javaMarkdownCommentMask javaMarkdownComment
hi def link javaMarkdownCommentTitle SpecialComment
hi def link javaMarkdownShortcutLink htmlLink
endif
if s:with_html
syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,@javaDocTags,javaTodo,javaCommentError,javaSpaceError,@Spell fold
exec 'syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*" matchgroup=javaCommentTitle end="\.$" end="\.[ \t\r]\@=" end="\%(^\s*\**\s*\)\@' . s:ff.Peek('80', '') . '<=@"me=s-2,he=s-1 end="\*/"me=s-1,he=s-1 contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags'
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@return\>\)\@=" matchgroup=javaCommentTitle end="}\%(\s*\.*\)*" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
syn region javaCommentTitle contained matchgroup=javaDocComment start="/\*\*\s*\r\=\n\=\s*\**\s*\%({@summary\>\)\@=" matchgroup=javaCommentTitle end="}" contains=@javaHtml,javaCommentStar,javaTodo,javaCommentError,javaSpaceError,@Spell,@javaDocTags,javaTitleSkipBlock
hi def link javaDocComment Comment
hi def link javaCommentTitle SpecialComment
endif
" The members of javaDocTags are sub-grouped according to the Java
" version of their introduction, and sub-group members in turn are
" arranged in alphabetical order, so that future newer members can
@@ -403,13 +502,29 @@ if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
syn match javaDocSerialFieldTag contained "@serialField\>"
syn match javaDocVersionTag contained "@version\>"
syn match javaDocSeeTag contained "@see\>" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTagStar skipwhite skipempty
syn match javaDocSeeTagStar contained "^\s*\*\+\%(\s*{\=@\|/\|$\)\@!" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3 skipwhite skipempty
syn match javaDocSeeTag contained "@see\>\s*" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTag4,javaDocSeeTagStar,javaDocSeeTagSlash skipwhite skipempty
if s:with_html
syn match javaDocSeeTagStar contained "^\s*\*\+\%(\s*{\=@\|/\|$\)\@!" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTag4 skipwhite skipempty
hi def link javaDocSeeTagStar javaDocComment
endif
if s:with_markdown
syn match javaDocSeeTagSlash contained "^\s*///\%(\s*{\=@\|$\)\@!" nextgroup=javaDocSeeTag1,javaDocSeeTag2,javaDocSeeTag3,javaDocSeeTag4 skipwhite skipempty
hi def link javaDocSeeTagSlash javaMarkdownComment
endif
syn match javaDocSeeTag1 contained @"\_[^"]\+"@
syn match javaDocSeeTag2 contained @<a\s\+\_.\{-}</a>@ contains=@javaHtml extend
syn match javaDocSeeTag3 contained @["< \t]\@!\%(\k\|[/.]\)*\%(##\=\k\+\%((\_[^)]*)\)\=\)\=@ nextgroup=javaDocSeeTag3Label skipwhite skipempty
exec 'syn match javaDocSeeTag3 contained @[' . s:ff.WithMarkdown('[', '') . '"< \t]\@!\%(\k\|[/.]\)*\%(##\=\k\+\%((\_[^)]*)\)\=\)\=@ nextgroup=javaDocSeeTag3Label skipwhite skipempty'
syn match javaDocSeeTag3Label contained @\k\%(\k\+\s*\)*$@
" COMBAK: No support for type javaDocSeeTag2 in Markdown.
""if s:with_markdown
"" syn match javaDocSeeTag4 contained @\[.\+\]\s\=\%(\[.\+\]\|(.\+)\)@ contains=@javaMarkdown extend
"" hi def link javaDocSeeTag4 Special
""endif
syn region javaCodeSkipBlock contained transparent start="{\%(@code\>\)\@!" end="}" contains=javaCodeSkipBlock,javaDocCodeTag
syn region javaDocCodeTag contained start="{@code\>" end="}" contains=javaDocCodeTag,javaCodeSkipBlock
@@ -418,9 +533,6 @@ if !exists("g:java_ignore_javadoc") && g:main_syntax != 'jsp'
syn region javaDocSnippetTag contained start="{@snippet\>" end="}" contains=javaDocSnippetTag,javaSnippetSkipBlock,javaDocSnippetTagAttr,javaCommentMarkupTag
syntax case match
hi def link javaDocComment Comment
hi def link javaDocSeeTagStar javaDocComment
hi def link javaCommentTitle SpecialComment
hi def link javaDocParam Function
hi def link javaDocAuthorTag Special
@@ -729,7 +841,7 @@ endif
let b:spell_options = "contained"
let &cpo = s:cpo_save
unlet s:ff s:cpo_save
unlet s:cpo_save s:ff s:with_html s:with_markdown
" See ":help vim9-mix".
if !has("vim9script")
@@ -757,4 +869,4 @@ if exists("g:java_foldtext_show_first_or_second_line")
setlocal foldtext=s:JavaSyntaxFoldTextExpr()
delfunction! g:JavaSyntaxFoldTextExpr
endif
" vim: sw=2 ts=8 noet sta
" vim: fdm=syntax sw=2 ts=8 noet sta