Rewritten KDoc-link resolve and completion to work more reasonably

This commit is contained in:
Valentin Kipyatkov
2017-08-08 09:57:47 +03:00
parent 998814b1a1
commit e52c3b4c81
19 changed files with 333 additions and 143 deletions
@@ -20,11 +20,13 @@ import com.intellij.openapi.components.ServiceManager
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.CallType
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -34,18 +36,22 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.*
import org.jetbrains.kotlin.resolve.scopes.utils.*
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
fun resolveKDocLink(context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
fromSubjectOfTag: KDocTag?,
qualifiedName: List<String>): Collection<DeclarationDescriptor> =
fun resolveKDocLink(
context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
fromSubjectOfTag: KDocTag?,
qualifiedName: List<String>
): Collection<DeclarationDescriptor> =
when (fromSubjectOfTag?.knownTag) {
KDocKnownTag.PARAM -> resolveParamLink(fromDescriptor, qualifiedName)
KDocKnownTag.SAMPLE -> resolveKDocSampleLink(context, resolutionFacade, fromDescriptor, qualifiedName)
@@ -56,8 +62,10 @@ fun resolveKDocLink(context: BindingContext,
fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<DeclarationDescriptor> {
// TODO resolve parameters of functions passed as parameters
when (fromDescriptor) {
is CallableDescriptor ->
is CallableDescriptor -> {
return fromDescriptor.valueParameters + fromDescriptor.typeParameters
}
is ClassifierDescriptor -> {
val typeParams = fromDescriptor.typeConstructor.parameters
if (fromDescriptor is ClassDescriptor) {
@@ -68,20 +76,24 @@ fun getParamDescriptors(fromDescriptor: DeclarationDescriptor): List<Declaration
}
return typeParams
}
}
return listOf()
else -> {
return emptyList()
}
}
}
private fun resolveParamLink(fromDescriptor: DeclarationDescriptor, qualifiedName: List<String>): List<DeclarationDescriptor> {
val name = qualifiedName.singleOrNull() ?: return listOf()
val name = qualifiedName.singleOrNull() ?: return emptyList()
return getParamDescriptors(fromDescriptor).filter { it.name.asString() == name }
}
fun resolveKDocSampleLink(context: BindingContext,
resolutionFacade: ResolutionFacade,
fromDescriptor: DeclarationDescriptor,
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
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
@@ -96,19 +108,21 @@ private fun resolveDefaultKDocLink(
qualifiedName: List<String>
): Collection<DeclarationDescriptor> {
val scope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor)
val contextScope = getKDocLinkResolutionScope(resolutionFacade, fromDescriptor)
if (qualifiedName.size == 1) {
val shortName = Name.identifier(qualifiedName.single())
val descriptorsByName = SmartList<DeclarationDescriptor>()
scope.collectAllByName(shortName, descriptorsByName)
descriptorsByName.addIfNotNull(contextScope.findClassifier(shortName, NoLookupLocation.FROM_IDE))
descriptorsByName.addIfNotNull(contextScope.findPackage(shortName))
descriptorsByName.addAll(contextScope.collectFunctions(shortName, NoLookupLocation.FROM_IDE))
descriptorsByName.addAll(contextScope.collectVariables(shortName, NoLookupLocation.FROM_IDE))
// Try to find a matching local descriptor (parameter or type parameter) first
val localDescriptors = descriptorsByName.filter { it.containingDeclaration == fromDescriptor }
if (localDescriptors.isNotEmpty()) return localDescriptors
descriptorsByName.addIfNotNull(fromDescriptor.module.getPackage(FqName.topLevel(shortName)))
return descriptorsByName
}
@@ -120,23 +134,17 @@ private fun resolveDefaultKDocLink(
// TODO escape identifiers
val codeFragment = factory.createExpressionCodeFragment(qualifiedName.joinToString("."), contextElement)
val qualifiedExpression = codeFragment.findElementAt(codeFragment.textLength - 1)?.getStrictParentOfType<KtQualifiedExpression>() ?: return emptyList()
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(qualifiedExpression, scope, context)
val (descriptor, memberName) = qualifiedExpressionResolver.resolveClassOrPackageInQualifiedExpression(qualifiedExpression, contextScope, context)
if (descriptor == null) return emptyList()
if (memberName != null) {
val memberScope = getKDocLinkResolutionScope(resolutionFacade, descriptor)
return memberScope.collectAllByName(memberName)
val memberScope = getKDocLinkMemberScope(descriptor, contextScope)
return memberScope.getContributedFunctions(memberName, NoLookupLocation.FROM_IDE) +
memberScope.getContributedVariables(memberName, NoLookupLocation.FROM_IDE) +
listOfNotNull(memberScope.getContributedClassifier(memberName, NoLookupLocation.FROM_IDE))
}
return listOf(descriptor)
}
private fun LexicalScope.collectAllByName(shortName: Name, toCollection: MutableCollection<DeclarationDescriptor> = SmartList()): Collection<DeclarationDescriptor> {
toCollection.addIfNotNull(findClassifier(shortName, NoLookupLocation.FROM_IDE))
toCollection.addIfNotNull(findPackage(shortName))
toCollection.addAll(collectFunctions(shortName, NoLookupLocation.FROM_IDE))
toCollection.addAll(collectVariables(shortName, NoLookupLocation.FROM_IDE))
return toCollection
}
private fun getPackageInnerScope(descriptor: PackageFragmentDescriptor): MemberScope {
return descriptor.containingDeclaration.getPackage(descriptor.fqName).memberScope
}
@@ -145,60 +153,108 @@ private fun getClassInnerScope(outerScope: LexicalScope, descriptor: ClassDescri
val headerScope = LexicalScopeImpl(outerScope, descriptor, false, descriptor.thisAsReceiverParameter,
LexicalScopeKind.SYNTHETIC) {
for (typeParameter in descriptor.declaredTypeParameters) {
addClassifierDescriptor(typeParameter)
}
for (constructor in descriptor.constructors) {
addFunctionDescriptor(constructor)
}
descriptor.declaredTypeParameters.forEach { addClassifierDescriptor(it) }
descriptor.constructors.forEach { addFunctionDescriptor(it) }
}
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)
val scopeChain = listOfNotNull(
descriptor.defaultType.memberScope,
descriptor.staticScope,
descriptor.companionObjectDescriptor?.defaultType?.memberScope
)
return LexicalChainedScope(headerScope, descriptor, false, null, LexicalScopeKind.SYNTHETIC, scopeChain)
}
fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LexicalScope {
return when (descriptor) {
is PackageFragmentDescriptor ->
LexicalScope.Base(getPackageInnerScope(descriptor).memberScopeAsImportingScope(), descriptor)
is PackageViewDescriptor ->
LexicalScope.Base(descriptor.memberScope.memberScopeAsImportingScope(), descriptor)
fun getKDocLinkResolutionScope(resolutionFacade: ResolutionFacade, contextDescriptor: DeclarationDescriptor): LexicalScope {
return when (contextDescriptor) {
is ClassDescriptor ->
getClassInnerScope(getOuterScope(descriptor, resolutionFacade), descriptor)
getClassInnerScope(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
is FunctionDescriptor ->
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(descriptor, resolutionFacade),
descriptor, LocalRedeclarationChecker.DO_NOTHING)
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(contextDescriptor, resolutionFacade),
contextDescriptor, LocalRedeclarationChecker.DO_NOTHING)
is PropertyDescriptor ->
ScopeUtils.makeScopeForPropertyHeader(getOuterScope(descriptor, resolutionFacade), descriptor)
ScopeUtils.makeScopeForPropertyHeader(getOuterScope(contextDescriptor, resolutionFacade), contextDescriptor)
is DeclarationDescriptorNonRoot ->
getOuterScope(descriptor, resolutionFacade)
getOuterScope(contextDescriptor, resolutionFacade)
else -> throw IllegalArgumentException("Cannot find resolution scope for root $descriptor")
else -> throw IllegalArgumentException("Cannot find resolution scope for root $contextDescriptor")
}
}
private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, resolutionFacade: ResolutionFacade): LexicalScope {
val parent = descriptor.containingDeclaration
val parent = descriptor.containingDeclaration!!
if (parent is PackageFragmentDescriptor) {
val containingFile = (descriptor.source as? PsiSourceElement)?.psi?.containingFile as? KtFile
if (containingFile != null) {
val kotlinCacheService = ServiceManager.getService(containingFile.project, KotlinCacheService::class.java)
val facadeToUse = kotlinCacheService?.getResolutionFacade(listOf(containingFile)) ?: resolutionFacade
return facadeToUse.getFileResolutionScope(containingFile)
}
?: return LexicalScope.Base(ImportingScope.Empty, parent)
val kotlinCacheService = ServiceManager.getService(containingFile.project, KotlinCacheService::class.java)
val facadeToUse = kotlinCacheService?.getResolutionFacade(listOf(containingFile)) ?: resolutionFacade
return facadeToUse.getFileResolutionScope(containingFile)
}
else {
return getKDocLinkResolutionScope(resolutionFacade, parent)
}
}
fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: LexicalScope): MemberScope {
return when (descriptor) {
is PackageFragmentDescriptor -> getPackageInnerScope(descriptor)
is PackageViewDescriptor -> descriptor.memberScope
is ClassDescriptor -> {
ChainedMemberScope("Member scope for KDoc resolve", listOfNotNull(
descriptor.unsubstitutedMemberScope,
descriptor.staticScope,
descriptor.companionObjectDescriptor?.unsubstitutedMemberScope,
ExtensionsScope(descriptor, contextScope)
))
}
else -> MemberScope.Empty
}
}
private class ExtensionsScope(
private val receiverClass: ClassDescriptor,
private val contextScope: LexicalScope
) : MemberScope {
private val receiverTypes = listOf(receiverClass.defaultType)
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
return contextScope.collectFunctions(name, location)
.flatMap { if (it is SimpleFunctionDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
}
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
return contextScope.collectVariables(name, location)
.flatMap { if (it is PropertyDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
}
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
if (DescriptorKindExclude.Extensions in kindFilter.excludes) return emptyList()
return contextScope.collectDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.NonExtensions, nameFilter, changeNamesForAliased = true)
.flatMap { if (it is CallableDescriptor && it.isExtension) it.substituteExtensionIfCallable(receiverTypes, CallType.DOT) else emptyList() }
}
override fun getFunctionNames(): Set<Name> {
return getContributedDescriptors(kindFilter = DescriptorKindFilter.FUNCTIONS)
.map { it.name }
.toSet()
}
override fun getVariableNames(): Set<Name> {
return getContributedDescriptors(kindFilter = DescriptorKindFilter.VARIABLES)
.map { it.name }
.toSet()
}
override fun printScopeStructure(p: Printer) {
p.println("Extensions for ${receiverClass.name} in:")
contextScope.printStructure(p)
}
return getKDocLinkResolutionScope(resolutionFacade, parent!!)
}
@@ -23,22 +23,17 @@ import com.intellij.codeInsight.lookup.LookupElementDecorator
import com.intellij.patterns.PlatformPatterns.psiElement
import com.intellij.patterns.StandardPatterns
import com.intellij.util.ProcessingContext
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.idea.core.ExpectedInfo
import org.jetbrains.kotlin.idea.kdoc.getKDocLinkMemberScope
import org.jetbrains.kotlin.idea.kdoc.getKDocLinkResolutionScope
import org.jetbrains.kotlin.idea.kdoc.getParamDescriptors
import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink
import org.jetbrains.kotlin.idea.util.CallType
import org.jetbrains.kotlin.idea.util.substituteExtensionIfCallable
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -46,12 +41,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
class KDocCompletionContributor : CompletionContributor() {
init {
@@ -79,6 +70,7 @@ class KDocNameCompletionSession(
toFromOriginalFileMapper: ToFromOriginalFileMapper,
resultSet: CompletionResultSet
) : CompletionSession(CompletionSessionConfiguration(parameters), parameters, toFromOriginalFileMapper, resultSet) {
override val descriptorKindFilter: DescriptorKindFilter? get() = null
override val expectedInfos: Collection<ExpectedInfo> get() = emptyList()
@@ -100,63 +92,28 @@ class KDocNameCompletionSession(
declarationDescriptor: DeclarationDescriptor) {
val section = position.getContainingSection()
val documentedParameters = section.findTagsByName("param").map { it.getSubjectName() }.toSet()
val descriptors = getParamDescriptors(declarationDescriptor)
getParamDescriptors(declarationDescriptor)
.filter { it.name.asString() !in documentedParameters }
descriptors.forEach {
collector.addElement(basicLookupElementFactory.createLookupElement(it, parametersAndTypeGrayed = true))
}
}
private fun collectPackageViewDescriptors(qualifiedLink: List<String>, nameFilter: (Name) -> Boolean): Sequence<PackageViewDescriptor> {
val fqName = FqName.fromSegments(qualifiedLink)
return moduleDescriptor.getSubPackagesOf(fqName, nameFilter).asSequence()
.map { moduleDescriptor.getPackage(it) }
}
private fun collectDescriptorsFromScope(scope: LexicalScope, nameFilter: (Name) -> Boolean, collectFromParentScopes: Boolean): Sequence<DeclarationDescriptor> {
val implicitReceivers = scope.getImplicitReceiversHierarchy().map { it.value }
fun isApplicable(descriptor: DeclarationDescriptor): Boolean {
if (descriptor is CallableDescriptor) {
val extensionReceiver = descriptor.extensionReceiverParameter
if (extensionReceiver != null) {
val substituted = descriptor.substituteExtensionIfCallable(implicitReceivers, bindingContext, DataFlowInfo.EMPTY,
CallType.DEFAULT, moduleDescriptor)
return substituted.isNotEmpty()
.forEach {
collector.addElement(basicLookupElementFactory.createLookupElement(it, parametersAndTypeGrayed = true))
}
}
return true
}
val sequence = when {
collectFromParentScopes -> scope.collectDescriptorsFiltered(nameFilter = nameFilter, changeNamesForAliased = true).asSequence()
scope is LexicalScope.Base -> scope.parent.getContributedDescriptors(nameFilter = nameFilter).asSequence()
else -> scope.getContributedDescriptors(nameFilter = nameFilter).asSequence() +
scope.parent.collectDescriptorsFiltered(nameFilter = nameFilter).asSequence().filter { it.isExtension }
}
return sequence.filter(::isApplicable)
}
private fun collectDescriptorsForLinkCompletion(declarationDescriptor: DeclarationDescriptor, kDocLink: KDocLink): Collection<DeclarationDescriptor> {
val contextScope = getKDocLinkResolutionScope(resolutionFacade, declarationDescriptor)
private fun collectDescriptorsForLinkCompletion(declarationDescriptor: DeclarationDescriptor, kDocLink: KDocLink): Sequence<DeclarationDescriptor> {
val qualifiedLink = kDocLink.getLinkText().split('.').dropLast(1)
val nameFilter = descriptorNameFilter.toNameFilter()
return if (qualifiedLink.isNotEmpty()) {
if (qualifiedLink.isNotEmpty()) {
val parentDescriptors = resolveKDocLink(bindingContext, resolutionFacade, declarationDescriptor, kDocLink.getTagIfSubject(), qualifiedLink)
val childDescriptorsOfPartialLink = parentDescriptors.asSequence().flatMap {
val scope = getKDocLinkResolutionScope(resolutionFacade, it)
collectDescriptorsFromScope(scope, nameFilter, false)
}
(collectPackageViewDescriptors(qualifiedLink, nameFilter) + childDescriptorsOfPartialLink)
return parentDescriptors
.flatMap {
val scope = getKDocLinkMemberScope(it, contextScope)
scope.getContributedDescriptors(nameFilter = nameFilter)
}
}
else {
val scope = getKDocLinkResolutionScope(resolutionFacade, declarationDescriptor)
(collectDescriptorsFromScope(scope, nameFilter, true)
+ collectPackageViewDescriptors(qualifiedLink, nameFilter))
return contextScope.collectDescriptorsFiltered(DescriptorKindFilter.ALL, nameFilter, changeNamesForAliased = true)
}
}
@@ -164,7 +121,7 @@ class KDocNameCompletionSession(
collectDescriptorsForLinkCompletion(declarationDescriptor, kDocLink).forEach {
val element = basicLookupElementFactory.createLookupElement(it, parametersAndTypeGrayed = true)
collector.addElement(object : LookupElementDecorator<LookupElement>(element) {
override fun handleInsert(context: InsertionContext?) {
override fun handleInsert(context: InsertionContext) {
// insert only plain name here, no qualifier/parentheses/etc.
}
})
@@ -0,0 +1,8 @@
import kotlin.text.capitalize as xxx
/**
* [String.x<caret>]
*/
fun foo(){}
// EXIST: { lookupString: "xxx", itemText: "xxx" }
@@ -0,0 +1,7 @@
/**
* [kotlin.<caret>]
*/
fun foo(){}
// EXIST: io
// EXIST: Int
+16 -3
View File
@@ -1,6 +1,10 @@
package a
class B {
interface I
class A : I
class B : I {
/**
* [a.B.<caret>]
*/
@@ -10,11 +14,20 @@ class B {
}
fun B.ext() {
}
val B.extVal: String
get() = ""
fun A.wrongExt(){}
val A.wrongExtVal: String
get() = ""
fun I.extForSuper(){}
// EXIST: ext
// EXIST: extVal
// EXIST: extVal
// ABSENT: wrongExt
// ABSENT: wrongExtVal
// EXIST: extForSuper
+8 -8
View File
@@ -1,19 +1,19 @@
package z
/**
* [<caret>]
* [a<caret>]
*/
fun f(xyzzy: String) {
fun az(ap: String) {
}
fun bar() {
fun aaa() {
}
class Z
class aZ
// EXIST: z
// EXIST: Z
// EXIST: xyzzy
// EXIST: bar
// EXIST: az
// EXIST: aZ
// EXIST: ap
// EXIST: aaa
+5 -4
View File
@@ -1,8 +1,8 @@
class Foo {
/**
* [<caret>]
* [b<caret>]
*/
fun xyzzy() {
fun baz() {
}
@@ -11,8 +11,9 @@ class Foo {
}
}
fun Foo.quux() {
fun Foo.boo() {
}
// EXIST: bar
// EXIST: quux
// EXIST: baz
// EXIST: boo
@@ -0,0 +1,10 @@
class Foo
fun Foo.ext() = ""
/**
* [Foo.ext.<caret>]
*/
fun test() {}
// NOTHING_ELSE
@@ -0,0 +1,9 @@
class Foo
/**
* [Foo.<caret>]
*/
fun test() {}
// ABSENT: test
@@ -3046,6 +3046,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName);
}
@TestMetadata("KDocExtension.kt")
public void testKDocExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/java/importAliases/KDocExtension.kt");
doTest(fileName);
}
@TestMetadata("PrefixUsed.kt")
public void testPrefixUsed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/java/importAliases/PrefixUsed.kt");
@@ -32,6 +32,12 @@ import java.util.regex.Pattern;
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class KDocCompletionTestGenerated extends AbstractJvmBasicCompletionTest {
@TestMetadata("AfterPackageName.kt")
public void testAfterPackageName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/AfterPackageName.kt");
doTest(fileName);
}
public void testAllFilesPresentInKdoc() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/kdoc"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@@ -42,9 +48,9 @@ public class KDocCompletionTestGenerated extends AbstractJvmBasicCompletionTest
doTest(fileName);
}
@TestMetadata("ExtensionsForSubClassFQLink.kt")
public void testExtensionsForSubClassFQLink() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/ExtensionsForSubClassFQLink.kt");
@TestMetadata("ExtensionsForNestedClassFQLink.kt")
public void testExtensionsForNestedClassFQLink() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/ExtensionsForNestedClassFQLink.kt");
doTest(fileName);
}
@@ -90,6 +96,18 @@ public class KDocCompletionTestGenerated extends AbstractJvmBasicCompletionTest
doTest(fileName);
}
@TestMetadata("NoCompletionAfterFunName.kt")
public void testNoCompletionAfterFunName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/NoCompletionAfterFunName.kt");
doTest(fileName);
}
@TestMetadata("NoTopLevelForQualified.kt")
public void testNoTopLevelForQualified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/NoTopLevelForQualified.kt");
doTest(fileName);
}
@TestMetadata("NotTagName.kt")
public void testNotTagName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/kdoc/NotTagName.kt");
+13
View File
@@ -0,0 +1,13 @@
class Foo
class Bar
fun Foo.foo(){}
fun foo(){}
/**
* [Bar.<caret>foo]
*/
fun test() {}
// REF_EMPTY
+10
View File
@@ -0,0 +1,10 @@
import kotlin.io.extension
import java.io.File
/**
* [File.<caret>extension]
*/
fun f() {
}
// REF: (for java.io.File in kotlin.io).extension
+14
View File
@@ -0,0 +1,14 @@
package a
class B {
/**
* [a.B.<caret>ext]
*/
fun member() {
}
}
fun B.ext() {
}
// REF: (for B in a).ext()
+10
View File
@@ -0,0 +1,10 @@
class Foo
fun Foo.foo(){}
/**
* [<caret>foo]
*/
fun test() {}
// REF: (for Foo in <root>).foo()
+14
View File
@@ -0,0 +1,14 @@
package a
class B {
/**
* [a.B.<caret>extVal]
*/
fun member() {
}
}
val B.extVal: String
get() = ""
// REF: (for B in a).extVal
+8
View File
@@ -0,0 +1,8 @@
class Foo
/**
* [Foo.<caret>test]
*/
fun test() {}
// REF_EMPTY
@@ -49,6 +49,12 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest {
doTest(fileName);
}
@TestMetadata("CheckExtensionReceiver.kt")
public void testCheckExtensionReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/CheckExtensionReceiver.kt");
doTest(fileName);
}
@TestMetadata("ClassSelfReference.kt")
public void testClassSelfReference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ClassSelfReference.kt");
@@ -73,6 +79,30 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest {
doTest(fileName);
}
@TestMetadata("ExtensionFromImports.kt")
public void testExtensionFromImports() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ExtensionFromImports.kt");
doTest(fileName);
}
@TestMetadata("ExtensionFun.kt")
public void testExtensionFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ExtensionFun.kt");
doTest(fileName);
}
@TestMetadata("ExtensionNonQualified.kt")
public void testExtensionNonQualified() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ExtensionNonQualified.kt");
doTest(fileName);
}
@TestMetadata("ExtensionVal.kt")
public void testExtensionVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ExtensionVal.kt");
doTest(fileName);
}
@TestMetadata("ImportAliasClass.kt")
public void testImportAliasClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ImportAliasClass.kt");
@@ -85,6 +115,12 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest {
doTest(fileName);
}
@TestMetadata("OnlyMembersFromClass.kt")
public void testOnlyMembersFromClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/OnlyMembersFromClass.kt");
doTest(fileName);
}
@TestMetadata("Overloads.kt")
public void testOverloads() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/resolve/Overloads.kt");