K2: Add extension point for additional KDoc resolution

Similar to K1 KDocLinkResolutionService used by Fe10KDocReference (to
support additional KDoc resolution), this commit adds K2 counterpart
AdditionalKDocResolutionProvider and uses it for KDocReferenceResolver.

^KT-62187
This commit is contained in:
Jaebaek Seo
2023-09-21 17:44:22 -07:00
committed by Space Team
parent 34ea0678ae
commit a6c432587f
3 changed files with 79 additions and 13 deletions
@@ -10,12 +10,13 @@ import org.jetbrains.kotlin.analysis.api.components.KtScopeContext
import org.jetbrains.kotlin.analysis.api.components.KtScopeKind
import org.jetbrains.kotlin.analysis.api.scopes.KtScope
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
import org.jetbrains.kotlin.analysis.utils.printer.parentsOfType
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import kotlin.reflect.KClass
@@ -82,6 +83,7 @@ internal object KDocReferenceResolver {
getExtensionReceiverSymbolByThisQualifier(fqName, contextElement).ifNotEmpty { return this }
(getSymbolsFromScopes(fqName, contextElement) + listOfNotNull(getPackageSymbolIfPackageExists(fqName))).ifNotEmpty { return this }
getNonImportedSymbolsByFullyQualifiedName(fqName).ifNotEmpty { return this }
AdditionalKDocResolutionProvider.resolveKdocFqName(fqName, contextElement).ifNotEmpty { return this }
return emptyList()
}
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.analysis.api.impl.base.java.source.JavaElementSource
import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
import org.jetbrains.kotlin.analysis.api.symbols.AdditionalKDocResolutionProvider
import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProvider
import org.jetbrains.kotlin.analysis.decompiler.psi.BuiltInsVirtualFileProviderCliImpl
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
@@ -141,15 +142,26 @@ object StandaloneProjectFactory {
) {
val applicationArea = applicationEnvironment.application.extensionArea
if (applicationArea.hasExtensionPoint(ClassTypePointerFactory.EP_NAME)) return
KotlinCoreEnvironment.underApplicationLock {
if (applicationArea.hasExtensionPoint(ClassTypePointerFactory.EP_NAME)) return@underApplicationLock
CoreApplicationEnvironment.registerApplicationExtensionPoint(
ClassTypePointerFactory.EP_NAME,
ClassTypePointerFactory::class.java
)
applicationArea.getExtensionPoint(ClassTypePointerFactory.EP_NAME)
.registerExtension(PsiClassReferenceTypePointerFactory(), applicationDisposable)
if (!applicationArea.hasExtensionPoint(AdditionalKDocResolutionProvider.EP_NAME)) {
KotlinCoreEnvironment.underApplicationLock {
if (applicationArea.hasExtensionPoint(AdditionalKDocResolutionProvider.EP_NAME)) return@underApplicationLock
CoreApplicationEnvironment.registerApplicationExtensionPoint(
AdditionalKDocResolutionProvider.EP_NAME,
AdditionalKDocResolutionProvider::class.java
)
}
}
if (!applicationArea.hasExtensionPoint(ClassTypePointerFactory.EP_NAME)) {
KotlinCoreEnvironment.underApplicationLock {
if (applicationArea.hasExtensionPoint(ClassTypePointerFactory.EP_NAME)) return@underApplicationLock
CoreApplicationEnvironment.registerApplicationExtensionPoint(
ClassTypePointerFactory.EP_NAME,
ClassTypePointerFactory::class.java
)
applicationArea.getExtensionPoint(ClassTypePointerFactory.EP_NAME)
.registerExtension(PsiClassReferenceTypePointerFactory(), applicationDisposable)
}
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.api.symbols
import com.intellij.openapi.extensions.ExtensionPointName
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtElement
/**
* An extension point to provide additional symbols for a KDoc reference. KDoc link resolution will use symbols returned by this EP
* only if the real resolution was unsuccessful. You can use this EP by creating a class implementing this interface.
* For example, let's assume that you want to return symbol `fun foo() = 3` for the following KDoc resolution:
*
* ```
* package com.example
* fun foo() = 3
* /**
* * [this.is.not.com.example.fo<caret>o] is not the above `com.example.foo`, but you want to resolve it to the above `com.example.foo`.
* */
* fun bar() = 7
* ```
*
* You can create
*
* ```
* class AdditionalKDocResolutionProviderBasedOnNameMatch : AdditionalKDocResolutionProvider {
* context(KtAnalysisSession)
* override fun resolveKdocFqName(fqName: FqName, contextElement: KtElement): Collection<KtSymbol> =
* contextElement.containingKtFile.declarations.filter { it.name == fqName.shortName().asString() }.map { it.getSymbol() }
* }
* ```
*/
public interface AdditionalKDocResolutionProvider {
/**
* This function must return additional symbols for [contextElement] in KDoc.
*/
context(KtAnalysisSession)
public fun resolveKdocFqName(fqName: FqName, contextElement: KtElement): Collection<KtSymbol>
public companion object {
public val EP_NAME: ExtensionPointName<AdditionalKDocResolutionProvider> =
ExtensionPointName<AdditionalKDocResolutionProvider>("org.jetbrains.kotlin.analysis.additionalKDocResolutionProvider")
context(KtAnalysisSession)
public fun resolveKdocFqName(fqName: FqName, contextElement: KtElement): Collection<KtSymbol> =
EP_NAME.extensions.flatMap { it.resolveKdocFqName(fqName, contextElement) }
}
}