kdoc improvements: added discovery of ReadMe.md or ReadMe.html files in a package source directory, so we can auto-discover documentation like this https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/ReadMe.md and fixed a regression where we could not find the KPackage of a descriptor with changes to the AST

This commit is contained in:
James Strachan
2012-04-14 05:26:23 +01:00
parent 07011ef00d
commit 7a96079cfd
2 changed files with 59 additions and 25 deletions
@@ -143,7 +143,7 @@ public class KDocMojo extends KotlinCompileMojoBase {
/** /**
* A Map of package name to file names for the description of packages. * A Map of package name to file names for the description of packages.
* This allows you to refer to ReadMe.md files in your project root directory which will then be included in the API Doc. * This allows you to refer to ReadMe.md files in your project root directory which will then be included in the API Doc.
* For packages which are not configured, KDoc will look for package.html or package.md files in the source directory * For packages which are not configured, KDoc will look for ReadMe.html or ReadMe.md files in the package source directory
* *
* @parameter expression="${packageDescriptionFiles}" * @parameter expression="${packageDescriptionFiles}"
*/ */
@@ -200,6 +200,13 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
private var _projectRootDir: String? = null private var _projectRootDir: String? = null
/**
* File names we look for in a package directory for the overall description of a package for KDoc
*/
val packageDescriptionFiles = arrayList("readme.md", "ReadMe.md, readme.html, ReadMe.html")
private val readMeDirsScanned = HashSet<String>()
/** /**
* Returns the root project directory for calculating relative source links * Returns the root project directory for calculating relative source links
*/ */
@@ -267,28 +274,45 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
if (pkg.wikiDescription.isEmpty()) { if (pkg.wikiDescription.isEmpty()) {
// lets try find a custom doc // lets try find a custom doc
var file = config.packageDescriptionFiles[name] var file = config.packageDescriptionFiles[name]
if (file == null) { loadWikiDescription(pkg, file)
// lets try find the package.html or package.md file }
val srcPath = pkg.filePath() }
if (srcPath != null) { return pkg;
val srcFile = File(srcPath) }
val dir = if (srcFile.isDirectory()) srcFile else srcFile.getParentFile()
val f = arrayList(File(dir, "package.html"), File(dir, "package.md")).find{ it.exists() } protected fun loadWikiDescription(pkg: KPackage, file: String?): Unit {
if (f != null) file = f.getCanonicalPath() else { if (file != null) {
info("package $name has no package.(html|md) in $dir") try {
} pkg.wikiDescription = File(file).readText()
} catch (e: Throwable) {
warning("Failed to load package ${pkg.name} documentation file $file. Reason $e")
}
}
}
/**
* If a package has no detailed description lets try load it from the descriptors
* source directory if we've not checked that directory before
*/
fun tryLoadReadMe(pkg: KPackage, descriptor: DeclarationDescriptor): Unit {
if (pkg.wikiDescription.isEmpty()) {
// lets try find the package.html or package.md file
val srcPath = pkg.model.filePath(descriptor)
if (srcPath != null) {
val srcFile = File(srcPath)
val dir = if (srcFile.isDirectory()) srcFile else srcFile.getParentFile()
if (dir != null && readMeDirsScanned.add(dir.getPath()!!)) {
val f = packageDescriptionFiles.map{ File(dir, it) }.find{ it.exists() }
if (f != null) {
val file = f.getCanonicalPath()
loadWikiDescription(pkg, file)
} }
} else {
if (file != null) { info("package ${pkg.name} has no ReadMe.(html|md) in $dir")
try {
pkg.wikiDescription = File(file).readText()
} catch (e: Throwable) {
warning("Failed to load package $name documentation file $file. Reason $e")
} }
} }
} }
} }
return pkg;
} }
fun wikiConvert(text: String, linkRenderer: LinkRenderer, fileName: String?): String { fun wikiConvert(text: String, linkRenderer: LinkRenderer, fileName: String?): String {
@@ -623,14 +647,20 @@ class KModel(var context: BindingContext, val config: KDocConfig) {
fun getClass(classElement: ClassDescriptor): KClass? { fun getClass(classElement: ClassDescriptor): KClass? {
val name = classElement.getName() val name = classElement.getName()
val container = classElement.getContainingDeclaration() if (name != null) {
if (name != null && container is NamespaceDescriptor) { var dec: DeclarationDescriptor? = classElement.getContainingDeclaration()
val pkg = getPackage(container) while (dec != null) {
return pkg.getClass(name, classElement) val container = dec
} else { if (container is NamespaceDescriptor) {
warning("no package found for $container and class $name") val pkg = getPackage(container)
return null return pkg.getClass(name, classElement)
} else {
dec = dec?.getContainingDeclaration()
}
}
warning("no package found for class $name")
} }
return null
} }
fun previous(pkg: KPackage): KPackage? { fun previous(pkg: KPackage): KPackage? {
@@ -857,6 +887,10 @@ class KPackage(model: KModel, val descriptor: NamespaceDescriptor,
KClass(this, descriptor, name) KClass(this, descriptor, name)
} }
if (created) { if (created) {
// sometimes we may have source files for a package in different source directories
// such as the kotlin package in generated directory; so lets always check if we can find
// the readme
model.tryLoadReadMe(this, descriptor)
model.configureComments(klass, descriptor) model.configureComments(klass, descriptor)
val typeConstructor = descriptor.getTypeConstructor() val typeConstructor = descriptor.getTypeConstructor()
val superTypes = typeConstructor.getSupertypes() val superTypes = typeConstructor.getSupertypes()