allow kdoc to link to the online source code in a source code repo (such as github)
This commit is contained in:
@@ -50,7 +50,8 @@
|
|||||||
<ignorePackage>junit</ignorePackage>
|
<ignorePackage>junit</ignorePackage>
|
||||||
<ignorePackage>org</ignorePackage>
|
<ignorePackage>org</ignorePackage>
|
||||||
</ignorePackages>
|
</ignorePackages>
|
||||||
|
<sourceRootHref>https://github.com/JetBrains/kotlin/tree/master</sourceRootHref>
|
||||||
|
<projectRootDir>${project-root}</projectRootDir>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
||||||
<executions>
|
<executions>
|
||||||
|
|||||||
+18
@@ -118,6 +118,20 @@ public class KDocMojo extends KotlinCompileMojoBase {
|
|||||||
*/
|
*/
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTTP link to source code
|
||||||
|
*
|
||||||
|
* @parameter expression="${sourceRootHref}"
|
||||||
|
*/
|
||||||
|
private String sourceRootHref;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root project directory used to deduce relative file names when linking to source code
|
||||||
|
*
|
||||||
|
* @parameter expression="${projectRootDir}" default-value="${project.basedir}"
|
||||||
|
*/
|
||||||
|
private String projectRootDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether warnings should be generated if no comments could be found for classes, functions and properties being documented
|
* Whether warnings should be generated if no comments could be found for classes, functions and properties being documented
|
||||||
*
|
*
|
||||||
@@ -150,10 +164,14 @@ public class KDocMojo extends KotlinCompileMojoBase {
|
|||||||
docConfig.setTitle(title);
|
docConfig.setTitle(title);
|
||||||
docConfig.setVersion(version);
|
docConfig.setVersion(version);
|
||||||
docConfig.setWarnNoComments(warnNoComments);
|
docConfig.setWarnNoComments(warnNoComments);
|
||||||
|
docConfig.setSourceRootHref(sourceRootHref);
|
||||||
|
docConfig.setProjectRootDir(projectRootDir);
|
||||||
getLog().info("API docs output to: " + docConfig.getDocOutputDir());
|
getLog().info("API docs output to: " + docConfig.getDocOutputDir());
|
||||||
getLog().info("classpath: " + classpath);
|
getLog().info("classpath: " + classpath);
|
||||||
getLog().info("title: " + title);
|
getLog().info("title: " + title);
|
||||||
getLog().info("sources: " + sources);
|
getLog().info("sources: " + sources);
|
||||||
|
getLog().info("sourceRootHref: " + sourceRootHref);
|
||||||
|
getLog().info("projectRootDir: " + projectRootDir);
|
||||||
getLog().info("API docs ignore packages: " + ignorePackages);
|
getLog().info("API docs ignore packages: " + ignorePackages);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ class KDocConfig() {
|
|||||||
*/
|
*/
|
||||||
public var warnNoComments: Boolean = true
|
public var warnNoComments: Boolean = true
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTTP URL of the root directory of source code that we should link to
|
||||||
|
*/
|
||||||
|
public var sourceRootHref: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root project directory used to deduce relative file names when linking to source code
|
||||||
|
*/
|
||||||
|
public var projectRootDir: String? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if protected functions and properties should be documented
|
* Returns true if protected functions and properties should be documented
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiDirectory
|
import com.intellij.psi.PsiDirectory
|
||||||
import org.jetbrains.jet.lang.descriptors.Visibilities
|
import org.jetbrains.jet.lang.descriptors.Visibilities
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils.LineAndColumn
|
||||||
|
import com.intellij.psi.PsiFileSystemItem
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,6 +194,25 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
|
|||||||
public val version: String
|
public val version: String
|
||||||
get() = config.version
|
get() = config.version
|
||||||
|
|
||||||
|
private var _projectRootDir: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root project directory for calculating relative source links
|
||||||
|
*/
|
||||||
|
fun projectRootDir(): String {
|
||||||
|
if (_projectRootDir == null) {
|
||||||
|
val rootDir = config.projectRootDir
|
||||||
|
_projectRootDir = if (rootDir == null) {
|
||||||
|
warning("KDocConfig does not have a projectRootDir defined so we cannot generate relative source Hrefs")
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
File(rootDir).getCanonicalPath() ?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _projectRootDir ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Loads the model from the given set of source files */
|
/** Loads the model from the given set of source files */
|
||||||
fun load(sources: List<JetFile?>): Unit {
|
fun load(sources: List<JetFile?>): Unit {
|
||||||
val allNamespaces = HashSet<NamespaceDescriptor>()
|
val allNamespaces = HashSet<NamespaceDescriptor>()
|
||||||
@@ -344,12 +367,30 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun locationFor(descriptor: DeclarationDescriptor): LineAndColumn? {
|
||||||
|
val psiElement = getPsiElement(descriptor)
|
||||||
|
if (psiElement != null) {
|
||||||
|
val document = psiElement.getContainingFile()?.getViewProvider()?.getDocument()
|
||||||
|
if (document != null) {
|
||||||
|
val offset = psiElement.getTextOffset()
|
||||||
|
return DiagnosticUtils.offsetToLineAndColumn(document, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
fun fileFor(descriptor: DeclarationDescriptor): String? {
|
fun fileFor(descriptor: DeclarationDescriptor): String? {
|
||||||
val psiElement = getPsiElement(descriptor)
|
val psiElement = getPsiElement(descriptor)
|
||||||
return psiElement?.getContainingFile()?.getName()
|
return psiElement?.getContainingFile()?.getName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun filePath(descriptor: DeclarationDescriptor): String? {
|
||||||
|
val psiElement = getPsiElement(descriptor)
|
||||||
|
val file = psiElement?.getContainingFile()
|
||||||
|
return filePath(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected fun getPsiElement(descriptor: DeclarationDescriptor): PsiElement? {
|
protected fun getPsiElement(descriptor: DeclarationDescriptor): PsiElement? {
|
||||||
return try {
|
return try {
|
||||||
BindingContextUtils.descriptorToDeclaration(context, descriptor)
|
BindingContextUtils.descriptorToDeclaration(context, descriptor)
|
||||||
@@ -446,6 +487,17 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun filePath(file: PsiFileSystemItem?): String? {
|
||||||
|
if (file != null) {
|
||||||
|
var dir = file.getParent()
|
||||||
|
if (dir != null) {
|
||||||
|
val parentName = filePath(dir) ?: ""
|
||||||
|
return parentName + "/" + file.getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the block of code within { .. } tokens or returning null if it can't be found
|
* Extracts the block of code within { .. } tokens or returning null if it can't be found
|
||||||
*/
|
*/
|
||||||
@@ -704,6 +756,39 @@ abstract class KAnnotated(val model: KModel, val declarationDescriptor: Declarat
|
|||||||
val file = model.fileFor(declarationDescriptor)
|
val file = model.fileFor(declarationDescriptor)
|
||||||
return model.wikiConvert(wikiDescription, TemplateLinkRenderer(this, template), file)
|
return model.wikiConvert(wikiDescription, TemplateLinkRenderer(this, template), file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isLinkToSourceRepo(): Boolean {
|
||||||
|
return model.config.sourceRootHref != null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sourceLink(): String {
|
||||||
|
val file = model.filePath(declarationDescriptor)
|
||||||
|
if (file != null) {
|
||||||
|
// lets remove the root project directory
|
||||||
|
val rootDir = model.projectRootDir()
|
||||||
|
val canonicalFile = File(file).getCanonicalPath() ?: ""
|
||||||
|
val relativeFile = if (rootDir != null && canonicalFile.startsWith(rootDir))
|
||||||
|
canonicalFile.substring(rootDir.length()) else canonicalFile
|
||||||
|
return sourceLinkFor(relativeFile!!)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun sourceLinkFor(filePath: String, lineLinkText: String = "#L"): String {
|
||||||
|
val root = model.config.sourceRootHref!!
|
||||||
|
val cleanRoot = root.trimTrailing("/")
|
||||||
|
val cleanPath = filePath.trimLeading("/")
|
||||||
|
return "$cleanRoot/$cleanPath$lineLinkText$sourceLine"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun location(): LineAndColumn? = model.locationFor(declarationDescriptor)
|
||||||
|
|
||||||
|
val sourceLine: Int
|
||||||
|
get() {
|
||||||
|
val loc = location()
|
||||||
|
return if (loc != null) loc.getLine() else 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KNamed(val name: String, model: KModel, declarationDescriptor: DeclarationDescriptor): KAnnotated(model, declarationDescriptor), Comparable<KNamed> {
|
abstract class KNamed(val name: String, model: KModel, declarationDescriptor: DeclarationDescriptor): KAnnotated(model, declarationDescriptor), Comparable<KNamed> {
|
||||||
@@ -772,6 +857,10 @@ class KPackage(model: KModel, val descriptor: NamespaceDescriptor,
|
|||||||
return if (answer.length == 0) "" else answer + "/"
|
return if (answer.length == 0) "" else answer + "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO generates java.lang.NoSuchMethodError: kotlin.util.namespace.hashMap(Ljet/TypeInfo;Ljet/TypeInfo;)Ljava/util/HashMap;
|
// TODO generates java.lang.NoSuchMethodError: kotlin.util.namespace.hashMap(Ljet/TypeInfo;Ljet/TypeInfo;)Ljava/util/HashMap;
|
||||||
//val classes = sortedMap<String,KClass>()
|
//val classes = sortedMap<String,KClass>()
|
||||||
public val classMap: SortedMap<String, KClass> = TreeMap<String, KClass>()
|
public val classMap: SortedMap<String, KClass> = TreeMap<String, KClass>()
|
||||||
@@ -838,8 +927,7 @@ class KClass(val pkg: KPackage, val descriptor: ClassDescriptor,
|
|||||||
var since: String = "",
|
var since: String = "",
|
||||||
var authors: List<String> = arrayList<String>(),
|
var authors: List<String> = arrayList<String>(),
|
||||||
var baseClasses: List<KType> = arrayList<KType>(),
|
var baseClasses: List<KType> = arrayList<KType>(),
|
||||||
var nestedClasses: List<KClass> = arrayList<KClass>(),
|
var nestedClasses: List<KClass> = arrayList<KClass>()): KClassOrPackage(pkg.model, descriptor), Comparable<KClass> {
|
||||||
var sourceLine: Int = 2): KClassOrPackage(pkg.model, descriptor), Comparable<KClass> {
|
|
||||||
|
|
||||||
public override fun compareTo(other: KClass): Int = name.compareTo(other.name)
|
public override fun compareTo(other: KClass): Int = name.compareTo(other.name)
|
||||||
|
|
||||||
@@ -921,8 +1009,7 @@ class KFunction(val descriptor: CallableDescriptor, val owner: KClassOrPackage,
|
|||||||
var modifiers: List<String> = arrayList<String>(),
|
var modifiers: List<String> = arrayList<String>(),
|
||||||
var typeParameters: List<KTypeParameter> = arrayList<KTypeParameter>(),
|
var typeParameters: List<KTypeParameter> = arrayList<KTypeParameter>(),
|
||||||
var exceptions: List<KClass> = arrayList<KClass>(),
|
var exceptions: List<KClass> = arrayList<KClass>(),
|
||||||
var annotations: List<KAnnotation> = arrayList<KAnnotation>(),
|
var annotations: List<KAnnotation> = arrayList<KAnnotation>()): KAnnotated(owner.model, descriptor), Comparable<KFunction> {
|
||||||
var sourceLine: Int = 2): KAnnotated(owner.model, descriptor), Comparable<KFunction> {
|
|
||||||
|
|
||||||
public val parameterTypeText: String = parameters.map{ it.aType.name }.makeString(", ")
|
public val parameterTypeText: String = parameters.map{ it.aType.name }.makeString(", ")
|
||||||
|
|
||||||
|
|||||||
+51
-20
@@ -54,30 +54,61 @@ abstract class KDocTemplate() : TextTemplate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun sourceHref(klass: KClass): String {
|
open fun sourceHref(klass: KClass): String {
|
||||||
val pkg = klass.pkg
|
if (klass.isLinkToSourceRepo()) {
|
||||||
return if (pkg.local) {
|
return klass.sourceLink()
|
||||||
"${pkg.nameAsRelativePath}src-html/${klass.nameAsPath}.html#line.${klass.sourceLine}"
|
|
||||||
} else {
|
} else {
|
||||||
href(klass)
|
val pkg = klass.pkg
|
||||||
|
return if (pkg.local) {
|
||||||
|
"${pkg.nameAsRelativePath}src-html/${klass.nameAsPath}.html#line.${klass.sourceLine}"
|
||||||
|
} else {
|
||||||
|
href(klass)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open fun sourceHref(f: KFunction): String {
|
open fun sourceHref(f: KFunction): String {
|
||||||
val owner = f.owner
|
if (f.isLinkToSourceRepo()) {
|
||||||
return if (owner is KClass) {
|
return f.sourceLink()
|
||||||
val pkg = owner.pkg
|
} else {
|
||||||
if (pkg.local) {
|
val owner = f.owner
|
||||||
"${rootHref(pkg)}src-html/${owner.simpleName}.html#line.${f.sourceLine}"
|
return if (owner is KClass) {
|
||||||
} else {
|
val pkg = owner.pkg
|
||||||
href(f)
|
if (pkg.local) {
|
||||||
}
|
"${rootHref(pkg)}src-html/${owner.simpleName}.html#line.${f.sourceLine}"
|
||||||
} else if (owner is KPackage) {
|
} else {
|
||||||
if (owner.local) {
|
href(f)
|
||||||
// TODO how to find the function in a package???
|
}
|
||||||
"${rootHref(owner)}src-html/namespace.html#line.${f.sourceLine}"
|
} else if (owner is KPackage) {
|
||||||
} else {
|
if (owner.local) {
|
||||||
href(owner)
|
// TODO how to find the function in a package???
|
||||||
}
|
"${rootHref(owner)}src-html/namespace.html#line.${f.sourceLine}"
|
||||||
} else href(f)
|
} else {
|
||||||
|
href(owner)
|
||||||
|
}
|
||||||
|
} else href(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun sourceHref(f: KProperty): String {
|
||||||
|
if (f.isLinkToSourceRepo()) {
|
||||||
|
return f.sourceLink()
|
||||||
|
} else {
|
||||||
|
val owner = f.owner
|
||||||
|
return if (owner is KClass) {
|
||||||
|
val pkg = owner.pkg
|
||||||
|
if (pkg.local) {
|
||||||
|
"${rootHref(pkg)}src-html/${owner.simpleName}.html#line.${f.sourceLine}"
|
||||||
|
} else {
|
||||||
|
href(f)
|
||||||
|
}
|
||||||
|
} else if (owner is KPackage) {
|
||||||
|
if (owner.local) {
|
||||||
|
// TODO how to find the function in a package???
|
||||||
|
"${rootHref(owner)}src-html/namespace.html#line.${f.sourceLine}"
|
||||||
|
} else {
|
||||||
|
href(owner)
|
||||||
|
}
|
||||||
|
} else href(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun link(c: KClass, fullName: Boolean = false): String {
|
open fun link(c: KClass, fullName: Boolean = false): String {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -207,7 +207,7 @@ abstract class PackageTemplateSupport(open val pkg: KPackage) : KDocTemplate() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
println("""</CODE></FONT></TD>""")
|
println("""</CODE></FONT></TD>""")
|
||||||
print("""<TD><CODE><B><A HREF="${href(property)}">${property.name}</A></B>: """)
|
print("""<TD><CODE><B><A HREF="${sourceHref(property)}">${property.name}</A></B>: """)
|
||||||
print(link(property.returnType))
|
print(link(property.returnType))
|
||||||
//printParameters(property)
|
//printParameters(property)
|
||||||
println("""</CODE>""")
|
println("""</CODE>""")
|
||||||
|
|||||||
Reference in New Issue
Block a user