mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-15 20:26:04 +07:00
Support wildcard element in descriptor documentation providers
They are useful to provide documentation for attributes or children of elements with unknown names (for example, id of an extension registration in plugin.xml) GitOrigin-RevId: 439ab24c45b6429d00c467b5ae01b7309a84ed8b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7723435cc8
commit
3836219950
@@ -31,7 +31,7 @@
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the element."
|
||||
"description": "Name of the element. For elements with unknown names, it supports wildcard: *. The purpose of wildcard elements is to provide documentation for known sub-children or attributes."
|
||||
},
|
||||
"sdkDocsFixedPath": {
|
||||
"type": "array",
|
||||
|
||||
@@ -43,7 +43,7 @@ internal abstract class AbstractXmlDescriptorDocumentationTargetProvider : PsiDo
|
||||
val content = DocumentationContentProvider.getInstance().getContent(docYamlCoordinates) ?: return null
|
||||
return when (xmlElement) {
|
||||
is XmlTag -> {
|
||||
val docElement = content.findElement(elementPath) ?: return null
|
||||
val docElement = content.findElement(elementPath)?.takeIf { !it.isWildcard() } ?: return null
|
||||
XmlDescriptorElementDocumentationTarget(element.project, content, docElement)
|
||||
}
|
||||
is XmlAttribute -> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 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 org.jetbrains.idea.devkit.documentation
|
||||
|
||||
internal data class DocumentationContent(
|
||||
@@ -14,7 +14,7 @@ internal data class DocumentationContent(
|
||||
if (path.isEmpty()) return null
|
||||
val name = path.first()
|
||||
val remainingPath = path.drop(1)
|
||||
val currentElement = currentElements.find { it.element?.name == name }?.element ?: return null
|
||||
val currentElement = currentElements.find { it.element?.name == name || it.element?.isWildcard() == true }?.element ?: return null
|
||||
return if (remainingPath.isEmpty()) currentElement else findElementRecursively(currentElement.children, remainingPath)
|
||||
}
|
||||
|
||||
@@ -51,6 +51,11 @@ internal data class Element(
|
||||
var examples: List<String> = emptyList(),
|
||||
var path: List<String> = emptyList(),
|
||||
) {
|
||||
|
||||
fun isWildcard(): Boolean {
|
||||
return name == "*"
|
||||
}
|
||||
|
||||
fun copy(): Element {
|
||||
return this.copy(attributes = this.attributes.map { it.copy() })
|
||||
}
|
||||
|
||||
@@ -168,23 +168,28 @@ internal class DocumentationRenderer(private val project: Project) {
|
||||
if (i > 0) {
|
||||
append(" / ")
|
||||
}
|
||||
append(elementLink(linkElements[i], linkElements.take(i + 1)))
|
||||
append(elementLinkOrWildcard(linkElements[i], linkElements.take(i + 1)))
|
||||
}
|
||||
if (linkElements.isNotEmpty()) {
|
||||
append(" / ")
|
||||
}
|
||||
val lastElementName = elementPath.last()
|
||||
if (linkForLast) {
|
||||
append(elementLink(lastElementName, elementPath))
|
||||
append(elementLinkOrWildcard(lastElementName, elementPath))
|
||||
}
|
||||
else {
|
||||
append("**`<$lastElementName>`**")
|
||||
}
|
||||
}
|
||||
|
||||
private fun elementLink(text: String, path: List<String>): String {
|
||||
val linkPath = path.toPathString()
|
||||
return "[`<$text>`]($ELEMENT_DOC_LINK_PREFIX$linkPath)"
|
||||
private fun elementLinkOrWildcard(text: String, path: List<String>): String {
|
||||
if (text != "*") {
|
||||
val linkPath = path.toPathString()
|
||||
return "[`<$text>`]($ELEMENT_DOC_LINK_PREFIX$linkPath)"
|
||||
}
|
||||
else {
|
||||
return "`*`"
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendDeprecation(deprecatedSince: String?, deprecationNote: String?) {
|
||||
@@ -285,7 +290,7 @@ internal class DocumentationRenderer(private val project: Project) {
|
||||
appendParagraphSeparator()
|
||||
} else {
|
||||
for (child in element.children) {
|
||||
val childElement = child.element ?: continue
|
||||
val childElement = child.element?.takeIf { !it.isWildcard() } ?: continue
|
||||
val linkText = childElement.name
|
||||
val linkPath = childElement.path.toPathString()
|
||||
appendLine("- [`<$linkText>`]($ELEMENT_DOC_LINK_PREFIX$linkPath)${getRequirementSimpleText(child.element?.requirement)}")
|
||||
|
||||
@@ -201,3 +201,17 @@ elements:
|
||||
name: child1
|
||||
- element:
|
||||
name: child2
|
||||
- element:
|
||||
name: "*"
|
||||
attributes:
|
||||
- attribute:
|
||||
name: attributeUnderWildcard
|
||||
description: Description of `attributeUnderWildcard`.
|
||||
children:
|
||||
- element:
|
||||
name: childUnderWildcard
|
||||
description: Description of `childUnderWildcard`.
|
||||
attributes:
|
||||
- attribute:
|
||||
name: attributeOfElementUnderWildcard
|
||||
description: Description of `attributeOfElementUnderWildcard`.
|
||||
|
||||
@@ -270,6 +270,50 @@ class XmlDescriptorDocumentationProviderTest : CodeInsightFixtureTestCase<Module
|
||||
)
|
||||
}
|
||||
|
||||
fun `test attribute of a wildcard element`() {
|
||||
doTestDocContains(
|
||||
"""
|
||||
<root>
|
||||
<anyNameElement attribute<caret>UnderWildcard="any"/>
|
||||
</root>
|
||||
""".trimIndent(),
|
||||
"<p><a href=\"psi_element://#element:root\"><code><root></code></a> / <code>*</code> / <b><code>@attributeUnderWildcard</code></b><hr/>\n" +
|
||||
"Description of <code>attributeUnderWildcard</code>."
|
||||
)
|
||||
}
|
||||
|
||||
fun `test element under wildcard element`() {
|
||||
doTestDocContains(
|
||||
"""
|
||||
<root>
|
||||
<anyNameElement>
|
||||
<childUnder<caret>Wildcard/>
|
||||
</anyNameElement>
|
||||
</root>
|
||||
""".trimIndent(),
|
||||
"<p><a href=\"psi_element://#element:root\"><code><root></code></a> / <code>*</code> / <b><code><childUnderWildcard></code></b><hr/>\n" +
|
||||
"Description of <code>childUnderWildcard</code>." +
|
||||
"<h5>Attributes</h5>" +
|
||||
"<ul>" +
|
||||
"<li><a href=\"psi_element://#attribute:root__*__childUnderWildcard__attributeOfElementUnderWildcard\"><code>attributeOfElementUnderWildcard</code></a></li>" +
|
||||
"</ul>"
|
||||
)
|
||||
}
|
||||
|
||||
fun `test attribute of element under wildcard element`() {
|
||||
doTestDocContains(
|
||||
"""
|
||||
<root>
|
||||
<anyNameElement>
|
||||
<childUnderWildcard attribute<caret>OfElementUnderWildcard="any"/>
|
||||
</anyNameElement>
|
||||
</root>
|
||||
""".trimIndent(),
|
||||
"<p><a href=\"psi_element://#element:root\"><code><root></code></a> / <code>*</code> / <a href=\"psi_element://#element:root__*__childUnderWildcard\"><code><childUnderWildcard></code></a> / <b><code>@attributeOfElementUnderWildcard</code></b><hr/>\n" +
|
||||
"Description of <code>attributeOfElementUnderWildcard</code>."
|
||||
)
|
||||
}
|
||||
|
||||
private fun doTestDocContains(@Language("XML") fileText: String, @Language("HTML") expectedDoc: String) {
|
||||
myFixture.configureByText(TEST_XML_FILE_NAME, fileText)
|
||||
val targets = IdeDocumentationTargetProvider.getInstance(project)
|
||||
|
||||
Reference in New Issue
Block a user