[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) {
|
if (symbol.isLocal) {
|
||||||
val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol)
|
val isCrossingInlineBounds = isCrossingInlineBounds(element, symbol)
|
||||||
val capturedValue = when {
|
val capturedValue = when {
|
||||||
|
symbol.fir.foreignValueMarker == true -> CodeFragmentCapturedValue.ForeignValue(symbol.name, isCrossingInlineBounds)
|
||||||
symbol.hasDelegate -> CodeFragmentCapturedValue.LocalDelegate(symbol.name, symbol.isMutated, isCrossingInlineBounds)
|
symbol.hasDelegate -> CodeFragmentCapturedValue.LocalDelegate(symbol.name, symbol.isMutated, isCrossingInlineBounds)
|
||||||
else -> CodeFragmentCapturedValue.Local(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.api.resolve.extensions.KtResolveExtensionProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
|
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.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.fir.caches.FirThreadSafeCachesFactory
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdePredicateBasedProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdePredicateBasedProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdeRegisteredPluginAnnotations
|
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.FirExtensionRegistrarAdapter
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
|
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
|
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.FirSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
|
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
|
||||||
import org.jetbrains.kotlin.load.java.createJavaClassFinder
|
|
||||||
|
|
||||||
@SessionConfiguration
|
@SessionConfiguration
|
||||||
internal fun LLFirSession.registerIdeComponents(project: Project) {
|
internal fun LLFirSession.registerIdeComponents(project: Project) {
|
||||||
@@ -45,6 +43,7 @@ internal fun LLFirSession.registerIdeComponents(project: Project) {
|
|||||||
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
||||||
register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider())
|
register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider())
|
||||||
register(FirExceptionHandler::class, LLFirExceptionHandler)
|
register(FirExceptionHandler::class, LLFirExceptionHandler)
|
||||||
|
register(CodeFragmentScopeProvider::class, CodeFragmentScopeProvider(this))
|
||||||
createResolveExtensionTool()?.let {
|
createResolveExtensionTool()?.let {
|
||||||
register(LLFirResolveExtensionTool::class, it)
|
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.LLFirWholeFileResolveTarget
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget
|
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.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.element.builder.getNonLocalContainingOrThisDeclaration
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
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 module = firCodeFragment.llFirModuleData.ktModule
|
||||||
val resolveSession = module.getFirResolveSession(ktCodeFragment.project) as LLFirResolvableResolveSession
|
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 contextPsiElement = ktCodeFragment.context
|
||||||
val contextKtFile = contextPsiElement?.containingFile as? KtFile
|
val contextKtFile = contextPsiElement?.containingFile as? KtFile
|
||||||
|
|
||||||
@@ -189,9 +195,9 @@ private class LLFirBodyTargetResolver(
|
|||||||
val elementContext = contextProvider[contextPsiElement, ContextCollector.ContextKind.BODY]
|
val elementContext = contextProvider[contextPsiElement, ContextCollector.ContextKind.BODY]
|
||||||
?: contextParentKtElements.firstNotNullOf { contextProvider[it, ContextCollector.ContextKind.SELF] }
|
?: contextParentKtElements.firstNotNullOf { contextProvider[it, ContextCollector.ContextKind.SELF] }
|
||||||
|
|
||||||
LLFirCodeFragmentContext(elementContext.towerDataContext, elementContext.smartCasts)
|
LLFirCodeFragmentContext(elementContext.towerDataContext.withExtraScopes(), elementContext.smartCasts)
|
||||||
} else {
|
} else {
|
||||||
val towerDataContext = FirTowerDataContext()
|
val towerDataContext = FirTowerDataContext().withExtraScopes()
|
||||||
LLFirCodeFragmentContext(towerDataContext, emptyMap())
|
LLFirCodeFragmentContext(towerDataContext, emptyMap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user