From e155d101a52f62b0c8c10778fdf0068549b413be Mon Sep 17 00:00:00 2001 From: Ilya Ryzhenkov Date: Sat, 12 Jul 2014 02:29:55 +0400 Subject: Implement resolution scope chaining for all scopes except imported packages. --- src/Analysis/CompilerAPI.kt | 74 +++++++++++++++++------------------ src/Model/DocumentationModel.kt | 6 +-- src/Model/DocumentationNodeBuilder.kt | 16 ++++++++ src/Model/DocumentationResolver.kt | 10 ++++- src/main.kt | 3 +- test/playground.kt | 4 +- 6 files changed, 68 insertions(+), 45 deletions(-) diff --git a/src/Analysis/CompilerAPI.kt b/src/Analysis/CompilerAPI.kt index 9562e763..8c58428c 100644 --- a/src/Analysis/CompilerAPI.kt +++ b/src/Analysis/CompilerAPI.kt @@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.psi.* import org.jetbrains.jet.analyzer.* import org.jetbrains.jet.lang.descriptors.* import org.jetbrains.jet.lang.resolve.scopes.* +import org.jetbrains.jet.lang.resolve.name.* private fun getAnnotationsPath(paths: KotlinPaths, arguments: K2JVMCompilerArguments): MutableList { val annotationsPath = arrayListOf() @@ -62,79 +63,76 @@ fun DeclarationDescriptor.isUserCode() = else -> true } +public fun getPackageInnerScope(descriptor: PackageFragmentDescriptor): JetScope { + val module = descriptor.getContainingDeclaration() + val packageScope = ChainedScope(descriptor, "Package ${descriptor.getName()} scope", descriptor.getMemberScope(), + module.getPackage(FqName.ROOT)!!.getMemberScope()) + return packageScope +} + public fun getClassInnerScope(outerScope: JetScope, descriptor: ClassDescriptor): JetScope { - val redeclarationHandler = object : RedeclarationHandler { - override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) { - // TODO: check if we can ignore redeclarations - } - } + val redeclarationHandler = RedeclarationHandler.DO_NOTHING - val parameterScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Function KDoc scope") + val headerScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Class ${descriptor.getName()} header scope") for (typeParameter in descriptor.getTypeConstructor().getParameters()) { - parameterScope.addTypeParameterDescriptor(typeParameter) + headerScope.addTypeParameterDescriptor(typeParameter) } for (constructor in descriptor.getConstructors()) { - parameterScope.addFunctionDescriptor(constructor) + headerScope.addFunctionDescriptor(constructor) } - parameterScope.addLabeledDeclaration(descriptor) - parameterScope.changeLockLevel(WritableScope.LockLevel.READING) - return parameterScope + headerScope.addLabeledDeclaration(descriptor) + headerScope.changeLockLevel(WritableScope.LockLevel.READING) + + val classScope = ChainedScope(descriptor, "Class ${descriptor.getName()} scope", descriptor.getDefaultType().getMemberScope(), headerScope) + return classScope } public fun getFunctionInnerScope(outerScope: JetScope, descriptor: FunctionDescriptor): JetScope { - val redeclarationHandler = object : RedeclarationHandler { - override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) { - // TODO: check if we can ignore redeclarations - } - } + val redeclarationHandler = RedeclarationHandler.DO_NOTHING - val parameterScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Function KDoc scope") + val functionScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Function ${descriptor.getName()} scope") val receiver = descriptor.getReceiverParameter() if (receiver != null) { - parameterScope.setImplicitReceiver(receiver) + functionScope.setImplicitReceiver(receiver) } for (typeParameter in descriptor.getTypeParameters()) { - parameterScope.addTypeParameterDescriptor(typeParameter) + functionScope.addTypeParameterDescriptor(typeParameter) } for (valueParameterDescriptor in descriptor.getValueParameters()) { - parameterScope.addVariableDescriptor(valueParameterDescriptor) + functionScope.addVariableDescriptor(valueParameterDescriptor) } - parameterScope.addLabeledDeclaration(descriptor) - parameterScope.changeLockLevel(WritableScope.LockLevel.READING) - return parameterScope + functionScope.addLabeledDeclaration(descriptor) + functionScope.changeLockLevel(WritableScope.LockLevel.READING) + return functionScope } public fun getPropertyInnerScope(outerScope: JetScope, descriptor: PropertyDescriptor): JetScope { - val redeclarationHandler = object : RedeclarationHandler { - override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) { - // TODO: check if we can ignore redeclarations - } - } + val redeclarationHandler = RedeclarationHandler.DO_NOTHING - val parameterScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Function KDoc scope") + val propertyScope = WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Property ${descriptor.getName()} scope") val receiver = descriptor.getReceiverParameter() if (receiver != null) { - parameterScope.setImplicitReceiver(receiver) + propertyScope.setImplicitReceiver(receiver) } for (typeParameter in descriptor.getTypeParameters()) { - parameterScope.addTypeParameterDescriptor(typeParameter) + propertyScope.addTypeParameterDescriptor(typeParameter) } for (valueParameterDescriptor in descriptor.getValueParameters()) { - parameterScope.addVariableDescriptor(valueParameterDescriptor) + propertyScope.addVariableDescriptor(valueParameterDescriptor) } for (accessor in descriptor.getAccessors()) { - parameterScope.addFunctionDescriptor(accessor) + propertyScope.addFunctionDescriptor(accessor) } - parameterScope.addLabeledDeclaration(descriptor) - parameterScope.changeLockLevel(WritableScope.LockLevel.READING) - return parameterScope + propertyScope.addLabeledDeclaration(descriptor) + propertyScope.changeLockLevel(WritableScope.LockLevel.READING) + return propertyScope } fun BindingContext.getResolutionScope(descriptor: DeclarationDescriptor): JetScope { when (descriptor) { - is PackageFragmentDescriptor -> return descriptor.getMemberScope() + is PackageFragmentDescriptor -> return getPackageInnerScope(descriptor) is PackageViewDescriptor -> return descriptor.getMemberScope() - is ClassDescriptor -> return getClassInnerScope(descriptor.getDefaultType().getMemberScope(), descriptor) + is ClassDescriptor -> return getClassInnerScope(getResolutionScope(descriptor.getContainingDeclaration()), descriptor) is FunctionDescriptor -> return getFunctionInnerScope(getResolutionScope(descriptor.getContainingDeclaration()), descriptor) is PropertyDescriptor -> return getPropertyInnerScope(getResolutionScope(descriptor.getContainingDeclaration()), descriptor) } diff --git a/src/Model/DocumentationModel.kt b/src/Model/DocumentationModel.kt index aa8d9a6b..83aa911f 100644 --- a/src/Model/DocumentationModel.kt +++ b/src/Model/DocumentationModel.kt @@ -40,8 +40,8 @@ public open class DocumentationNode(val name: String, val scope: JetScope) { private val references = arrayListOf() - public val owner: DocumentationNode - get() = references(DocumentationReferenceKind.Owner).single().to + public val owner: DocumentationNode? + get() = references(DocumentationReferenceKind.Owner).firstOrNull()?.to // TODO: should be singleOrNull, but bugz! public val details: List get() = references(DocumentationReferenceKind.Detail).map { it.to } public val members: List @@ -62,7 +62,7 @@ public open class DocumentationNode(val name: String, public fun allReferences(): List = references public override fun toString(): String { - return "$kind $name" + return "$kind:$name" } } diff --git a/src/Model/DocumentationNodeBuilder.kt b/src/Model/DocumentationNodeBuilder.kt index aa0c4700..d32edbc5 100644 --- a/src/Model/DocumentationNodeBuilder.kt +++ b/src/Model/DocumentationNodeBuilder.kt @@ -19,6 +19,10 @@ class DocumentationNodeBuilder(val context: BindingContext) : DeclarationDescrip override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, data: DocumentationNode?): DocumentationNode? { val node = DocumentationNode(descriptor!!.getName().asString(), "", DocumentationNodeKind.Receiver, context.getResolutionScope(descriptor)) data!!.addReferenceTo(node, DocumentationReferenceKind.Detail) + + val typeNode = DocumentationNode(descriptor.getType().toString(), "", DocumentationNodeKind.UpperBound, context.getResolutionScope(descriptor)) + node.addReferenceTo(typeNode, DocumentationReferenceKind.Detail) + node.addReferenceTo(data, DocumentationReferenceKind.Owner) return node } @@ -27,6 +31,10 @@ class DocumentationNodeBuilder(val context: BindingContext) : DeclarationDescrip val doc = context.getDocumentation(descriptor!!) val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Parameter, context.getResolutionScope(descriptor)) data!!.addReferenceTo(node, DocumentationReferenceKind.Detail) + + val typeNode = DocumentationNode(descriptor.getType().toString(), "", DocumentationNodeKind.UpperBound, context.getResolutionScope(descriptor)) + node.addReferenceTo(typeNode, DocumentationReferenceKind.Detail) + node.addReferenceTo(data, DocumentationReferenceKind.Owner) return node } @@ -47,6 +55,10 @@ class DocumentationNodeBuilder(val context: BindingContext) : DeclarationDescrip val doc = context.getDocumentation(descriptor!!) val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Function, context.getResolutionScope(descriptor)) data!!.addReferenceTo(node, DocumentationReferenceKind.Member) + + val typeNode = DocumentationNode(descriptor.getReturnType().toString(), "", DocumentationNodeKind.UpperBound, context.getResolutionScope(descriptor)) + node.addReferenceTo(typeNode, DocumentationReferenceKind.Detail) + node.addReferenceTo(data, DocumentationReferenceKind.Owner) return node } @@ -76,6 +88,10 @@ class DocumentationNodeBuilder(val context: BindingContext) : DeclarationDescrip val doc = context.getDocumentation(descriptor!!) val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Property, context.getResolutionScope(descriptor)) data!!.addReferenceTo(node, DocumentationReferenceKind.Member) + + val typeNode = DocumentationNode(descriptor.getType().toString(), "", DocumentationNodeKind.UpperBound, context.getResolutionScope(descriptor)) + node.addReferenceTo(typeNode, DocumentationReferenceKind.Detail) + node.addReferenceTo(data, DocumentationReferenceKind.Owner) return node } diff --git a/src/Model/DocumentationResolver.kt b/src/Model/DocumentationResolver.kt index e69a70f8..b5b6b1a2 100644 --- a/src/Model/DocumentationResolver.kt +++ b/src/Model/DocumentationResolver.kt @@ -23,10 +23,18 @@ fun DocumentationNode.checkResolve() { } if (symbol == null) - throw IllegalStateException("Cannot resolve $item in $this") + println("WARNING: Cannot resolve $item in ${path(this)}") } for (reference in allReferences().filterNot { it.kind == DocumentationReferenceKind.Owner }) { reference.to.checkResolve() } +} + +fun path(node: DocumentationNode) : String { + val owner = node.owner + if (owner != null) + return "$node in ${path(owner)}" + else + return "$node" } \ No newline at end of file diff --git a/src/main.kt b/src/main.kt index 1ed3e625..1edecdcb 100644 --- a/src/main.kt +++ b/src/main.kt @@ -4,6 +4,7 @@ import com.sampullara.cli.* import com.intellij.openapi.util.* import org.jetbrains.jet.cli.common.messages.* import org.jetbrains.jet.cli.common.arguments.* +import org.jetbrains.jet.utils.PathUtil class DokkaArguments { Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)") @@ -24,8 +25,8 @@ public fun main(args: Array) { val environment = AnalysisEnvironment(MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR) { /* addClasspath(PathUtil.getJdkClassesRoots()) - addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) */ + addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) addSources(sources) } diff --git a/test/playground.kt b/test/playground.kt index 502d5efd..291419d1 100644 --- a/test/playground.kt +++ b/test/playground.kt @@ -29,7 +29,7 @@ class Class { * This is a class with constructor and space after doc */ -class ClassWithConstructor(/** Doc at parameter */ val name: String) +class ClassWithConstructor(/** Doc at parameter */ val name: Class) /** * This is data class $Person with constructor and two properties @@ -37,7 +37,7 @@ class ClassWithConstructor(/** Doc at parameter */ val name: String) * $name: Person's name * $age: Person's age */ -data class Person(val name: String, val age: Int) {} +data class Person(val name: ClassWithConstructor, val age: Int) {} object Object { throws(javaClass()) -- cgit