[LL API] Support '_DebugLabel's in code fragments
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.providers
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
|
||||
public interface ForeignValueProviderService {
|
||||
public fun getForeignValues(codeFragment: KtCodeFragment): Map<String, String>
|
||||
|
||||
public companion object {
|
||||
public fun getInstance(): ForeignValueProviderService? {
|
||||
return ApplicationManager.getApplication().getService(ForeignValueProviderService::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -180,6 +180,7 @@ private class CodeFragmentCapturedValueVisitor(
|
||||
if (symbol.isLocal) {
|
||||
val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol)
|
||||
val capturedValue = when {
|
||||
symbol.fir.foreignValueMarker == true -> CodeFragmentCapturedValue.ForeignValue(symbol.name, isCrossingInlineBounds)
|
||||
symbol.hasDelegate -> CodeFragmentCapturedValue.LocalDelegate(symbol.name, symbol.isMutated, isCrossingInlineBounds)
|
||||
else -> CodeFragmentCapturedValue.Local(symbol.name, symbol.isMutated, isCrossingInlineBounds)
|
||||
}
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.compile
|
||||
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import org.jetbrains.kotlin.analysis.providers.ForeignValueProviderService
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.jvm.buildJavaTypeRef
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.source.JavaElementSourceFactory
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
val FirSession.codeFragmentScopeProvider: CodeFragmentScopeProvider by FirSession.sessionComponentAccessor()
|
||||
|
||||
private object ForeignValueMarkerDataKey : FirDeclarationDataKey()
|
||||
|
||||
var FirProperty.foreignValueMarker: Boolean? by FirDeclarationDataRegistry.data(ForeignValueMarkerDataKey)
|
||||
|
||||
class CodeFragmentScopeProvider(private val session: FirSession) : FirSessionComponent {
|
||||
private val foreignValueProvider = ForeignValueProviderService.getInstance()
|
||||
|
||||
private val typeCache = session.firCachesFactory.createCache<String, FirTypeRef, KtCodeFragment> { typeDescriptor, ktCodeFragment ->
|
||||
getPrimitiveType(typeDescriptor, session)?.let { return@createCache it }
|
||||
|
||||
val project = ktCodeFragment.project
|
||||
val javaElementSourceFactory = JavaElementSourceFactory.getInstance(project)
|
||||
|
||||
val signatureIterator = StringCharacterIterator(typeDescriptor)
|
||||
val typeString = SignatureParsing.parseTypeString(signatureIterator, StubBuildingVisitor.GUESSING_MAPPER)
|
||||
val psiType = ClsTypeElementImpl(ktCodeFragment, typeString, '\u0000').type
|
||||
val javaType = JavaTypeImpl.create(psiType, javaElementSourceFactory.createTypeSource(psiType))
|
||||
|
||||
val javaTypeRef = buildJavaTypeRef {
|
||||
annotationBuilder = { emptyList() }
|
||||
type = javaType
|
||||
}
|
||||
|
||||
javaTypeRef.resolveIfJavaType(session, JavaTypeParameterStack.EMPTY)
|
||||
}
|
||||
|
||||
fun getExtraScopes(codeFragment: KtCodeFragment): List<FirLocalScope> {
|
||||
val foreignValues = foreignValueProvider?.getForeignValues(codeFragment)?.takeUnless { it.isEmpty() } ?: return emptyList()
|
||||
return listOf(getForeignValuesScope(codeFragment, foreignValues))
|
||||
}
|
||||
|
||||
private fun getForeignValuesScope(ktCodeFragment: KtCodeFragment, foreignValues: Map<String, String>): FirLocalScope {
|
||||
var result = FirLocalScope(session)
|
||||
|
||||
for ((variableNameString, typeDescriptor) in foreignValues) {
|
||||
val variableName = Name.identifier(variableNameString)
|
||||
|
||||
val variable = buildProperty {
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
moduleData = session.moduleData
|
||||
origin = FirDeclarationOrigin.Source
|
||||
status = FirDeclarationStatusImpl(Visibilities.Local, Modality.FINAL)
|
||||
returnTypeRef = typeCache.getValue(typeDescriptor, ktCodeFragment)
|
||||
deprecationsProvider = EmptyDeprecationsProvider
|
||||
name = variableName
|
||||
isVar = false
|
||||
symbol = FirPropertySymbol(variableName)
|
||||
isLocal = true
|
||||
}
|
||||
|
||||
variable.foreignValueMarker = true
|
||||
|
||||
result = result.storeVariable(variable, session)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPrimitiveType(typeDescriptor: String, session: FirSession): FirTypeRef? {
|
||||
val asmType = Type.getType(typeDescriptor)
|
||||
return when (asmType.sort) {
|
||||
Type.VOID -> session.builtinTypes.unitType
|
||||
Type.BOOLEAN -> session.builtinTypes.booleanType
|
||||
Type.CHAR -> session.builtinTypes.charType
|
||||
Type.BYTE -> session.builtinTypes.byteType
|
||||
Type.SHORT -> session.builtinTypes.shortType
|
||||
Type.INT -> session.builtinTypes.intType
|
||||
Type.FLOAT -> session.builtinTypes.floatType
|
||||
Type.LONG -> session.builtinTypes.longType
|
||||
Type.DOUBLE -> session.builtinTypes.doubleType
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -10,6 +10,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentScopeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdePredicateBasedProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdeRegisteredPluginAnnotations
|
||||
@@ -32,12 +33,9 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
|
||||
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaFacadeForSource
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
|
||||
import org.jetbrains.kotlin.load.java.createJavaClassFinder
|
||||
|
||||
@SessionConfiguration
|
||||
internal fun LLFirSession.registerIdeComponents(project: Project) {
|
||||
@@ -45,6 +43,7 @@ internal fun LLFirSession.registerIdeComponents(project: Project) {
|
||||
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
||||
register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider())
|
||||
register(FirExceptionHandler::class, LLFirExceptionHandler)
|
||||
register(CodeFragmentScopeProvider::class, CodeFragmentScopeProvider(this))
|
||||
createResolveExtensionTool()?.let {
|
||||
register(LLFirResolveExtensionTool::class, it)
|
||||
}
|
||||
|
||||
+8
-2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveT
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeFileResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.codeFragmentScopeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
@@ -169,6 +170,11 @@ private class LLFirBodyTargetResolver(
|
||||
val module = firCodeFragment.llFirModuleData.ktModule
|
||||
val resolveSession = module.getFirResolveSession(ktCodeFragment.project) as LLFirResolvableResolveSession
|
||||
|
||||
fun FirTowerDataContext.withExtraScopes(): FirTowerDataContext {
|
||||
return resolveSession.useSiteFirSession.codeFragmentScopeProvider.getExtraScopes(ktCodeFragment)
|
||||
.fold(this) { context, scope -> context.addLocalScope(scope) }
|
||||
}
|
||||
|
||||
val contextPsiElement = ktCodeFragment.context
|
||||
val contextKtFile = contextPsiElement?.containingFile as? KtFile
|
||||
|
||||
@@ -189,9 +195,9 @@ private class LLFirBodyTargetResolver(
|
||||
val elementContext = contextProvider[contextPsiElement, ContextCollector.ContextKind.BODY]
|
||||
?: contextParentKtElements.firstNotNullOf { contextProvider[it, ContextCollector.ContextKind.SELF] }
|
||||
|
||||
LLFirCodeFragmentContext(elementContext.towerDataContext, elementContext.smartCasts)
|
||||
LLFirCodeFragmentContext(elementContext.towerDataContext.withExtraScopes(), elementContext.smartCasts)
|
||||
} else {
|
||||
val towerDataContext = FirTowerDataContext()
|
||||
val towerDataContext = FirTowerDataContext().withExtraScopes()
|
||||
LLFirCodeFragmentContext(towerDataContext, emptyMap())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user