1 package org.jetbrains.dokka 2 3 import com.intellij.psi.PsiDocumentManager 4 import com.intellij.psi.PsiElement 5 import com.intellij.psi.PsiNameIdentifierOwner 6 import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition 7 import org.jetbrains.kotlin.psi.psiUtil.startOffset 8 import java.io.File 9 10 appendSourceLinknull11fun DocumentationNode.appendSourceLink(psi: PsiElement?, sourceLinks: List<SourceLinkDefinition>) { 12 val path = psi?.containingFile?.virtualFile?.path ?: return 13 14 val target = if (psi is PsiNameIdentifierOwner) psi.nameIdentifier else psi 15 val absPath = File(path).absolutePath 16 val linkDef = sourceLinks.firstOrNull { absPath.startsWith(it.path) } 17 if (linkDef != null) { 18 var url = linkDef.url + path.substring(linkDef.path.length) 19 if (linkDef.lineSuffix != null) { 20 val line = target?.lineNumber() 21 if (line != null) { 22 url += linkDef.lineSuffix + line.toString() 23 } 24 } 25 append(DocumentationNode(url, Content.Empty, NodeKind.SourceUrl), 26 RefKind.Detail); 27 } 28 29 if (target != null) { 30 append(DocumentationNode(target.sourcePosition(), Content.Empty, NodeKind.SourcePosition), RefKind.Detail) 31 } 32 } 33 sourcePositionnull34private fun PsiElement.sourcePosition(): String { 35 val path = containingFile.virtualFile.path 36 val lineNumber = lineNumber() 37 val columnNumber = columnNumber() 38 39 return when { 40 lineNumber == null -> path 41 columnNumber == null -> "$path:$lineNumber" 42 else -> "$path:$lineNumber:$columnNumber" 43 } 44 } 45 lineNumbernull46fun PsiElement.lineNumber(): Int? { 47 val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile) 48 // IJ uses 0-based line-numbers; external source browsers use 1-based 49 return doc?.getLineNumber(textRange.startOffset)?.plus(1) 50 } 51 columnNumbernull52fun PsiElement.columnNumber(): Int? { 53 val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile) ?: return null 54 val lineNumber = doc.getLineNumber(textRange.startOffset) 55 return startOffset - doc.getLineStartOffset(lineNumber) 56 }