diff --git a/libraries/kdoc/kdoc.iml b/libraries/kdoc/kdoc.iml
index 0de4561e8e1..eaed1e76539 100644
--- a/libraries/kdoc/kdoc.iml
+++ b/libraries/kdoc/kdoc.iml
@@ -35,6 +35,8 @@
+
+
diff --git a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/model/KotlinModel.kt b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/model/KotlinModel.kt
index fe167bbecce..e8b58ebf1f9 100644
--- a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/model/KotlinModel.kt
+++ b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/model/KotlinModel.kt
@@ -31,6 +31,7 @@ import org.pegdown.ast.AutoLinkNode
import org.pegdown.ast.ExpLinkNode
import org.pegdown.Extensions
import org.jetbrains.kotlin.doc.templates.KDocTemplate
+import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl
fun containerName(descriptor: DeclarationDescriptor): String = qualifiedName(descriptor.getContainingDeclaration())
@@ -125,6 +126,18 @@ abstract class KClassOrPackage(model: KModel, declarationDescriptor: Declaration
public open val functions: SortedSet = TreeSet()
public open val properties: SortedSet = TreeSet()
+
+ fun findProperty(name: String): KProperty? {
+ // TODO we should use a Map?
+ return properties.find{ it.name == name }
+ }
+
+ fun findFunction(expression: String): KFunction? {
+ val idx = expression.indexOf('(')
+ val name = if (idx > 0) expression.substring(0, idx) else expression
+ val postfix = if (idx > 0) expression.substring(idx).trimTrailing("()") else ""
+ return functions.find{ it.name == name && it.parameterTypeText == postfix }
+ }
}
class KModel(var context: BindingContext, val config: KDocConfig, var title: String = "Documentation", var version: String = "TODO") {
@@ -358,6 +371,22 @@ class KModel(var context: BindingContext, val config: KDocConfig, var title: Str
return null
}
+ /**
+ * Returns the [[KClass]] for the fully qualified name or null if it could not be found
+ */
+ fun getClass(qualifiedName: String): KClass? {
+ // TODO warning this only works for top level classes
+ // a better algorithm is to walk down each dot path dealing with nested packages/classes
+ val idx = qualifiedName.lastIndexOf('.')
+ val pkgName = if (idx >= 0) qualifiedName.substring(0, idx) ?: "" else ""
+ val pkg = getPackage(pkgName)
+ if (pkg != null) {
+ val simpleName = if (idx >= 0) qualifiedName.substring(idx + 1) ?: "" else qualifiedName
+ return pkg.classMap.get(simpleName)
+ }
+ return null
+ }
+
fun getClass(classElement: ClassDescriptor): KClass? {
val name = classElement.getName()
val container = classElement.getContainingDeclaration()
@@ -384,10 +413,107 @@ class KModel(var context: BindingContext, val config: KDocConfig, var title: Str
class TemplateLinkRenderer(val annotated: KAnnotated, val template: KDocTemplate) : LinkRenderer() {
override fun render(node : WikiLinkNode?) : Rendering? {
- annotated.declarationDescriptor.getContainingDeclaration()
- println("LinkRenderer.render(WikiLinkNode): $node")
- // TODO translate the wiki link to a Class/function/property/extensionFunction etc
- return super.render(node)
+ val answer = super.render(node)
+ if (answer != null) {
+ val text = answer.text
+ if (text != null) {
+ val qualified = resolveToQualifiedName(text)
+
+ var href = resolveClassNameLink(qualified)
+ if (href != null) {
+ answer.href = href
+ } else {
+
+ // TODO really dirty hack alert!!!
+ // until the resolver is working, lets try adding a few prefixes :)
+ for (prefix in arrayList("java.lang", "java.util", "java.util.regex", "java.io", "jet"))
+ if (href == null) {
+ href = resolveClassNameLink(prefix + "." + qualified)
+ }
+ /** TODO use break when KT-1523 is fixed
+ if (href != null) {
+ break
+ }
+ */
+ }
+ if (href != null) {
+ answer.href = href
+ } else {
+ println("Warning: could not resolve expression: $qualified into a wiki link")
+ }
+ }
+ }
+ return answer
+ }
+
+ /**
+ * Try to resolve a fully qualified class name as a link
+ */
+ protected fun resolveClassNameLink(qualifiedName: String): String? {
+ val model = annotated.model
+ val pkg = model.getPackage(qualifiedName)
+ if (pkg != null) {
+ return template.href(pkg)
+ }
+ val klass = model.getClass(qualifiedName)
+ if (klass != null) {
+ return template.href(klass)
+ } else {
+ // is it a method?
+ val idx = qualifiedName.lastIndexOf('.')
+ if (idx > 0) {
+ val className = qualifiedName.substring(0, idx)
+ val c = model.getClass(className)
+ if (c != null) {
+ // lets try find method...
+ val remaining = qualifiedName.substring(idx + 1)
+ // lets try find the function
+ val fn = c.findFunction(remaining)
+ if (fn != null) {
+ return template.href(fn)
+ }
+ val p = c.findProperty(remaining)
+ if (p != null) {
+ return template.href(p)
+ }
+ }
+ }
+ return null
+ }
+ }
+ /**
+ * Attempts to resolve the class, method or property expression using the
+ * current imports and declaraiton
+ */
+ protected fun resolveToQualifiedName(text: String): String {
+ // TODO use the CompletionContributors maybe to figure out what local names are imported???
+ return text
+/*
+ val scope = findWritableScope(annotated.declarationDescriptor)
+ if (scope != null) {
+ val classifierDescriptor = scope.getClassifier(text)
+ if (classifierDescriptor == null) {
+ val o = scope.getObjectDescriptor(text)
+ println("Attempt to resolve HREF: $text Found objectDescriptor $o")
+ } else {
+ println("Attempt to resolve HREF: $text Found classifierDescriptor $classifierDescriptor")
+ }
+ }
+ }
+
+ protected fun findWritableScope(declarationDescriptor: DeclarationDescriptor) : WritableScopeImpl? {
+ val container = declarationDescriptor.getContainingDeclaration()
+ if (container is NamespaceDescriptor) {
+ val scope = container.getMemberScope()
+ if (scope is WritableScopeImpl) {
+ return scope
+ }
+ } else if (container != null) {
+ return findWritableScope(container)
+ }
+ return null
+
+*/
}
override fun render(node : RefLinkNode?, url : String?, title : String?, text : String?) : Rendering? {
@@ -404,6 +530,8 @@ class TemplateLinkRenderer(val annotated: KAnnotated, val template: KDocTemplate
// println("LinkRenderer.render(ExpLinkNode): $node text: $text")
return super.render(node, text)
}
+
+
}
abstract class KAnnotated(val model: KModel, val declarationDescriptor: DeclarationDescriptor) {
diff --git a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/templates/ClassExtensionsTemplate.kt b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/templates/ClassExtensionsTemplate.kt
index 93ddaf8f992..64a883ee720 100644
--- a/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/templates/ClassExtensionsTemplate.kt
+++ b/libraries/kdoc/src/main/kotlin/org/jetbrains/kotlin/doc/templates/ClassExtensionsTemplate.kt
@@ -41,6 +41,6 @@ from package ${link(pkg)}
""")
}
- override fun href(f: KFunction): String = "#${f.link}"
+ override fun href(f: KFunction): String = if (f.extensionClass == klass) "#${f.link}" else super.href(f)
}