KT-14710 Sample references aren't resolved in IDE

#KT-14710 fixed
This commit is contained in:
Simon Ogorodnik
2017-01-17 18:18:31 +03:00
committed by Simon Ogorodnik
parent cd73d17bd4
commit bf3d4471cd
8 changed files with 232 additions and 29 deletions
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2017 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 com.intellij.openapi.components.ServiceManager
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.resolve.BindingContext
interface SampleResolutionService {
fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor>
companion object {
/**
* It's internal implementation, please use [resolveKDocSampleLink], or [resolveKDocLink]
*/
internal fun resolveSample(context: BindingContext, fromDescriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, qualifiedName: List<String>): Collection<DeclarationDescriptor> {
val instance = ServiceManager.getService(resolutionFacade.project, SampleResolutionService::class.java)
return instance?.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName) ?: emptyList()
}
}
}
@@ -35,17 +35,64 @@ 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
import org.jetbrains.kotlin.utils.ifEmpty
fun resolveKDocLink(context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
fromSubjectOfTag: KDocTag?,
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
qualifiedName: List<String>): Collection<DeclarationDescriptor> =
when (fromSubjectOfTag?.knownTag) {
KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName)
KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName)
else -> resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName)
}
if (fromSubjectOfTag?.knownTag == KDocKnownTag.PARAM) {
return resolveParamLink(fromDescriptor, qualifiedName)
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 }
}
fun resolveKDocSampleLink(context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
val resolvedViaService = SampleResolutionService.resolveSample(context, fromDescriptor, resolutionFacade, qualifiedName)
if (resolvedViaService.isNotEmpty()) return resolvedViaService
return resolveDefaultKDocLink(context, resolutionFacade, fromDescriptor, qualifiedName)
}
private fun resolveDefaultKDocLink(context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
val scope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor)
if (qualifiedName.size == 1) {
@@ -82,31 +129,6 @@ fun resolveKDocLink(context: BindingContext,
return listOf(descriptor)
}
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
}