173: Revert changes for IDEA < 181
This commit is contained in:
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.google.common.html.HtmlEscapers
|
||||
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
|
||||
import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory
|
||||
import com.intellij.lang.documentation.AbstractDocumentationProvider
|
||||
import com.intellij.lang.java.JavaDocumentationProvider
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper
|
||||
import org.jetbrains.kotlin.idea.kdoc.KDocRenderer
|
||||
import org.jetbrains.kotlin.idea.kdoc.findKDoc
|
||||
import org.jetbrains.kotlin.idea.kdoc.isBoringBuiltinClass
|
||||
import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.deprecatedByAnnotationReplaceWithExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.constant
|
||||
|
||||
class HtmlClassifierNamePolicy(val base: ClassifierNamePolicy) : ClassifierNamePolicy {
|
||||
override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String {
|
||||
if (DescriptorUtils.isAnonymousObject(classifier)) {
|
||||
|
||||
val supertypes = classifier.typeConstructor.supertypes
|
||||
return buildString {
|
||||
append("<anonymous object")
|
||||
if (supertypes.isNotEmpty()) {
|
||||
append(" : ")
|
||||
supertypes.joinTo(this) {
|
||||
val ref = it.constructor.declarationDescriptor
|
||||
if (ref != null)
|
||||
renderClassifier(ref, renderer)
|
||||
else
|
||||
"<ERROR CLASS>"
|
||||
}
|
||||
}
|
||||
append(">")
|
||||
}
|
||||
}
|
||||
|
||||
val name = base.renderClassifier(classifier, renderer)
|
||||
if (classifier.isBoringBuiltinClass())
|
||||
return name
|
||||
return buildString {
|
||||
val ref = classifier.fqNameUnsafe.toString()
|
||||
DocumentationManagerUtil.createHyperlink(this, ref, name, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() {
|
||||
|
||||
override fun getQuickNavigateInfo(element: PsiElement?, originalElement: PsiElement?): String? {
|
||||
return if (element == null) null else getText(element, originalElement, true)
|
||||
}
|
||||
|
||||
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
|
||||
return getText(element, originalElement, false)
|
||||
}
|
||||
|
||||
override fun getDocumentationElementForLink(psiManager: PsiManager, link: String, context: PsiElement?): PsiElement? {
|
||||
val navElement = context?.navigationElement as? KtElement ?: return null
|
||||
val bindingContext = navElement.analyze(BodyResolveMode.PARTIAL)
|
||||
val contextDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, navElement] ?: return null
|
||||
val descriptors = resolveKDocLink(bindingContext, navElement.getResolutionFacade(),
|
||||
contextDescriptor, null, link.split('.'))
|
||||
val target = descriptors.firstOrNull() ?: return null
|
||||
return DescriptorToSourceUtilsIde.getAnyDeclaration(psiManager.project, target)
|
||||
}
|
||||
|
||||
override fun getDocumentationElementForLookupItem(psiManager: PsiManager, `object`: Any?, element: PsiElement?): PsiElement? {
|
||||
if (`object` is DeclarationLookupObject) {
|
||||
`object`.psiElement?.let { return it }
|
||||
`object`.descriptor?.let { descriptor ->
|
||||
return DescriptorToSourceUtilsIde.getAnyDeclaration(psiManager.project, descriptor)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinQuickDocumentationProvider::class.java)
|
||||
|
||||
private val DESCRIPTOR_RENDERER = DescriptorRenderer.HTML.withOptions {
|
||||
classifierNamePolicy = HtmlClassifierNamePolicy(ClassifierNamePolicy.SHORT)
|
||||
renderCompanionObjectName = true
|
||||
}
|
||||
|
||||
private fun renderEnumSpecialFunction(element: KtClass, functionDescriptor: FunctionDescriptor, quickNavigation: Boolean): String {
|
||||
var renderedDecl = DESCRIPTOR_RENDERER.render(functionDescriptor)
|
||||
|
||||
if (quickNavigation) return renderedDecl
|
||||
|
||||
val declarationDescriptor = element.resolveToDescriptorIfAny()
|
||||
val enumDescriptor = declarationDescriptor?.getSuperClassNotAny() ?: return renderedDecl
|
||||
|
||||
val enumDeclaration =
|
||||
DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, enumDescriptor) as? KtDeclaration ?: return renderedDecl
|
||||
|
||||
val enumSource = SourceNavigationHelper.getNavigationElement(enumDeclaration)
|
||||
val functionName = functionDescriptor.fqNameSafe.shortName().asString()
|
||||
val kdoc = enumSource.findDescendantOfType<KDoc> {
|
||||
it.getChildrenOfType<KDocSection>().any { it.findTagByName(functionName) != null }
|
||||
}
|
||||
|
||||
if (kdoc != null) {
|
||||
val renderedComment = KDocRenderer.renderKDoc(kdoc.getDefaultSection())
|
||||
if (renderedComment.startsWith("<p>")) {
|
||||
renderedDecl += renderedComment
|
||||
}
|
||||
else {
|
||||
renderedDecl = "$renderedDecl<br/>$renderedComment"
|
||||
}
|
||||
}
|
||||
|
||||
return renderedDecl
|
||||
}
|
||||
|
||||
private fun renderEnum(element: KtClass, originalElement: PsiElement?, quickNavigation: Boolean): String? {
|
||||
val referenceExpression = originalElement?.getNonStrictParentOfType<KtReferenceExpression>()
|
||||
if (referenceExpression != null) {
|
||||
// When caret on special enum function (e.g SomeEnum.values<caret>())
|
||||
// element is not an KtReferenceExpression, but KtClass of enum
|
||||
// so reference extracted from originalElement
|
||||
val context = referenceExpression.analyze(BodyResolveMode.PARTIAL)
|
||||
(context[BindingContext.REFERENCE_TARGET, referenceExpression] ?:
|
||||
context[BindingContext.REFERENCE_TARGET, referenceExpression.getChildOfType<KtReferenceExpression>()])?.let {
|
||||
if (it is FunctionDescriptor) // To protect from Some<caret>Enum.values()
|
||||
return renderEnumSpecialFunction(element, it, quickNavigation)
|
||||
}
|
||||
}
|
||||
return renderKotlinDeclaration(element, quickNavigation)
|
||||
}
|
||||
|
||||
private fun getText(element: PsiElement, originalElement: PsiElement?, quickNavigation: Boolean): String? {
|
||||
if (element is PsiWhiteSpace) {
|
||||
val itElement = findElementWithText(originalElement, "it")
|
||||
val itReference = itElement?.getParentOfType<KtNameReferenceExpression>(false)
|
||||
if (itReference != null) {
|
||||
return getText(itReference, originalElement, quickNavigation)
|
||||
}
|
||||
}
|
||||
|
||||
if (element is KtTypeReference) {
|
||||
val declaration = element.parent
|
||||
if (declaration is KtCallableDeclaration && declaration.receiverTypeReference == element) {
|
||||
val thisElement = findElementWithText(originalElement, "this")
|
||||
if (thisElement != null) {
|
||||
return getText(declaration, originalElement, quickNavigation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (element is KtClass && element.isEnum()) {
|
||||
// When caret on special enum function (e.g SomeEnum.values<caret>())
|
||||
// element is not an KtReferenceExpression, but KtClass of enum
|
||||
return renderEnum(element, originalElement, quickNavigation)
|
||||
}
|
||||
else if (element is KtEnumEntry && !quickNavigation) {
|
||||
val ordinal = element.containingClassOrObject?.getBody()?.run { getChildrenOfType<KtEnumEntry>().indexOf(element) }
|
||||
|
||||
return buildString {
|
||||
append(renderKotlinDeclaration(element, quickNavigation))
|
||||
ordinal?.let {
|
||||
wrapTag("b") {
|
||||
append("Enum constant ordinal: $ordinal")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element is KtDeclaration) {
|
||||
return renderKotlinDeclaration(element, quickNavigation)
|
||||
}
|
||||
else if (element is KtNameReferenceExpression && element.getReferencedName() == "it") {
|
||||
return renderKotlinImplicitLambdaParameter(element, quickNavigation)
|
||||
}
|
||||
else if (element is KtLightDeclaration<*, *>) {
|
||||
val origin = element.kotlinOrigin ?: return null
|
||||
return renderKotlinDeclaration(origin, quickNavigation)
|
||||
}
|
||||
|
||||
if (quickNavigation) {
|
||||
val referenceExpression = originalElement?.getNonStrictParentOfType<KtReferenceExpression>()
|
||||
if (referenceExpression != null) {
|
||||
val context = referenceExpression.analyze(BodyResolveMode.PARTIAL)
|
||||
val declarationDescriptor = context[BindingContext.REFERENCE_TARGET, referenceExpression]
|
||||
if (declarationDescriptor != null) {
|
||||
return mixKotlinToJava(declarationDescriptor, element, originalElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This element was resolved to non-kotlin element, it will be rendered with own provider
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun renderKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): String {
|
||||
val context = declaration.analyze(BodyResolveMode.PARTIAL)
|
||||
val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||
|
||||
if (declarationDescriptor == null) {
|
||||
LOG.info("Failed to find descriptor for declaration " + declaration.getElementTextWithContext())
|
||||
return "No documentation available"
|
||||
}
|
||||
|
||||
return renderKotlin(context, declarationDescriptor, quickNavigation, declaration)
|
||||
}
|
||||
|
||||
private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? {
|
||||
val context = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null
|
||||
return renderKotlin(context, target, quickNavigation, element)
|
||||
}
|
||||
|
||||
private fun renderKotlin(
|
||||
context: BindingContext,
|
||||
declarationDescriptor: DeclarationDescriptor,
|
||||
quickNavigation: Boolean,
|
||||
ktElement: KtElement
|
||||
): String {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
var declarationDescriptor = declarationDescriptor
|
||||
if (declarationDescriptor is ValueParameterDescriptor) {
|
||||
val property = context[BindingContext.VALUE_PARAMETER_AS_PROPERTY, declarationDescriptor]
|
||||
if (property != null) {
|
||||
declarationDescriptor = property
|
||||
}
|
||||
}
|
||||
|
||||
var renderedDecl = DESCRIPTOR_RENDERER.withOptions {
|
||||
withDefinedIn = !DescriptorUtils.isLocal(declarationDescriptor)
|
||||
}.render(declarationDescriptor)
|
||||
|
||||
if (!quickNavigation) {
|
||||
renderedDecl = "<pre>$renderedDecl</pre>"
|
||||
}
|
||||
|
||||
val deprecationProvider = ktElement.getResolutionFacade().frontendService<DeprecationResolver>()
|
||||
renderedDecl += renderDeprecationInfo(declarationDescriptor, deprecationProvider)
|
||||
|
||||
if (!quickNavigation) {
|
||||
val comment = declarationDescriptor.findKDoc { DescriptorToSourceUtilsIde.getAnyDeclaration(ktElement.project, it) }
|
||||
if (comment != null) {
|
||||
val renderedComment = KDocRenderer.renderKDoc(comment)
|
||||
if (renderedComment.startsWith("<p>")) {
|
||||
renderedDecl += renderedComment
|
||||
}
|
||||
else {
|
||||
renderedDecl = "$renderedDecl<br/>$renderedComment"
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (declarationDescriptor is CallableDescriptor) { // If we couldn't find KDoc, try to find javadoc in one of super's
|
||||
val psi = declarationDescriptor.findPsi() as? KtFunction
|
||||
if (psi != null) {
|
||||
val lightElement = LightClassUtil.getLightClassMethod(psi) // Light method for super's scan in javadoc info gen
|
||||
val javaDocInfoGenerator = JavaDocInfoGeneratorFactory.create(psi.project, lightElement)
|
||||
val builder = StringBuilder()
|
||||
if (javaDocInfoGenerator.generateDocInfoCore(builder, false))
|
||||
renderedDecl += builder.toString().substringAfter("</PRE>") // Cut off light method signature
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return renderedDecl
|
||||
}
|
||||
|
||||
private fun renderDeprecationInfo(
|
||||
declarationDescriptor: DeclarationDescriptor,
|
||||
deprecationResolver: DeprecationResolver
|
||||
): String {
|
||||
val deprecation = deprecationResolver.getDeprecations(declarationDescriptor).firstOrNull() ?: return ""
|
||||
|
||||
return buildString {
|
||||
wrapTag("DL") {
|
||||
deprecation.message?.let { message ->
|
||||
wrapTag("DT") { wrapTag("b") { append("Deprecated:") } }
|
||||
wrapTag("DD") {
|
||||
append(message.htmlEscape())
|
||||
}
|
||||
}
|
||||
deprecation.deprecatedByAnnotationReplaceWithExpression()?.let { replaceWith ->
|
||||
wrapTag("DT") { wrapTag("b") { append("Replace with:") } }
|
||||
wrapTag("DD") {
|
||||
wrapTag("code") { append(replaceWith.htmlEscape()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.htmlEscape(): String = HtmlEscapers.htmlEscaper().escape(this)
|
||||
|
||||
private inline fun StringBuilder.wrap(prefix: String, postfix: String, crossinline body: () -> Unit) {
|
||||
this.append(prefix)
|
||||
body()
|
||||
this.append(postfix)
|
||||
}
|
||||
|
||||
private inline fun StringBuilder.wrapTag(tag: String, crossinline body: () -> Unit) {
|
||||
wrap("<$tag>", "</$tag>", body)
|
||||
}
|
||||
|
||||
private fun mixKotlinToJava(declarationDescriptor: DeclarationDescriptor, element: PsiElement, originalElement: PsiElement?): String? {
|
||||
val originalInfo = JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement)
|
||||
if (originalInfo != null) {
|
||||
val renderedDecl = constant { DESCRIPTOR_RENDERER.withOptions { withDefinedIn = false } }.render(declarationDescriptor)
|
||||
return renderedDecl + "<br/>Java declaration:<br/>" + originalInfo
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findElementWithText(element: PsiElement?, text: String): PsiElement? {
|
||||
return when {
|
||||
element == null -> null
|
||||
element.text == text -> element
|
||||
element.prevLeaf()?.text == text -> element.prevLeaf()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.kdoc
|
||||
|
||||
import com.intellij.codeInsight.documentation.DocumentationManagerUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.intellij.markdown.IElementType
|
||||
import org.intellij.markdown.MarkdownElementTypes
|
||||
import org.intellij.markdown.MarkdownTokenTypes
|
||||
import org.intellij.markdown.ast.ASTNode
|
||||
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
||||
import org.intellij.markdown.parser.MarkdownParser
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.wrapTag
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithBody
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||
|
||||
object KDocRenderer {
|
||||
fun renderKDoc(docComment: KDocTag): String {
|
||||
val content = docComment.getContent()
|
||||
val result = StringBuilder()
|
||||
result.append(markdownToHtml(content, allowSingleParagraph = true))
|
||||
if (docComment is KDocSection) {
|
||||
result.append("\n")
|
||||
renderTag(docComment.findTagByName("receiver"), "Receiver", result)
|
||||
val paramTags = docComment.findTagsByName("param").filter { it.getSubjectName() != null }
|
||||
renderTagList(paramTags, "Parameters", result)
|
||||
|
||||
renderTag(docComment.findTagByName("return"), "Returns", result)
|
||||
|
||||
val throwsTags = (docComment.findTagsByName("exception").union(docComment.findTagsByName("throws")))
|
||||
.filter { it.getSubjectName() != null }
|
||||
renderTagList(throwsTags, "Throws", result)
|
||||
|
||||
renderTag(docComment.findTagByName("author"), "Author", result)
|
||||
renderTag(docComment.findTagByName("since"), "Since", result)
|
||||
|
||||
renderSeeAlso(docComment, result)
|
||||
|
||||
val sampleTags = docComment.findTagsByName("sample").filter { it.getSubjectLink() != null }
|
||||
renderSamplesList(sampleTags, result)
|
||||
}
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
private fun KDocLink.createHyperlink(to: StringBuilder) {
|
||||
DocumentationManagerUtil.createHyperlink(to, getLinkText(), getLinkText(), false)
|
||||
}
|
||||
|
||||
private fun KDocLink.getTargetElement(): PsiElement? {
|
||||
return this.getChildrenOfType<KDocName>().last().mainReference.resolve()
|
||||
}
|
||||
|
||||
private fun PsiElement.extractExampleText() = when (this) {
|
||||
is KtDeclarationWithBody -> {
|
||||
val bodyExpression = bodyExpression
|
||||
when (bodyExpression) {
|
||||
is KtBlockExpression -> bodyExpression.text.removeSurrounding("{", "}")
|
||||
else -> bodyExpression!!.text
|
||||
}
|
||||
}
|
||||
else -> text
|
||||
}
|
||||
|
||||
private fun trimCommonIndent(text: String): String {
|
||||
fun String.leadingIndent() = indexOfFirst { !it.isWhitespace() }
|
||||
|
||||
val lines = text.split('\n')
|
||||
val minIndent = lines.filter { it.trim().isNotEmpty() }.map(String::leadingIndent).min() ?: 0
|
||||
return lines.joinToString("\n") { it.drop(minIndent) }
|
||||
}
|
||||
|
||||
|
||||
private fun renderSamplesList(sampleTags: List<KDocTag>, to: StringBuilder) {
|
||||
if (sampleTags.isEmpty()) return
|
||||
to.apply {
|
||||
wrapTag("dl") {
|
||||
append("<dt><b>Samples:</b></dt>")
|
||||
sampleTags.forEach {
|
||||
wrapTag("dd") {
|
||||
it.getSubjectLink()?.let { subjectLink ->
|
||||
subjectLink.createHyperlink(to)
|
||||
val target = subjectLink.getTargetElement()
|
||||
wrapTag("pre") {
|
||||
wrapTag("code") {
|
||||
if (target == null)
|
||||
to.append("// Unresolved")
|
||||
else {
|
||||
to.append(trimCommonIndent(target.extractExampleText()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderSeeAlso(docComment: KDocSection, to: StringBuilder) {
|
||||
val seeTags = docComment.findTagsByName("see")
|
||||
if (seeTags.isEmpty()) return
|
||||
to.append("<DD><DL>")
|
||||
to.append("<DT><b>").append("See Also:").append("</b>")
|
||||
to.append("<DD>")
|
||||
seeTags.forEachIndexed { index, tag ->
|
||||
val subjectName = tag.getSubjectName()
|
||||
if (subjectName != null) {
|
||||
DocumentationManagerUtil.createHyperlink(to, subjectName, subjectName, false)
|
||||
}
|
||||
else {
|
||||
to.append(tag.getContent())
|
||||
}
|
||||
if (index < seeTags.size - 1) {
|
||||
to.append(", ")
|
||||
}
|
||||
}
|
||||
to.append("</DD></DL></DD>")
|
||||
}
|
||||
|
||||
private fun renderTagList(tags: List<KDocTag>, title: String, to: StringBuilder) {
|
||||
if (tags.isEmpty()) {
|
||||
return
|
||||
}
|
||||
to.append("<dl><dt><b>$title:</b></dt>")
|
||||
tags.forEach {
|
||||
to.append("<dd><code>${it.getSubjectName()}</code> - ${markdownToHtml(it.getContent().trimStart())}</dd>")
|
||||
}
|
||||
to.append("</dl>\n")
|
||||
}
|
||||
|
||||
private fun renderTag(tag: KDocTag?, title: String, to: StringBuilder) {
|
||||
if (tag != null) {
|
||||
to.append("<dl><dt><b>$title:</b></dt>")
|
||||
to.append("<dd>${markdownToHtml(tag.getContent())}</dd>")
|
||||
to.append("</dl>\n")
|
||||
}
|
||||
}
|
||||
|
||||
fun markdownToHtml(markdown: String, allowSingleParagraph: Boolean = false): String {
|
||||
val markdownTree = MarkdownParser(CommonMarkFlavourDescriptor()).buildMarkdownTreeFromString(markdown)
|
||||
val markdownNode = MarkdownNode(markdownTree, null, markdown)
|
||||
|
||||
// Avoid wrapping the entire converted contents in a <p> tag if it's just a single paragraph
|
||||
val maybeSingleParagraph = markdownNode.children.singleOrNull { it.type != MarkdownTokenTypes.EOL }
|
||||
return if (maybeSingleParagraph != null && !allowSingleParagraph) {
|
||||
maybeSingleParagraph.children.joinToString("") {
|
||||
if (it.text == "\n") " " else it.toHtml()
|
||||
}
|
||||
}
|
||||
else {
|
||||
markdownNode.toHtml()
|
||||
}
|
||||
}
|
||||
|
||||
class MarkdownNode(val node: ASTNode, val parent: MarkdownNode?, val markdown: String) {
|
||||
val children: List<MarkdownNode> = node.children.map { MarkdownNode(it, this, markdown) }
|
||||
val endOffset: Int get() = node.endOffset
|
||||
val startOffset: Int get() = node.startOffset
|
||||
val type: IElementType get() = node.type
|
||||
val text: String get() = markdown.substring(startOffset, endOffset)
|
||||
fun child(type: IElementType): MarkdownNode? = children.firstOrNull { it.type == type }
|
||||
}
|
||||
|
||||
private fun MarkdownNode.visit(action: (MarkdownNode, () -> Unit) -> Unit) {
|
||||
action(this) {
|
||||
for (child in children) {
|
||||
child.visit(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MarkdownNode.toHtml(): String {
|
||||
if (node.type == MarkdownTokenTypes.WHITE_SPACE) {
|
||||
return text // do not trim trailing whitespace
|
||||
}
|
||||
|
||||
val sb = StringBuilder()
|
||||
visit { node, processChildren ->
|
||||
fun wrapChildren(tag: String, newline: Boolean = false) {
|
||||
sb.append("<$tag>")
|
||||
processChildren()
|
||||
sb.append("</$tag>")
|
||||
if (newline) sb.appendln()
|
||||
}
|
||||
|
||||
val nodeType = node.type
|
||||
val nodeText = node.text
|
||||
when (nodeType) {
|
||||
MarkdownElementTypes.UNORDERED_LIST -> wrapChildren("ul", newline = true)
|
||||
MarkdownElementTypes.ORDERED_LIST -> wrapChildren("ol", newline = true)
|
||||
MarkdownElementTypes.LIST_ITEM -> wrapChildren("li")
|
||||
MarkdownElementTypes.EMPH -> wrapChildren("em")
|
||||
MarkdownElementTypes.STRONG -> wrapChildren("strong")
|
||||
MarkdownElementTypes.ATX_1 -> wrapChildren("h1")
|
||||
MarkdownElementTypes.ATX_2 -> wrapChildren("h2")
|
||||
MarkdownElementTypes.ATX_3 -> wrapChildren("h3")
|
||||
MarkdownElementTypes.ATX_4 -> wrapChildren("h4")
|
||||
MarkdownElementTypes.ATX_5 -> wrapChildren("h5")
|
||||
MarkdownElementTypes.ATX_6 -> wrapChildren("h6")
|
||||
MarkdownElementTypes.BLOCK_QUOTE -> wrapChildren("blockquote")
|
||||
MarkdownElementTypes.PARAGRAPH -> {
|
||||
sb.trimEnd()
|
||||
wrapChildren("p", newline = true)
|
||||
}
|
||||
MarkdownElementTypes.CODE_SPAN -> {
|
||||
val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text
|
||||
if (startDelimiter != null) {
|
||||
val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter)
|
||||
sb.append("<code>").append(text.htmlEscape()).append("</code>")
|
||||
}
|
||||
}
|
||||
MarkdownElementTypes.CODE_BLOCK,
|
||||
MarkdownElementTypes.CODE_FENCE -> {
|
||||
sb.trimEnd()
|
||||
sb.append("<pre><code>")
|
||||
processChildren()
|
||||
sb.append("</code></pre>")
|
||||
}
|
||||
MarkdownElementTypes.SHORT_REFERENCE_LINK,
|
||||
MarkdownElementTypes.FULL_REFERENCE_LINK -> {
|
||||
val linkLabelNode = node.child(MarkdownElementTypes.LINK_LABEL)
|
||||
val linkLabelContent = linkLabelNode?.children
|
||||
?.dropWhile { it.type == MarkdownTokenTypes.LBRACKET }
|
||||
?.dropLastWhile { it.type == MarkdownTokenTypes.RBRACKET }
|
||||
if (linkLabelContent != null) {
|
||||
val label = linkLabelContent.joinToString(separator = "") { it.text }
|
||||
val linkText = node.child(MarkdownElementTypes.LINK_TEXT)?.toHtml() ?: label
|
||||
DocumentationManagerUtil.createHyperlink(sb, label, linkText, true)
|
||||
}
|
||||
else {
|
||||
sb.append(node.text)
|
||||
}
|
||||
}
|
||||
MarkdownElementTypes.INLINE_LINK -> {
|
||||
val label = node.child(MarkdownElementTypes.LINK_TEXT)?.toHtml()
|
||||
val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)?.text
|
||||
if (label != null && destination != null) {
|
||||
sb.append("<a href=\"$destination\">$label</a>")
|
||||
}
|
||||
else {
|
||||
sb.append(node.text)
|
||||
}
|
||||
}
|
||||
MarkdownTokenTypes.TEXT,
|
||||
MarkdownTokenTypes.WHITE_SPACE,
|
||||
MarkdownTokenTypes.COLON,
|
||||
MarkdownTokenTypes.SINGLE_QUOTE,
|
||||
MarkdownTokenTypes.DOUBLE_QUOTE,
|
||||
MarkdownTokenTypes.LPAREN,
|
||||
MarkdownTokenTypes.RPAREN,
|
||||
MarkdownTokenTypes.LBRACKET,
|
||||
MarkdownTokenTypes.RBRACKET,
|
||||
MarkdownTokenTypes.EXCLAMATION_MARK -> {
|
||||
sb.append(nodeText)
|
||||
}
|
||||
MarkdownTokenTypes.CODE_LINE -> {
|
||||
sb.append(nodeText.removePrefix(KDocTag.indentationWhiteSpaces).htmlEscape())
|
||||
}
|
||||
MarkdownTokenTypes.CODE_FENCE_CONTENT -> {
|
||||
sb.append(nodeText.htmlEscape())
|
||||
}
|
||||
MarkdownTokenTypes.EOL -> {
|
||||
val parentType = node.parent?.type
|
||||
if (parentType == MarkdownElementTypes.CODE_BLOCK || parentType == MarkdownElementTypes.CODE_FENCE) {
|
||||
sb.append("\n")
|
||||
}
|
||||
else {
|
||||
sb.append(" ")
|
||||
}
|
||||
}
|
||||
MarkdownTokenTypes.GT -> sb.append(">")
|
||||
MarkdownTokenTypes.LT -> sb.append("<")
|
||||
|
||||
MarkdownElementTypes.LINK_TEXT -> {
|
||||
val childrenWithoutBrackets = node.children.drop(1).dropLast(1)
|
||||
for (child in childrenWithoutBrackets) {
|
||||
sb.append(child.toHtml())
|
||||
}
|
||||
}
|
||||
|
||||
MarkdownTokenTypes.EMPH -> {
|
||||
val parentNodeType = node.parent?.type
|
||||
if (parentNodeType != MarkdownElementTypes.EMPH && parentNodeType != MarkdownElementTypes.STRONG) {
|
||||
sb.append(node.text)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
processChildren()
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString().trimEnd()
|
||||
}
|
||||
|
||||
private fun StringBuilder.trimEnd() {
|
||||
while (length > 0 && this[length - 1] == ' ') {
|
||||
deleteCharAt(length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.htmlEscape(): String = replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
interface OurFace
|
||||
open class OurClass
|
||||
|
||||
fun context() {
|
||||
val v = object : OurClass(), OurFace {}
|
||||
v<caret>
|
||||
}
|
||||
|
||||
//INFO: <pre><b>val</b> v: <anonymous object : <a href="psi_element://OurClass">OurClass</a>, <a href="psi_element://OurFace">OurFace</a>></pre>
|
||||
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
/** Use [SOME_REFERENCED_VAL] to do something */
|
||||
fun fo<caret>o() {
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SOME_REFERENCED_VAL = 1
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>fun</b> foo(): Unit <i>defined in</i> C</pre><p>Use <a href="psi_element://SOME_REFERENCED_VAL">SOME_REFERENCED_VAL</a> to do something</p>
|
||||
@@ -0,0 +1,3 @@
|
||||
fun some(<caret>f: (Int) -> String) : String? = null
|
||||
|
||||
//INFO: <pre><b>value-parameter</b> f: (Int) → String</pre>
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
listOf(1).forEach {
|
||||
println(it<caret>)
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>value-parameter</b> it: Int</pre>
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
listOf(1).forEach {
|
||||
println(i<caret>t)
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>value-parameter</b> it: Int</pre>
|
||||
@@ -0,0 +1,9 @@
|
||||
fun context() {
|
||||
fun local() {
|
||||
|
||||
}
|
||||
|
||||
<caret>local()
|
||||
}
|
||||
|
||||
//INFO: <pre><b>local</b> <b>final</b> <b>fun</b> local(): Unit</pre>
|
||||
@@ -0,0 +1,5 @@
|
||||
interface Base
|
||||
|
||||
class Some<<caret>T: Base>
|
||||
|
||||
//INFO: <pre><T : <a href="psi_element://Base">Base</a>> <i>defined in</i> Some</pre>
|
||||
@@ -0,0 +1,8 @@
|
||||
fun some() : String? = null
|
||||
|
||||
fun test() {
|
||||
val <caret>test = some()
|
||||
}
|
||||
|
||||
|
||||
//INFO: <pre><b>val</b> test: String?</pre>
|
||||
@@ -0,0 +1,7 @@
|
||||
class C(var v: Int) {
|
||||
fun foo() {
|
||||
print(<caret>v)
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>var</b> v: Int <i>defined in</i> C</pre>
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Code block:
|
||||
* ``` kotlin
|
||||
* A<T>
|
||||
* ```
|
||||
* Code span:
|
||||
* `<T>` is type parameter
|
||||
*/
|
||||
class <caret>A<T>
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>class</b> A<T> <i>defined in</i> root package <i>in file</i> EscapeHtmlInsideCodeBlocks.kt</pre><p>Code block:</p>
|
||||
//INFO: <pre><code>
|
||||
//INFO: A<T>
|
||||
//INFO: </code></pre><p>Code span: <code><T></code> is type parameter</p>
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
interface Foo
|
||||
|
||||
fun foo(a: Any) {}
|
||||
|
||||
fun Foo.bar() {
|
||||
foo(th<caret>is)
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> <a href="psi_element://Foo">Foo</a>.bar(): Unit <i>defined in</i> root package <i>in file</i> ExtensionReceiver.kt</pre>
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
interface Foo
|
||||
|
||||
fun foo(a: Any) {}
|
||||
|
||||
fun Foo.bar() {
|
||||
foo(this<caret>)
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> <a href="psi_element://Foo">Foo</a>.bar(): Unit <i>defined in</i> root package <i>in file</i> ExtensionReceiverEnd.kt</pre>
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* val a = A()
|
||||
* println(a) // comment
|
||||
* ```
|
||||
* <fenced>Code_block</fenced>
|
||||
* ```
|
||||
* val b = B()
|
||||
* println(b)
|
||||
* some text content
|
||||
*
|
||||
* Indented code block with tab
|
||||
* Second line
|
||||
*/
|
||||
class <caret>A
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>class</b> A <i>defined in</i> root package <i>in file</i> IndentedCodeBlock.kt</pre><br/><pre><code>val a = A()
|
||||
//INFO: println(a) // comment</code></pre><pre><code>
|
||||
//INFO: <fenced>Code_block</fenced>
|
||||
//INFO: </code></pre><pre><code>val b = B()
|
||||
//INFO: println(b)</code></pre><p>some text content</p>
|
||||
//INFO: <pre><code>Indented code block with tab
|
||||
//INFO: Second line</code></pre>
|
||||
@@ -0,0 +1,8 @@
|
||||
fun testing() {
|
||||
<caret>SomeClass<List<String>>()
|
||||
}
|
||||
|
||||
//INFO: <html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><PRE>public class <b>SomeClass</b><T extends <a href="psi_element://java.util.List"><code>List</code></a>>
|
||||
//INFO: extends <a href="psi_element://java.lang.Object"><code>Object</code></a></PRE>
|
||||
//INFO: Some Java Class
|
||||
//INFO: <DD><DL><DT><b>Type parameters:</b><DD><code><T></code> - </DD></DL></DD></body></html>
|
||||
@@ -0,0 +1,9 @@
|
||||
class A : OverrideMe() {
|
||||
override fun <caret>overrideMe() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//INFO: <pre><b>protected</b> <b>open</b> <b>fun</b> overrideMe(): Unit <i>defined in</i> A</pre><DD><DL><DT><b>Description copied from class:</b> <a href="psi_element://OverrideMe"><code>OverrideMe</code></a><br>
|
||||
//INFO: Some comment
|
||||
//INFO: </DD></DL></DD><DD><DL><DT><b>Overrides:</b><DD><a href="psi_element://OverrideMe#overrideMe()"><code>overrideMe</code></a> in class <a href="psi_element://OverrideMe"><code>OverrideMe</code></a></DD></DL></DD>
|
||||
@@ -0,0 +1,9 @@
|
||||
class A : OverrideMe {
|
||||
override fun <caret>overrideMe() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//INFO: <pre><b>public</b> <b>open</b> <b>fun</b> overrideMe(): Unit <i>defined in</i> A</pre><DD><DL><DT><b>Description copied from interface:</b> <a href="psi_element://OverrideMe"><code>OverrideMe</code></a><br>
|
||||
//INFO: Some comment
|
||||
//INFO: </DD></DL></DD><DD><DL><DT><b>Specified by:</b><DD><a href="psi_element://OverrideMe#overrideMe()"><code>overrideMe</code></a> in interface <a href="psi_element://OverrideMe"><code>OverrideMe</code></a></DD></DL></DD>
|
||||
@@ -0,0 +1,13 @@
|
||||
fun ktTest() {
|
||||
Test.<caret>foo("SomeTest")
|
||||
}
|
||||
|
||||
//INFO: <html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Test"><code>Test</code></a></b></small><PRE><i>@Contract(pure = true)</i>
|
||||
//INFO: <i>@<a href="psi_element://org.jetbrains.annotations.NotNull"><code>NotNull</code></a></i>
|
||||
//INFO: public static <a href="psi_element://java.lang.Object"><code>Object</code></a>[] <b>foo</b>(<a href="psi_element://java.lang.String"><code>String</code></a> param)</PRE>
|
||||
//INFO: Java Method
|
||||
//INFO:
|
||||
//INFO: <i>Inferred</i> annotations available:<br>
|
||||
//INFO: <ul>
|
||||
//INFO: <li><i>@org.jetbrains.annotations.Contract(pure = true)</i> <i>@<a href="psi_element://org.jetbrains.annotations.NotNull"><code>org.jetbrains.annotations.NotNull</code></a></i></li>
|
||||
//INFO: </ul></body></html>
|
||||
@@ -0,0 +1,9 @@
|
||||
import testing.Test;
|
||||
|
||||
class KotlinClassUsedFromJava {
|
||||
void test() {
|
||||
<caret>Test();
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>class</b> Test <i>defined in</i> testing <i>in file</i> KotlinClassUsedFromJava_Data.kt</pre><p>Some comment</p>
|
||||
@@ -0,0 +1,10 @@
|
||||
import testing.KotlinPackageClassUsedFromJava_DataKt;
|
||||
|
||||
class KotlinPackageClassUsedFromJava {
|
||||
void test() {
|
||||
<caret>KotlinPackageClassUsedFromJava_DataKt.foo();
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b>testing</b></small><PRE>public final class <b>testing.KotlinPackageClassUsedFromJava_DataKt</b>
|
||||
//INFO: extends <a href="psi_element://java.lang.Object"><code>Object</code></a></PRE></body></html>
|
||||
@@ -0,0 +1,5 @@
|
||||
fun test() {
|
||||
listOf(1, 2, 4).<caret>filter { it > 0 }
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>inline</b> <b>fun</b> <T> <a href="psi_element://kotlin.collections.Iterable">Iterable</a><<a href="psi_element://kotlin.collections.filter.T">T</a>>.filter(predicate: (<a href="psi_element://kotlin.collections.filter.T">T</a>) → Boolean): <a href="psi_element://kotlin.collections.List">List</a><<a href="psi_element://kotlin.collections.filter.T">T</a>> <i>defined in</i> kotlin.collections <i>in file</i> CollectionsKt.class</pre><p>Returns a list containing only elements matching the given <a href="psi_element://predicate">predicate</a>.</p>
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Usefull comment
|
||||
*/
|
||||
class <caret>Some
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>class</b> Some <i>defined in</i> root package <i>in file</i> OnClassDeclarationWithNoPackage.kt</pre><p>Usefull comment</p>
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Useless one
|
||||
*/
|
||||
enum class SomeEnum
|
||||
|
||||
fun use() {
|
||||
Some<caret>Enum::class
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>enum class</b> SomeEnum : <a href="psi_element://kotlin.Enum">Enum</a><<a href="psi_element://SomeEnum">SomeEnum</a>> <i>defined in</i> root package <i>in file</i> OnEnumClassReference.kt</pre><p>Useless one</p>
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Useless one
|
||||
*/
|
||||
enum class SomeEnum<caret>
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>enum class</b> SomeEnum : <a href="psi_element://kotlin.Enum">Enum</a><<a href="psi_element://SomeEnum">SomeEnum</a>> <i>defined in</i> root package <i>in file</i> OnEnumDeclaration.kt</pre><p>Useless one</p>
|
||||
@@ -0,0 +1,7 @@
|
||||
enum class TestEnum{
|
||||
A, B, <caret>C
|
||||
}
|
||||
|
||||
|
||||
|
||||
//INFO: <pre><b>enum entry</b> C <i>defined in</i> TestEnum</pre><b>Enum constant ordinal: 2</b>
|
||||
@@ -0,0 +1,9 @@
|
||||
enum class TestEnum{
|
||||
A, B, C
|
||||
}
|
||||
|
||||
fun test() {
|
||||
TestEnum.<caret>C
|
||||
}
|
||||
|
||||
//INFO: <pre><b>enum entry</b> C <i>defined in</i> TestEnum</pre><b>Enum constant ordinal: 2</b>
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Enum of 1, 2
|
||||
*/
|
||||
enum class SomeEnum(val i: Int) {
|
||||
One(1), Two(2);
|
||||
}
|
||||
|
||||
fun use() {
|
||||
Some<caret>Enum.One
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>final</b> <b>enum class</b> SomeEnum : <a href="psi_element://kotlin.Enum">Enum</a><<a href="psi_element://SomeEnum">SomeEnum</a>> <i>defined in</i> root package <i>in file</i> OnEnumUsage.kt</pre><p>Enum of 1, 2</p>
|
||||
@@ -0,0 +1,11 @@
|
||||
enum class E {
|
||||
A
|
||||
}
|
||||
|
||||
fun use() {
|
||||
E.valueOf<caret>("A")
|
||||
}
|
||||
|
||||
|
||||
//INFO: <b>public</b> <b>final</b> <b>fun</b> valueOf(value: String): <a href="psi_element://E">E</a> <i>defined in</i> E<p>Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)</p>
|
||||
//INFO: <dl><dt><b>Throws:</b></dt><dd><code>IllegalArgumentException</code> - if this enum type has no constant with the specified name</dd></dl>
|
||||
@@ -0,0 +1,9 @@
|
||||
enum class E {
|
||||
|
||||
}
|
||||
|
||||
fun use() {
|
||||
E.values<caret>()
|
||||
}
|
||||
|
||||
//INFO: <b>public</b> <b>final</b> <b>fun</b> values(): Array<<a href="psi_element://E">E</a>> <i>defined in</i> E<p>Returns an array containing the constants of this enum type, in the order they're declared. This method may be used to iterate over the constants.</p>
|
||||
@@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
/**
|
||||
|
||||
*
|
||||
*
|
||||
* Test function
|
||||
|
||||
*
|
||||
* @param first Some
|
||||
* @param second Other
|
||||
*/
|
||||
fun <caret>testFun(first: String, second: Int) = 12
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testFun(first: String, second: Int): Int <i>defined in</i> test <i>in file</i> OnFunctionDeclarationWithPackage.kt</pre><p>Test function</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>first</code> - Some</dd><dd><code>second</code> - Other</dd></dl>
|
||||
@@ -0,0 +1,17 @@
|
||||
open class C() {
|
||||
/**
|
||||
* This method returns zero.
|
||||
*/
|
||||
open fun foo(): Int = 0
|
||||
}
|
||||
|
||||
class D(): C() {
|
||||
override fun foo(): Int = 1
|
||||
}
|
||||
|
||||
|
||||
fun test() {
|
||||
D().f<caret>oo()
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>open</b> <b>fun</b> foo(): Int <i>defined in</i> D</pre><p>This method returns zero.</p>
|
||||
@@ -0,0 +1,17 @@
|
||||
open class C() {
|
||||
/**
|
||||
* This property returns zero.
|
||||
*/
|
||||
open val foo: Int get() = 0
|
||||
}
|
||||
|
||||
class D(): C() {
|
||||
override val foo: Int get() = 1
|
||||
}
|
||||
|
||||
|
||||
fun test() {
|
||||
D().f<caret>oo
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>open</b> <b>val</b> foo: Int <i>defined in</i> D</pre><p>This property returns zero.</p>
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsage.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Some documentation
|
||||
* on two lines.
|
||||
*/
|
||||
fun testMethod() {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod()
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageMultiline.kt</pre><p>Some documentation on two lines.</p>
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param[a] Some int
|
||||
* @param[b] String
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithBracketsInParam.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Some documentation.
|
||||
*
|
||||
* ```
|
||||
* Code block
|
||||
* Second line
|
||||
*
|
||||
* Third line
|
||||
* ```
|
||||
*
|
||||
* Text between code blocks.
|
||||
* ```
|
||||
* ```
|
||||
* Text after code block.
|
||||
*/
|
||||
fun testMethod() {
|
||||
|
||||
}
|
||||
|
||||
class C {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithCodeBlock.kt</pre><p>Some documentation.</p>
|
||||
//INFO: <pre><code>
|
||||
//INFO: Code block
|
||||
//INFO: Second line
|
||||
//INFO:
|
||||
//INFO: Third line
|
||||
//INFO: </code></pre><p>Text between code blocks.</p>
|
||||
//INFO: <pre><code>
|
||||
//INFO: </code></pre><p>Text after code block.</p>
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Some documentation. **Bold** *underline* `code` foo: bar (baz) [quux] <xyzzy> 'apos'
|
||||
*
|
||||
* [Kotlin](http://www.kotlinlang.org)
|
||||
* [a**b**__d__ kas ](http://www.ibm.com)
|
||||
*
|
||||
* [C]
|
||||
*
|
||||
* [See **this** class][C]
|
||||
*
|
||||
* This is _emphasized text_ but text_with_underscores has to preserve the underscores.
|
||||
* Single stars embedded in a word like Embedded*Star have to be preserved as well.
|
||||
*
|
||||
* Exclamation marks are also important! Also in `code blocks!`
|
||||
*
|
||||
* bt+ : ``prefix ` postfix``
|
||||
* backslash: `\`
|
||||
*/
|
||||
fun testMethod() {
|
||||
|
||||
}
|
||||
|
||||
class C {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithMarkdown.kt</pre><p>Some documentation. <strong>Bold</strong> <em>underline</em> <code>code</code> foo: bar (baz) <a href="psi_element://quux">quux</a> 'apos'</p>
|
||||
//INFO: <p><a href="http://www.kotlinlang.org">Kotlin</a> <a href="http://www.ibm.com">a<strong>b</strong><strong>d</strong> kas</a></p>
|
||||
//INFO: <p><a href="psi_element://C">C</a></p>
|
||||
//INFO: <p><a href="psi_element://C">See <strong>this</strong> class</a></p>
|
||||
//INFO: <p>This is <em>emphasized text</em> but text_with_underscores has to preserve the underscores. Single stars embedded in a word like Embedded*Star have to be preserved as well.</p>
|
||||
//INFO: <p>Exclamation marks are also important! Also in <code>code blocks!</code></p>
|
||||
//INFO: <p>bt+ : <code>prefix ` postfix</code> backslash: <code>\</code></p>
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Some documentation
|
||||
* on two lines.
|
||||
*
|
||||
* @param test String
|
||||
* on two lines
|
||||
*/
|
||||
fun testMethod(test: String) {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod("")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(test: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithMultilineParam.kt</pre><p>Some documentation on two lines.</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>test</code> - String on two lines</dd></dl>
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @receiver Some int
|
||||
* @param b String
|
||||
* @return Return [a] and nothing else
|
||||
*/
|
||||
fun Int.testMethod(b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
1.<caret>testMethod("value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> Int.testMethod(b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithReceiver.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Receiver:</b></dt><dd>Some int</dd></dl>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>b</code> - String</dd></dl>
|
||||
//INFO: <dl><dt><b>Returns:</b></dt><dd>Return <a href="psi_element://a">a</a> and nothing else</dd></dl>
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
* @return Return [a] and nothing else
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithReturnAndLink.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
|
||||
//INFO: <dl><dt><b>Returns:</b></dt><dd>Return <a href="psi_element://a">a</a> and nothing else</dd></dl>
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
* @return Return value
|
||||
* @throws IllegalArgumentException if the weather is bad
|
||||
*/
|
||||
fun testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(a: Int, b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithReturnAndThrows.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
|
||||
//INFO: <dl><dt><b>Returns:</b></dt><dd>Return value</dd></dl>
|
||||
//INFO: <dl><dt><b>Throws:</b></dt><dd><code>IllegalArgumentException</code> - if the weather is bad</dd></dl>
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @see C
|
||||
* @see D
|
||||
* @see <a href="http://kotl.in">kotlin</a>
|
||||
*/
|
||||
fun testMethod() {
|
||||
|
||||
}
|
||||
|
||||
class C {
|
||||
}
|
||||
|
||||
class D {
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> testMethod(): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithSee.kt</pre><br/>
|
||||
//INFO: <DD><DL><DT><b>See Also:</b><DD><a href="psi_element://C"><code>C</code></a>, <a href="psi_element://D"><code>D</code></a>, <a href="http://kotl.in">kotlin</a></DD></DL></DD>
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
Some documentation
|
||||
|
||||
* @param T the type parameter
|
||||
* @param a Some int
|
||||
* @param b String
|
||||
*/
|
||||
fun <T> testMethod(a: Int, b: String) {
|
||||
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<caret>testMethod(1, "value")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> <T> testMethod(a: Int, b: String): Unit <i>defined in</i> root package <i>in file</i> OnMethodUsageWithTypeParameter.kt</pre><p>Some documentation</p>
|
||||
//INFO: <dl><dt><b>Parameters:</b></dt><dd><code>T</code> - the type parameter</dd><dd><code>a</code> - Some int</dd><dd><code>b</code> - String</dd></dl>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package magic
|
||||
|
||||
object Samples {
|
||||
fun sampleMagic() {
|
||||
castTextSpell("[asd] [dse] [asz]")
|
||||
}
|
||||
}
|
||||
|
||||
fun sampleScroll() {
|
||||
val reader = Scroll("[asd] [dse] [asz]").reader()
|
||||
castTextSpell(reader.readAll())
|
||||
}
|
||||
|
||||
/**
|
||||
* @sample Samples.sampleMagic
|
||||
* @sample sampleScroll
|
||||
*/
|
||||
fun <caret>castTextSpell(spell: String) {
|
||||
throw SecurityException("Magic prohibited outside Hogwarts")
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> castTextSpell(spell: String): Unit <i>defined in</i> magic <i>in file</i> Samples.kt</pre><br/>
|
||||
//INFO: <dl><dt><b>Samples:</b></dt><dd><a href="psi_element://Samples.sampleMagic"><code>Samples.sampleMagic</code></a><pre><code>
|
||||
//INFO: castTextSpell("[asd] [dse] [asz]")
|
||||
//INFO: </code></pre></dd><dd><a href="psi_element://sampleScroll"><code>sampleScroll</code></a><pre><code>
|
||||
//INFO: val reader = Scroll("[asd] [dse] [asz]").reader()
|
||||
//INFO: castTextSpell(reader.readAll())
|
||||
//INFO: </code></pre></dd></dl>
|
||||
@@ -0,0 +1,11 @@
|
||||
package server
|
||||
|
||||
import some.TopLevelMethodFromJava_DataKt
|
||||
|
||||
class Testing {
|
||||
void test() {
|
||||
TopLevelMethodFromJava_DataKt.<caret>foo(12);
|
||||
}
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> foo(bar: Int): Unit <i>defined in</i> some <i>in file</i> TopLevelMethodFromJava_Data.kt</pre><p>KDoc foo</p>
|
||||
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
|
||||
}
|
||||
|
||||
fun foo(x : A) { }
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
<caret>foo()
|
||||
}
|
||||
|
||||
//INFO: <pre><b>public</b> <b>fun</b> foo(x: <a href="psi_element://A">A</a>): Unit <i>defined in</i> root package <i>in file</i> TypeNamesFromStdLibNavigation.kt</pre>
|
||||
Reference in New Issue
Block a user