move KDoc-related logic shared between IDEA and Dokka to ide-common module
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.kdoc
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
|
||||
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
|
||||
object KDocFinder {
|
||||
fun findKDoc(declaration: DeclarationDescriptor): KDocTag? {
|
||||
if (declaration is DeclarationDescriptorWithSource) {
|
||||
var psiDeclaration = (declaration.source as? PsiSourceElement)?.psi?.navigationElement
|
||||
// KDoc for primary constructor is located inside of its class KDoc
|
||||
if (psiDeclaration is KtPrimaryConstructor) {
|
||||
psiDeclaration = psiDeclaration.getContainingClassOrObject()
|
||||
}
|
||||
|
||||
if (psiDeclaration is KtDeclaration) {
|
||||
val kdoc = psiDeclaration.docComment
|
||||
if (kdoc != null) {
|
||||
if (declaration is ConstructorDescriptor) {
|
||||
// ConstructorDescriptor resolves to the same JetDeclaration
|
||||
val constructorSection = kdoc.findSectionByTag(KDocKnownTag.CONSTRUCTOR)
|
||||
if (constructorSection != null) {
|
||||
return constructorSection
|
||||
}
|
||||
}
|
||||
return kdoc.getDefaultSection()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is PropertyDescriptor) {
|
||||
val containingClassDescriptor = declaration.containingDeclaration as? ClassDescriptor
|
||||
if (containingClassDescriptor != null) {
|
||||
val classKDoc = findKDoc(containingClassDescriptor)?.getParentOfType<KDoc>(false)
|
||||
if (classKDoc != null) {
|
||||
val propertySection = classKDoc.findSectionByTag(KDocKnownTag.PROPERTY,
|
||||
declaration.getName().asString())
|
||||
if (propertySection != null) {
|
||||
return propertySection
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration is CallableDescriptor) {
|
||||
for (baseDescriptor in declaration.overriddenDescriptors) {
|
||||
val baseKDoc = findKDoc(baseDescriptor.original)
|
||||
if (baseKDoc != null) {
|
||||
return baseKDoc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -18,23 +18,13 @@ package org.jetbrains.kotlin.idea.kdoc
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.references.KtMultiReference
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
|
||||
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.memberScopeAsImportingScope
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
|
||||
class KDocReference(element: KDocName): KtMultiReference<KDocName>(element) {
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
@@ -63,126 +53,3 @@ class KDocReference(element: KDocName): KtMultiReference<KDocName>(element) {
|
||||
|
||||
override fun getCanonicalText(): String = element.getNameText()
|
||||
}
|
||||
|
||||
fun resolveKDocLink(resolutionFacade: ResolutionFacade,
|
||||
fromDescriptor: DeclarationDescriptor,
|
||||
fromSubjectOfTag: KDocTag?,
|
||||
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
|
||||
if (fromSubjectOfTag?.knownTag == KDocKnownTag.PARAM) {
|
||||
return resolveParamLink(fromDescriptor, qualifiedName)
|
||||
}
|
||||
|
||||
// Try to find a matching local descriptor (parameter or type parameter) first.
|
||||
if (qualifiedName.size == 1) {
|
||||
val localResult = resolveInLocalScope(fromDescriptor, qualifiedName.single(), resolutionFacade)
|
||||
if (!localResult.isEmpty()) {
|
||||
return localResult
|
||||
}
|
||||
}
|
||||
|
||||
var result: Collection<DeclarationDescriptor> = listOf(fromDescriptor)
|
||||
qualifiedName.forEach { nameComponent ->
|
||||
val scope = getResolutionScope(resolutionFacade, result.singleOrNull() ?: return emptyList())
|
||||
result = scope.collectDescriptorsFiltered(nameFilter = { it.asString() == nameComponent})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun resolveInLocalScope(fromDescriptor: DeclarationDescriptor,
|
||||
name: String,
|
||||
resolutionFacade: ResolutionFacade): List<DeclarationDescriptor> {
|
||||
val scope = getResolutionScope(resolutionFacade, fromDescriptor)
|
||||
return scope.collectDescriptorsFiltered(nameFilter = { it.asString() == name }).filter {
|
||||
it.containingDeclaration == fromDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
|
||||
// TODO resolve parameters of functions passed as parameters
|
||||
when (fromDescriptor) {
|
||||
is CallableDescriptor ->
|
||||
return fromDescriptor.valueParameters + fromDescriptor.typeParameters
|
||||
is ClassifierDescriptor -> {
|
||||
val typeParams = fromDescriptor.typeConstructor.parameters
|
||||
if (fromDescriptor is ClassDescriptor) {
|
||||
val constructorDescriptor = fromDescriptor.unsubstitutedPrimaryConstructor
|
||||
if (constructorDescriptor != null) {
|
||||
return typeParams + constructorDescriptor.valueParameters
|
||||
}
|
||||
}
|
||||
return typeParams
|
||||
}
|
||||
}
|
||||
|
||||
return listOf()
|
||||
}
|
||||
|
||||
private fun resolveParamLink(fromDescriptor: DeclarationDescriptor, qualifiedName: List<String>): List<DeclarationDescriptor> {
|
||||
val name = qualifiedName.singleOrNull() ?: return listOf()
|
||||
return getParamDescriptors(fromDescriptor).filter { it.name.asString() == name }
|
||||
}
|
||||
|
||||
private fun getPackageInnerScope(descriptor: PackageFragmentDescriptor): MemberScope {
|
||||
return descriptor.containingDeclaration.getPackage(descriptor.fqName).memberScope
|
||||
}
|
||||
|
||||
private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescriptor): LexicalScope {
|
||||
|
||||
val headerScope = LexicalScopeImpl(outerScope, descriptor, false, descriptor.thisAsReceiverParameter,
|
||||
LexicalScopeKind.SYNTHETIC) {
|
||||
for (typeParameter in descriptor.declaredTypeParameters) {
|
||||
addClassifierDescriptor(typeParameter)
|
||||
}
|
||||
for (constructor in descriptor.constructors) {
|
||||
addFunctionDescriptor(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
val scopeChain = arrayListOf(descriptor.defaultType.memberScope,
|
||||
descriptor.staticScope)
|
||||
|
||||
descriptor.companionObjectDescriptor?.let {
|
||||
scopeChain.add(it.defaultType.memberScope)
|
||||
}
|
||||
|
||||
return LexicalChainedScope(headerScope, descriptor, false, null,
|
||||
LexicalScopeKind.SYNTHETIC,
|
||||
scopeChain)
|
||||
}
|
||||
|
||||
fun getResolutionScope(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LexicalScope {
|
||||
return when (descriptor) {
|
||||
is PackageFragmentDescriptor ->
|
||||
LexicalScope.empty(getPackageInnerScope(descriptor).memberScopeAsImportingScope(), descriptor)
|
||||
|
||||
is PackageViewDescriptor ->
|
||||
LexicalScope.empty(descriptor.memberScope.memberScopeAsImportingScope(), descriptor)
|
||||
|
||||
is ClassDescriptor ->
|
||||
getClassInnerScope(getOuterScope(descriptor, resolutionFacade), descriptor)
|
||||
|
||||
is FunctionDescriptor ->
|
||||
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(descriptor, resolutionFacade),
|
||||
descriptor, LocalRedeclarationChecker.DO_NOTHING)
|
||||
|
||||
is PropertyDescriptor ->
|
||||
ScopeUtils.makeScopeForPropertyHeader(getOuterScope(descriptor, resolutionFacade), descriptor)
|
||||
|
||||
is DeclarationDescriptorNonRoot ->
|
||||
getOuterScope(descriptor, resolutionFacade)
|
||||
|
||||
else -> throw IllegalArgumentException("Cannot find resolution scope for root $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, resolutionFacade: ResolutionFacade): LexicalScope {
|
||||
val parent = descriptor.containingDeclaration
|
||||
if (parent is PackageFragmentDescriptor) {
|
||||
val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile
|
||||
if (containingFile != null) {
|
||||
return resolutionFacade.getFileResolutionScope(containingFile)
|
||||
}
|
||||
}
|
||||
return getResolutionScope(resolutionFacade, parent!!)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user