FIR IDE: rework high level API
Make analysis session to always be a receiver parameter
This commit is contained in:
+26
-29
@@ -6,14 +6,13 @@
|
|||||||
package org.jetbrains.kotlin.idea.completion
|
package org.jetbrains.kotlin.idea.completion
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.*
|
import com.intellij.codeInsight.completion.*
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import com.intellij.patterns.PsiJavaPatterns
|
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor
|
import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
@@ -38,40 +37,38 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
|
|||||||
|
|
||||||
val possibleReceiver = nameExpression.getQualifiedExpressionForSelector()?.receiverExpression
|
val possibleReceiver = nameExpression.getQualifiedExpressionForSelector()?.receiverExpression
|
||||||
|
|
||||||
val originalSession = getAnalysisSessionFor(originalFile)
|
with(getAnalysisSessionFor(originalFile).createContextDependentCopy()) {
|
||||||
val sessionForCompletion = originalSession.createContextDependentCopy()
|
val (implicitScopes, implicitReceivers) = originalFile.getScopeContextForPosition(nameExpression)
|
||||||
val scopeProvider = sessionForCompletion.scopeProvider
|
|
||||||
|
|
||||||
val (implicitScopes, implicitReceivers) = scopeProvider.getScopeContextForPosition(originalFile, nameExpression)
|
val typeOfPossibleReceiver = possibleReceiver?.getKtType()
|
||||||
|
val possibleReceiverScope = typeOfPossibleReceiver?.let { it.getTypeScope() }
|
||||||
|
|
||||||
val typeOfPossibleReceiver = possibleReceiver?.let { sessionForCompletion.getKtExpressionType(it) }
|
fun addToCompletion(symbol: KtSymbol) {
|
||||||
val possibleReceiverScope = typeOfPossibleReceiver?.let { sessionForCompletion.scopeProvider.getScopeForType(it) }
|
if (symbol !is KtNamedSymbol) return
|
||||||
|
result.addElement(lookupElementFactory.createLookupElement(symbol))
|
||||||
|
}
|
||||||
|
|
||||||
fun addToCompletion(symbol: KtSymbol) {
|
if (possibleReceiverScope != null) {
|
||||||
if (symbol !is KtNamedSymbol) return
|
val nonExtensionMembers = possibleReceiverScope
|
||||||
result.addElement(lookupElementFactory.createLookupElement(symbol))
|
.getCallableSymbols()
|
||||||
}
|
.filterNot { it.isExtension }
|
||||||
|
|
||||||
if (possibleReceiverScope != null) {
|
val extensionNonMembers = implicitScopes
|
||||||
val nonExtensionMembers = possibleReceiverScope
|
.getCallableSymbols()
|
||||||
.getCallableSymbols()
|
.filter { it.isExtension && it.canBeCalledWith(listOf(typeOfPossibleReceiver)) }
|
||||||
.filterNot { it.isExtension }
|
|
||||||
|
|
||||||
val extensionNonMembers = implicitScopes
|
nonExtensionMembers.forEach(::addToCompletion)
|
||||||
.getCallableSymbols()
|
extensionNonMembers.forEach(::addToCompletion)
|
||||||
.filter { it.isExtension && it.canBeCalledWith(listOf(typeOfPossibleReceiver)) }
|
} else {
|
||||||
|
val extensionNonMembers = implicitScopes
|
||||||
|
.getCallableSymbols()
|
||||||
|
.filter { !it.isExtension || it.canBeCalledWith(implicitReceivers) }
|
||||||
|
|
||||||
nonExtensionMembers.forEach(::addToCompletion)
|
extensionNonMembers.forEach(::addToCompletion)
|
||||||
extensionNonMembers.forEach(::addToCompletion)
|
|
||||||
} else {
|
|
||||||
val extensionNonMembers = implicitScopes
|
|
||||||
.getCallableSymbols()
|
|
||||||
.filter { !it.isExtension || it.canBeCalledWith(implicitReceivers) }
|
|
||||||
|
|
||||||
extensionNonMembers.forEach(::addToCompletion)
|
val availableClasses = implicitScopes.getClassClassLikeSymbols()
|
||||||
|
availableClasses.forEach(::addToCompletion)
|
||||||
val availableClasses = implicitScopes.getClassClassLikeSymbols()
|
}
|
||||||
availableClasses.forEach(::addToCompletion)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ class KotlinFirPsiChecker : AbstractKotlinPsiChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun highlightDiagnostics(element: KtElement, analysisSession: KtAnalysisSession, holder: AnnotationHolder) {
|
private fun highlightDiagnostics(element: KtElement, analysisSession: KtAnalysisSession, holder: AnnotationHolder) = with(analysisSession) {
|
||||||
val diagnostics = analysisSession.getDiagnosticsForElement(element)
|
val diagnostics = element.getDiagnostics()
|
||||||
if (diagnostics.isEmpty()) return
|
if (diagnostics.isEmpty()) return
|
||||||
|
|
||||||
if (diagnostics.none(Diagnostic::isValid)) return
|
if (diagnostics.none(Diagnostic::isValid)) return
|
||||||
|
|||||||
+3
-3
@@ -16,8 +16,8 @@ internal class ExpressionsSmartcastHighlightingVisitor(
|
|||||||
analysisSession: KtAnalysisSession,
|
analysisSession: KtAnalysisSession,
|
||||||
holder: AnnotationHolder
|
holder: AnnotationHolder
|
||||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||||
override fun visitExpression(expression: KtExpression) {
|
override fun visitExpression(expression: KtExpression) = with(analysisSession) {
|
||||||
analysisSession.getImplicitReceiverSmartCasts(expression).forEach { (types, kind) ->
|
expression.getImplicitReceiverSmartCasts().forEach { (types, kind) ->
|
||||||
val receiverName = when (kind) {
|
val receiverName = when (kind) {
|
||||||
ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.implicit.receiver")
|
ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.implicit.receiver")
|
||||||
ImplicitReceiverSmartcastKind.DISPATCH -> KotlinIdeaAnalysisBundle.message("implicit.receiver")
|
ImplicitReceiverSmartcastKind.DISPATCH -> KotlinIdeaAnalysisBundle.message("implicit.receiver")
|
||||||
@@ -34,7 +34,7 @@ internal class ExpressionsSmartcastHighlightingVisitor(
|
|||||||
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_RECEIVER
|
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_RECEIVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
analysisSession.getSmartCastedToTypes(expression)?.forEach { type ->
|
expression.getSmartCasts()?.forEach { type ->
|
||||||
createInfoAnnotation(
|
createInfoAnnotation(
|
||||||
getSmartCastTarget(expression),
|
getSmartCastTarget(expression),
|
||||||
KotlinIdeaAnalysisBundle.message(
|
KotlinIdeaAnalysisBundle.message(
|
||||||
|
|||||||
+5
-5
@@ -21,13 +21,13 @@ internal class FunctionCallHighlightingVisitor(
|
|||||||
analysisSession: KtAnalysisSession,
|
analysisSession: KtAnalysisSession,
|
||||||
holder: AnnotationHolder
|
holder: AnnotationHolder
|
||||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
override fun visitBinaryExpression(expression: KtBinaryExpression) = with(analysisSession) {
|
||||||
(expression.operationReference as? KtReferenceExpression)
|
(expression.operationReference as? KtReferenceExpression)
|
||||||
?.takeIf {
|
?.takeIf {
|
||||||
// do not highlight assignment statement
|
// do not highlight assignment statement
|
||||||
(it as? KtOperationReferenceExpression)?.operationSignTokenType != KtTokens.EQ
|
(it as? KtOperationReferenceExpression)?.operationSignTokenType != KtTokens.EQ
|
||||||
}?.let { callee ->
|
}?.let { callee ->
|
||||||
analysisSession.resolveCall(expression)
|
expression.resolveCall()
|
||||||
?.takeIf { callInfo ->
|
?.takeIf { callInfo ->
|
||||||
// ignore arithmetic-like operator calls
|
// ignore arithmetic-like operator calls
|
||||||
(callInfo.targetFunction as? KtFunctionSymbol)?.isOperator != true
|
(callInfo.targetFunction as? KtFunctionSymbol)?.isOperator != true
|
||||||
@@ -41,12 +41,12 @@ internal class FunctionCallHighlightingVisitor(
|
|||||||
super.visitBinaryExpression(expression)
|
super.visitBinaryExpression(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCallExpression(expression: KtCallExpression) {
|
override fun visitCallExpression(expression: KtCallExpression) = with(analysisSession) {
|
||||||
expression.calleeExpression
|
expression.calleeExpression
|
||||||
?.takeUnless { it is KtLambdaExpression }
|
?.takeUnless { it is KtLambdaExpression }
|
||||||
?.takeUnless { it is KtCallExpression /* KT-16159 */}
|
?.takeUnless { it is KtCallExpression /* KT-16159 */ }
|
||||||
?.let { callee ->
|
?.let { callee ->
|
||||||
analysisSession.resolveCall(expression)?.let { callInfo ->
|
expression.resolveCall()?.let { callInfo ->
|
||||||
getTextAttributesForCal(callInfo)?.let { attributes ->
|
getTextAttributesForCal(callInfo)?.let { attributes ->
|
||||||
highlightName(callee, attributes)
|
highlightName(callee, attributes)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -20,9 +20,9 @@ class AddFunctionReturnTypeIntention :
|
|||||||
element.typeReference == null && !element.hasBlockBody()
|
element.typeReference == null && !element.hasBlockBody()
|
||||||
|
|
||||||
override fun KtAnalysisSession.analyzeAndGetData(element: KtNamedFunction): TypeCandidate? {
|
override fun KtAnalysisSession.analyzeAndGetData(element: KtNamedFunction): TypeCandidate? {
|
||||||
val returnType = getReturnTypeForKtDeclaration(element)
|
val returnType = element.getReturnKtType()
|
||||||
val approximated = approximateTypeToUpperDenotable(returnType) ?: return null
|
val approximated = approximateTypeToUpperDenotable(returnType) ?: return null
|
||||||
return TypeCandidate(KtTypeRenderer.render(approximated))
|
return TypeCandidate(approximated.render())
|
||||||
}
|
}
|
||||||
|
|
||||||
private tailrec fun approximateTypeToUpperDenotable(type: KtType): KtDenotableType? = when (type) {
|
private tailrec fun approximateTypeToUpperDenotable(type: KtType): KtDenotableType? = when (type) {
|
||||||
|
|||||||
+87
-18
@@ -6,10 +6,17 @@
|
|||||||
package org.jetbrains.kotlin.idea.frontend.api
|
package org.jetbrains.kotlin.idea.frontend.api
|
||||||
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider
|
import org.jetbrains.kotlin.idea.frontend.api.components.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
|
import org.jetbrains.kotlin.idea.references.KtSimpleReference
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
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.psi.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,24 +32,86 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
* To create analysis session consider using [analyze]
|
* To create analysis session consider using [analyze]
|
||||||
*/
|
*/
|
||||||
abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTokenOwner {
|
abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTokenOwner {
|
||||||
abstract val symbolProvider: KtSymbolProvider
|
protected abstract val smartCastProvider: KtSmartCastProvider
|
||||||
abstract val scopeProvider: KtScopeProvider
|
protected abstract val typeProvider: KtTypeProvider
|
||||||
abstract val containingDeclarationProvider: KtSymbolContainingDeclarationProvider
|
protected abstract val diagnosticProvider: KtDiagnosticProvider
|
||||||
|
protected abstract val scopeProvider: KtScopeProvider
|
||||||
|
protected abstract val containingDeclarationProvider: KtSymbolContainingDeclarationProvider
|
||||||
|
protected abstract val symbolProvider: KtSymbolProvider
|
||||||
|
protected abstract val callResolver: KtCallResolver
|
||||||
|
|
||||||
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>?
|
|
||||||
|
|
||||||
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
|
|
||||||
|
|
||||||
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
|
|
||||||
|
|
||||||
abstract fun getKtExpressionType(expression: KtExpression): KtType
|
|
||||||
|
|
||||||
abstract fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean
|
|
||||||
|
|
||||||
abstract fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic>
|
|
||||||
|
|
||||||
abstract fun resolveCall(call: KtCallExpression): CallInfo?
|
|
||||||
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
|
|
||||||
|
|
||||||
|
/// TODO: get rid of
|
||||||
|
@Deprecated("Used only in completion now, temporary")
|
||||||
abstract fun createContextDependentCopy(): KtAnalysisSession
|
abstract fun createContextDependentCopy(): KtAnalysisSession
|
||||||
|
|
||||||
|
|
||||||
|
fun KtExpression.getSmartCasts(): Collection<KtType> = smartCastProvider.getSmartCastedToTypes(this)
|
||||||
|
|
||||||
|
fun KtExpression.getImplicitReceiverSmartCasts(): Collection<ImplicitReceiverSmartCast> = smartCastProvider.getImplicitReceiverSmartCasts(this)
|
||||||
|
|
||||||
|
fun KtExpression.getKtType(): KtType = typeProvider.getKtExpressionType(this)
|
||||||
|
|
||||||
|
fun KtDeclaration.getReturnKtType(): KtType = typeProvider.getReturnTypeForKtDeclaration(this)
|
||||||
|
|
||||||
|
fun KtElement.getDiagnostics(): Collection<Diagnostic> = diagnosticProvider.getDiagnosticsForElement(this)
|
||||||
|
|
||||||
|
fun KtSymbolWithKind.getContainingSymbol(): KtSymbolWithKind? = containingDeclarationProvider.getContainingDeclaration(this)
|
||||||
|
|
||||||
|
fun KtClassOrObjectSymbol.getMemberScope(): KtMemberScope = scopeProvider.getMemberScope(this)
|
||||||
|
|
||||||
|
fun KtClassOrObjectSymbol.getDeclaredMemberScope(): KtDeclaredMemberScope = scopeProvider.getDeclaredMemberScope(this)
|
||||||
|
|
||||||
|
fun KtPackageSymbol.getPackageScope(): KtPackageScope = scopeProvider.getPackageScope(this)
|
||||||
|
|
||||||
|
fun List<KtScope>.asCompositeScope(): KtCompositeScope = scopeProvider.getCompositeScope(this)
|
||||||
|
|
||||||
|
fun KtType.getTypeScope(): KtScope? = scopeProvider.getTypeScope(this)
|
||||||
|
|
||||||
|
fun KtFile.getScopeContextForPosition(positionInFakeFile: KtElement): KtScopeContext = scopeProvider.getScopeContextForPosition(this, positionInFakeFile)
|
||||||
|
|
||||||
|
fun KtDeclaration.getSymbol(): KtSymbol = symbolProvider.getSymbol(this)
|
||||||
|
|
||||||
|
fun KtParameter.getParameterSymbol(): KtParameterSymbol = symbolProvider.getParameterSymbol(this)
|
||||||
|
|
||||||
|
fun KtNamedFunction.getFunctionSymbol(): KtFunctionSymbol = symbolProvider.getFunctionSymbol(this)
|
||||||
|
|
||||||
|
fun KtConstructor<*>.getConstructorSymbol(): KtConstructorSymbol = symbolProvider.getConstructorSymbol(this)
|
||||||
|
|
||||||
|
fun KtTypeParameter.getTypeParameterSymbol(): KtTypeParameterSymbol = symbolProvider.getTypeParameterSymbol(this)
|
||||||
|
|
||||||
|
fun KtTypeAlias.getTypeAliasSymbol(): KtTypeAliasSymbol = symbolProvider.getTypeAliasSymbol(this)
|
||||||
|
|
||||||
|
fun KtEnumEntry.getEnumEntrySymbol(): KtEnumEntrySymbol = symbolProvider.getEnumEntrySymbol(this)
|
||||||
|
|
||||||
|
fun KtNamedFunction.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol = symbolProvider.getAnonymousFunctionSymbol(this)
|
||||||
|
|
||||||
|
fun KtLambdaExpression.getAnonymousFunctionSymbol(): KtAnonymousFunctionSymbol = symbolProvider.getAnonymousFunctionSymbol(this)
|
||||||
|
|
||||||
|
fun KtProperty.getVariableSymbol(): KtVariableSymbol = symbolProvider.getVariableSymbol(this)
|
||||||
|
|
||||||
|
fun KtClassOrObject.getClassOrObjectSymbol(): KtClassOrObjectSymbol = symbolProvider.getClassOrObjectSymbol(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return symbol with specified [this@getClassOrObjectSymbolByClassId] or `null` in case such symbol is not found
|
||||||
|
*/
|
||||||
|
fun ClassId.getCorrespondingToplevelClassOrObjectSymbol(): KtClassOrObjectSymbol? = symbolProvider.getClassOrObjectSymbolByClassId(this)
|
||||||
|
|
||||||
|
fun FqName.getContainingCallableSymbolsWithName(name: Name): Sequence<KtSymbol> = symbolProvider.getTopLevelCallableSymbols(this, name)
|
||||||
|
|
||||||
|
fun <S : KtSymbol> KtSymbolPointer<S>.restoreSymbol(): S? = restoreSymbol(this@KtAnalysisSession)
|
||||||
|
|
||||||
|
fun KtCallExpression.resolveCall(): CallInfo? = callResolver.resolveCall(this)
|
||||||
|
|
||||||
|
fun KtBinaryExpression.resolveCall(): CallInfo? = callResolver.resolveCall(this)
|
||||||
|
|
||||||
|
fun KtReference.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
|
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
|
||||||
|
return this@KtAnalysisSession.resolveToSymbols()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtSimpleReference<*>.resolveToSymbol(): KtSymbol? {
|
||||||
|
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
|
||||||
|
return resolveToSymbols().singleOrNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-11
@@ -10,15 +10,5 @@ import org.jetbrains.kotlin.idea.references.KtReference
|
|||||||
import org.jetbrains.kotlin.idea.references.KtSimpleReference
|
import org.jetbrains.kotlin.idea.references.KtSimpleReference
|
||||||
|
|
||||||
interface KtSymbolBasedReference : KtReference {
|
interface KtSymbolBasedReference : KtReference {
|
||||||
fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol>
|
fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol>
|
||||||
}
|
|
||||||
|
|
||||||
fun KtReference.resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
|
||||||
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference" }
|
|
||||||
return resolveToSymbols(analysisSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KtSimpleReference<*>.resolveToSymbol(analysisSession: KtAnalysisSession): KtSymbol? {
|
|
||||||
check(this is KtSymbolBasedReference) { "To get reference symbol the one should be KtSymbolBasedReference but was ${this::class}" }
|
|
||||||
return resolveToSymbols(analysisSession).singleOrNull()
|
|
||||||
}
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||||
|
|
||||||
|
abstract class KtAnalysisSessionComponent : ValidityTokenOwner {
|
||||||
|
protected abstract val analysisSession: KtAnalysisSession
|
||||||
|
final override val token: ValidityToken get() = analysisSession.token
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.CallInfo
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
|
|
||||||
|
abstract class KtCallResolver : KtAnalysisSessionComponent() {
|
||||||
|
abstract fun resolveCall(call: KtCallExpression): CallInfo?
|
||||||
|
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
|
||||||
|
abstract class KtDiagnosticProvider : KtAnalysisSessionComponent() {
|
||||||
|
abstract fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic>
|
||||||
|
}
|
||||||
+4
-4
@@ -3,22 +3,22 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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.idea.frontend.api.scopes
|
package org.jetbrains.kotlin.idea.frontend.api.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
abstract class KtScopeProvider : ValidityTokenOwner {
|
abstract class KtScopeProvider : KtAnalysisSessionComponent() {
|
||||||
abstract fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope
|
abstract fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope
|
||||||
abstract fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope
|
abstract fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope
|
||||||
abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope
|
abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope
|
||||||
abstract fun getCompositeScope(subScopes: List<KtScope>): KtCompositeScope
|
abstract fun getCompositeScope(subScopes: List<KtScope>): KtCompositeScope
|
||||||
|
|
||||||
abstract fun getScopeForType(type: KtType): KtScope?
|
abstract fun getTypeScope(type: KtType): KtScope?
|
||||||
|
|
||||||
abstract fun getScopeContextForPosition(originalFile: KtFile, positionInFakeFile: KtElement): KtScopeContext
|
abstract fun getScopeContextForPosition(originalFile: KtFile, positionInFakeFile: KtElement): KtScopeContext
|
||||||
}
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
abstract class KtSmartCastProvider : KtAnalysisSessionComponent() {
|
||||||
|
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>
|
||||||
|
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
|
||||||
|
}
|
||||||
+2
-2
@@ -3,11 +3,11 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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.idea.frontend.api.symbols
|
package org.jetbrains.kotlin.idea.frontend.api.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
||||||
|
|
||||||
abstract class KtSymbolContainingDeclarationProvider {
|
abstract class KtSymbolContainingDeclarationProvider : KtAnalysisSessionComponent() {
|
||||||
/**
|
/**
|
||||||
* Returns containing declaration for symbol:
|
* Returns containing declaration for symbol:
|
||||||
* for top-level declarations returns null
|
* for top-level declarations returns null
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
|
||||||
|
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
|
||||||
|
abstract fun getKtExpressionType(expression: KtExpression): KtType
|
||||||
|
}
|
||||||
+1
-1
@@ -17,7 +17,7 @@ class KtPsiBasedSymbolPointer<S : KtSymbol>(private val psiPointer: SmartPsiElem
|
|||||||
val psi = psiPointer.element ?: return null
|
val psi = psiPointer.element ?: return null
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return analysisSession.symbolProvider.getSymbol(psi) as S?
|
return with(analysisSession) { psi.getSymbol() } as S?
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+3
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|||||||
abstract class KtSymbolPointer<out S : KtSymbol> {
|
abstract class KtSymbolPointer<out S : KtSymbol> {
|
||||||
/**
|
/**
|
||||||
* @return restored symbol (possibly the new symbol instance) if one is still valid, `null` otherwise
|
* @return restored symbol (possibly the new symbol instance) if one is still valid, `null` otherwise
|
||||||
|
*
|
||||||
|
* Consider using [org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession.restoreSymbol]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Consider using org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession.restoreSymbol")
|
||||||
abstract fun restoreSymbol(analysisSession: KtAnalysisSession): S?
|
abstract fun restoreSymbol(analysisSession: KtAnalysisSession): S?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.types
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
object KtTypeRenderer {
|
private object KtTypeRenderer {
|
||||||
fun render(type: KtType, options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String = type.withValidityAssertion {
|
fun render(type: KtType, options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String = type.withValidityAssertion {
|
||||||
buildString { render(type, options) }
|
buildString { render(type, options) }
|
||||||
}
|
}
|
||||||
@@ -108,4 +108,8 @@ data class KtTypeRendererOptions(
|
|||||||
renderFqNames = true
|
renderFqNames = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtType.render(options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String =
|
||||||
|
KtTypeRenderer.render(this, options)
|
||||||
|
|
||||||
|
|||||||
+19
-159
@@ -5,37 +5,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.frontend.api.fir
|
package org.jetbrains.kotlin.idea.frontend.api.fir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.isSuspend
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.idea.fir.*
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirScopeProvider
|
import org.jetbrains.kotlin.idea.frontend.api.ReadActionConfinementValidityToken
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolContainingDeclarationProvider
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.assertIsValid
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.components.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.*
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
|
||||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
|
||||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper.toTargetSymbol
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
|
||||||
|
|
||||||
internal class KtFirAnalysisSession
|
internal class KtFirAnalysisSession
|
||||||
private constructor(
|
private constructor(
|
||||||
@@ -45,85 +28,23 @@ private constructor(
|
|||||||
token: ValidityToken,
|
token: ValidityToken,
|
||||||
val isContextSession: Boolean,
|
val isContextSession: Boolean,
|
||||||
) : KtAnalysisSession(token) {
|
) : KtAnalysisSession(token) {
|
||||||
private val project = element.project
|
|
||||||
|
|
||||||
override val symbolProvider: KtSymbolProvider =
|
|
||||||
KtFirSymbolProvider(
|
|
||||||
token,
|
|
||||||
firResolveState.firIdeLibrariesSession.firSymbolProvider,
|
|
||||||
firResolveState,
|
|
||||||
firSymbolBuilder
|
|
||||||
)
|
|
||||||
|
|
||||||
private val firScopeStorage = FirScopeRegistry()
|
|
||||||
|
|
||||||
override val scopeProvider: KtScopeProvider by threadLocal {
|
|
||||||
KtFirScopeProvider(token, firSymbolBuilder, project, firResolveState, firScopeStorage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val containingDeclarationProvider: KtSymbolContainingDeclarationProvider =
|
|
||||||
KtFirSymbolContainingDeclarationProvider(this)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
assertIsValid()
|
assertIsValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>? = withValidityAssertion {
|
private val project = element.project
|
||||||
// TODO filter out not used smartcasts
|
private val firScopeStorage = FirScopeRegistry()
|
||||||
expression.getOrBuildFirSafe<FirExpressionWithSmartcast>(firResolveState)?.typesFromSmartCast?.map { it.asTypeInfo() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
override val smartCastProvider: KtSmartCastProvider = KtFirSmartcastProvider(this)
|
||||||
override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast> = withValidityAssertion {
|
override val typeProvider: KtTypeProvider = KtFirTypeProvider(this)
|
||||||
// TODO filter out not used smartcasts
|
override val diagnosticProvider: KtDiagnosticProvider = KtFirDiagnosticProvider(this)
|
||||||
val qualifiedExpression = expression.getOrBuildFirSafe<FirQualifiedAccessExpression>(firResolveState) ?: return emptyList()
|
override val containingDeclarationProvider = KtFirSymbolContainingDeclarationProvider(this)
|
||||||
if (qualifiedExpression.dispatchReceiver !is FirExpressionWithSmartcast
|
override val callResolver: KtCallResolver = KtFirCallResolver(this)
|
||||||
&& qualifiedExpression.extensionReceiver !is FirExpressionWithSmartcast
|
override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, firScopeStorage) }
|
||||||
) return emptyList()
|
override val symbolProvider: KtSymbolProvider =
|
||||||
buildList {
|
KtFirSymbolProvider(token, firResolveState.firIdeLibrariesSession.firSymbolProvider, firResolveState, firSymbolBuilder)
|
||||||
(qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
|
||||||
ImplicitReceiverSmartCast(
|
|
||||||
smartCasted.typesFromSmartCast.map { it.asTypeInfo() },
|
|
||||||
ImplicitReceiverSmartcastKind.DISPATCH
|
|
||||||
)
|
|
||||||
}?.let(::add)
|
|
||||||
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
|
||||||
ImplicitReceiverSmartCast(
|
|
||||||
smartCasted.typesFromSmartCast.map { it.asTypeInfo() },
|
|
||||||
ImplicitReceiverSmartcastKind.EXTENSION
|
|
||||||
)
|
|
||||||
}?.let(::add)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType = withValidityAssertion {
|
|
||||||
val firDeclaration = declaration.getOrBuildFirOfType<FirCallableDeclaration<*>>(firResolveState)
|
|
||||||
firDeclaration.returnTypeRef.coneType.asTypeInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getKtExpressionType(expression: KtExpression): KtType = withValidityAssertion {
|
|
||||||
expression.getOrBuildFirOfType<FirExpression>(firResolveState).typeRef.coneType.asTypeInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean {
|
|
||||||
assertIsValid()
|
|
||||||
var result = false
|
|
||||||
forEachSuperClass(klass.getOrBuildFirSafe(firResolveState) ?: return false) { type ->
|
|
||||||
result = result || type.firClassLike(firResolveState.firIdeSourcesSession)?.symbol?.classId == superClassId
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic> = withValidityAssertion {
|
|
||||||
LowLevelFirApiFacade.getDiagnosticsFor(element, firResolveState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resolveCall(call: KtBinaryExpression): CallInfo? = withValidityAssertion {
|
|
||||||
val firCall = call.getOrBuildFirSafe<FirFunctionCall>(firResolveState) ?: return null
|
|
||||||
resolveCall(firCall, call)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createContextDependentCopy(): KtAnalysisSession {
|
override fun createContextDependentCopy(): KtAnalysisSession {
|
||||||
check(!isContextSession) { "Cannot create context-dependent copy of KtAnalysis session from a context dependent one" }
|
check(!isContextSession) { "Cannot create context-dependent copy of KtAnalysis session from a context dependent one" }
|
||||||
val contextResolveState = LowLevelFirApiFacade.getResolveStateForCompletion(element, firResolveState)
|
val contextResolveState = LowLevelFirApiFacade.getResolveStateForCompletion(element, firResolveState)
|
||||||
@@ -136,68 +57,7 @@ private constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveCall(call: KtCallExpression): CallInfo? = withValidityAssertion {
|
|
||||||
val firCall = when (val fir = call.getOrBuildFir(firResolveState)) {
|
|
||||||
is FirFunctionCall -> fir
|
|
||||||
is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall
|
|
||||||
else -> null
|
|
||||||
} ?: return null
|
|
||||||
return resolveCall(firCall, call)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
|
|
||||||
val session = firResolveState.firIdeSourcesSession
|
|
||||||
val resolvedFunctionSymbol = firCall.calleeReference.toTargetSymbol(session, firSymbolBuilder)
|
|
||||||
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
|
||||||
return when {
|
|
||||||
resolvedCalleeSymbol is FirConstructorSymbol -> {
|
|
||||||
val fir = resolvedCalleeSymbol.fir
|
|
||||||
FunctionCallInfo(firSymbolBuilder.buildConstructorSymbol(fir))
|
|
||||||
}
|
|
||||||
firCall.dispatchReceiver is FirQualifiedAccessExpression && firCall.isImplicitFunctionCall() -> {
|
|
||||||
val target = with(FirReferenceResolveHelper) {
|
|
||||||
val calleeReference = (firCall.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
|
|
||||||
calleeReference.toTargetSymbol(session, firSymbolBuilder)
|
|
||||||
}
|
|
||||||
when (target) {
|
|
||||||
null -> null
|
|
||||||
is KtVariableLikeSymbol -> {
|
|
||||||
val functionSymbol =
|
|
||||||
(firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol
|
|
||||||
when (functionSymbol?.callableId) {
|
|
||||||
null -> null
|
|
||||||
in kotlinFunctionInvokeCallableIds -> VariableAsFunctionCallInfo(target, functionSymbol.fir.isSuspend)
|
|
||||||
else -> (resolvedFunctionSymbol as? KtFunctionSymbol)
|
|
||||||
?.let { VariableAsFunctionLikeCallInfo(target, it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> resolvedFunctionSymbol?.asSimpleFunctionCall()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> resolvedFunctionSymbol?.asSimpleFunctionCall()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KtSymbol.asSimpleFunctionCall() =
|
|
||||||
(this as? KtFunctionSymbol)?.let(::FunctionCallInfo)
|
|
||||||
|
|
||||||
private fun forEachSuperClass(firClass: FirClass<*>, action: (FirResolvedTypeRef) -> Unit) {
|
|
||||||
firClass.superTypeRefs.forEach { superType ->
|
|
||||||
(superType as? FirResolvedTypeRef)?.let(action)
|
|
||||||
(superType.firClassLike(firClass.session) as? FirClass<*>?)?.let { forEachSuperClass(it, action) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ConeKotlinType.asTypeInfo() = firSymbolBuilder.buildKtType(this)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val kotlinFunctionInvokeCallableIds = (0..23).flatMapTo(hashSetOf()) { arity ->
|
|
||||||
listOf(
|
|
||||||
CallableId(KotlinBuiltIns.getFunctionClassId(arity), Name.identifier("invoke")),
|
|
||||||
CallableId(KotlinBuiltIns.getSuspendFunctionClassId(arity), Name.identifier("invoke"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze")
|
@Deprecated("Please use org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProviderKt.analyze")
|
||||||
internal fun createForElement(element: KtElement): KtFirAnalysisSession {
|
internal fun createForElement(element: KtElement): KtFirAnalysisSession {
|
||||||
val firResolveState = LowLevelFirApiFacade.getResolveStateFor(element)
|
val firResolveState = LowLevelFirApiFacade.getResolveStateFor(element)
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
|
|
||||||
|
internal interface KtFirAnalysisSessionComponent {
|
||||||
|
val analysisSession: KtFirAnalysisSession
|
||||||
|
|
||||||
|
val firSymbolBuilder get() = analysisSession.firSymbolBuilder
|
||||||
|
val firResolveState get() = analysisSession.firResolveState
|
||||||
|
fun ConeKotlinType.asKtType() = analysisSession.firSymbolBuilder.buildKtType(this)
|
||||||
|
}
|
||||||
+91
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.isSuspend
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFir
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
|
||||||
|
import org.jetbrains.kotlin.idea.fir.isImplicitFunctionCall
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtCallResolver
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
||||||
|
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper.toTargetSymbol
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
internal class KtFirCallResolver(override val analysisSession: KtFirAnalysisSession) : KtCallResolver(), KtFirAnalysisSessionComponent {
|
||||||
|
|
||||||
|
override fun resolveCall(call: KtBinaryExpression): CallInfo? = withValidityAssertion {
|
||||||
|
val firCall = call.getOrBuildFirSafe<FirFunctionCall>(firResolveState) ?: return null
|
||||||
|
resolveCall(firCall, call)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resolveCall(call: KtCallExpression): CallInfo? = withValidityAssertion {
|
||||||
|
val firCall = when (val fir = call.getOrBuildFir(firResolveState)) {
|
||||||
|
is FirFunctionCall -> fir
|
||||||
|
is FirSafeCallExpression -> fir.regularQualifiedAccess as? FirFunctionCall
|
||||||
|
else -> null
|
||||||
|
} ?: return null
|
||||||
|
return resolveCall(firCall, call)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
|
||||||
|
val session = firResolveState.firIdeSourcesSession
|
||||||
|
val resolvedFunctionSymbol = firCall.calleeReference.toTargetSymbol(session, firSymbolBuilder)
|
||||||
|
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||||
|
return when {
|
||||||
|
resolvedCalleeSymbol is FirConstructorSymbol -> {
|
||||||
|
val fir = resolvedCalleeSymbol.fir
|
||||||
|
FunctionCallInfo(firSymbolBuilder.buildConstructorSymbol(fir))
|
||||||
|
}
|
||||||
|
firCall.dispatchReceiver is FirQualifiedAccessExpression && firCall.isImplicitFunctionCall() -> {
|
||||||
|
val target = with(FirReferenceResolveHelper) {
|
||||||
|
val calleeReference = (firCall.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
|
||||||
|
calleeReference.toTargetSymbol(session, firSymbolBuilder)
|
||||||
|
}
|
||||||
|
when (target) {
|
||||||
|
null -> null
|
||||||
|
is KtVariableLikeSymbol -> {
|
||||||
|
val functionSymbol =
|
||||||
|
(firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol
|
||||||
|
when (functionSymbol?.callableId) {
|
||||||
|
null -> null
|
||||||
|
in kotlinFunctionInvokeCallableIds -> VariableAsFunctionCallInfo(target, functionSymbol.fir.isSuspend)
|
||||||
|
else -> (resolvedFunctionSymbol as? KtFunctionSymbol)
|
||||||
|
?.let { VariableAsFunctionLikeCallInfo(target, it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> resolvedFunctionSymbol?.asSimpleFunctionCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> resolvedFunctionSymbol?.asSimpleFunctionCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KtSymbol.asSimpleFunctionCall() =
|
||||||
|
(this as? KtFunctionSymbol)?.let(::FunctionCallInfo)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val kotlinFunctionInvokeCallableIds = (0..23).flatMapTo(hashSetOf()) { arity ->
|
||||||
|
listOf(
|
||||||
|
CallableId(KotlinBuiltIns.getFunctionClassId(arity), Name.identifier("invoke")),
|
||||||
|
CallableId(KotlinBuiltIns.getSuspendFunctionClassId(arity), Name.identifier("invoke"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSmartCastProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
internal class KtFirDiagnosticProvider(
|
||||||
|
override val analysisSession: KtFirAnalysisSession
|
||||||
|
) : KtDiagnosticProvider(), KtFirAnalysisSessionComponent {
|
||||||
|
override fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic> = withValidityAssertion {
|
||||||
|
LowLevelFirApiFacade.getDiagnosticsFor(element, firResolveState)
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-4
@@ -3,10 +3,9 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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.idea.frontend.api.fir.scopes
|
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
@@ -21,10 +20,20 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
|||||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
import org.jetbrains.kotlin.idea.fir.low.level.api.FirModuleResolveState
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityToken
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeContext
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeProvider
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.FirScopeRegistry
|
import org.jetbrains.kotlin.idea.frontend.api.fir.FirScopeRegistry
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirDeclaredMemberScope
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirDelegatingScope
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirMemberScope
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirNonStarImportingScope
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirPackageScope
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirStarImportingScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirClassOrObjectSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||||
@@ -41,7 +50,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal class KtFirScopeProvider(
|
internal class KtFirScopeProvider(
|
||||||
override val token: ValidityToken,
|
override val analysisSession: KtAnalysisSession,
|
||||||
private val builder: KtSymbolByFirBuilder,
|
private val builder: KtSymbolByFirBuilder,
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
firResolveState: FirModuleResolveState,
|
firResolveState: FirModuleResolveState,
|
||||||
@@ -89,7 +98,7 @@ internal class KtFirScopeProvider(
|
|||||||
KtFirCompositeScope(subScopes, token)
|
KtFirCompositeScope(subScopes, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getScopeForType(type: KtType): KtScope? {
|
override fun getTypeScope(type: KtType): KtScope? {
|
||||||
check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" }
|
check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" }
|
||||||
|
|
||||||
val firTypeScope = type.coneType.scope(firResolveState.firIdeSourcesSession, ScopeSession()) ?: return null
|
val firTypeScope = type.coneType.scope(firResolveState.firIdeSourcesSession, ScopeSession()) ?: return null
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSmartCastProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
internal class KtFirSmartcastProvider(
|
||||||
|
override val analysisSession: KtFirAnalysisSession
|
||||||
|
) : KtSmartCastProvider(), KtFirAnalysisSessionComponent {
|
||||||
|
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType> = withValidityAssertion {
|
||||||
|
// TODO filter out not used smartcasts
|
||||||
|
expression.getOrBuildFirSafe<FirExpressionWithSmartcast>(analysisSession.firResolveState)
|
||||||
|
?.typesFromSmartCast
|
||||||
|
?.map { it.asKtType() }
|
||||||
|
?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast> = withValidityAssertion {
|
||||||
|
// TODO filter out not used smartcasts
|
||||||
|
val qualifiedExpression =
|
||||||
|
expression.getOrBuildFirSafe<FirQualifiedAccessExpression>(analysisSession.firResolveState) ?: return emptyList()
|
||||||
|
if (qualifiedExpression.dispatchReceiver !is FirExpressionWithSmartcast
|
||||||
|
&& qualifiedExpression.extensionReceiver !is FirExpressionWithSmartcast
|
||||||
|
) return emptyList()
|
||||||
|
buildList {
|
||||||
|
(qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
||||||
|
ImplicitReceiverSmartCast(
|
||||||
|
smartCasted.typesFromSmartCast.map { it.asKtType() },
|
||||||
|
ImplicitReceiverSmartcastKind.DISPATCH
|
||||||
|
)
|
||||||
|
}?.let(::add)
|
||||||
|
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
||||||
|
ImplicitReceiverSmartCast(
|
||||||
|
smartCasted.typesFromSmartCast.map { it.asKtType() },
|
||||||
|
ImplicitReceiverSmartcastKind.EXTENSION
|
||||||
|
)
|
||||||
|
}?.let(::add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-10
@@ -3,18 +3,19 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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.idea.frontend.api.fir.symbols
|
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||||
|
|
||||||
import com.intellij.psi.util.parentOfType
|
import com.intellij.psi.util.parentOfType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSymbolContainingDeclarationProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
|
||||||
class KtFirSymbolContainingDeclarationProvider(
|
internal class KtFirSymbolContainingDeclarationProvider(
|
||||||
private val analysisSession: KtAnalysisSession
|
override val analysisSession: KtFirAnalysisSession
|
||||||
) : KtSymbolContainingDeclarationProvider() {
|
) : KtSymbolContainingDeclarationProvider(), KtFirAnalysisSessionComponent {
|
||||||
override fun getContainingDeclaration(symbol: KtSymbolWithKind): KtSymbolWithKind? {
|
override fun getContainingDeclaration(symbol: KtSymbolWithKind): KtSymbolWithKind? {
|
||||||
if (symbol is KtPackageSymbol) return null
|
if (symbol is KtPackageSymbol) return null
|
||||||
if (symbol.symbolKind == KtSymbolKind.TOP_LEVEL) return null
|
if (symbol.symbolKind == KtSymbolKind.TOP_LEVEL) return null
|
||||||
@@ -26,24 +27,25 @@ class KtFirSymbolContainingDeclarationProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContainingDeclarationForKotlinInSourceSymbol(symbol: KtSymbolWithKind): KtSymbolWithKind {
|
private fun getContainingDeclarationForKotlinInSourceSymbol(symbol: KtSymbolWithKind): KtSymbolWithKind = with(analysisSession) {
|
||||||
require(symbol.origin == KtSymbolOrigin.SOURCE)
|
require(symbol.origin == KtSymbolOrigin.SOURCE)
|
||||||
val psi = symbol.psi ?: error("PSI should present for declaration built by Kotlin code")
|
val psi = symbol.psi ?: error("PSI should present for declaration built by Kotlin code")
|
||||||
check(psi is KtDeclaration) { "PSI of kotlin declaration should be KtDeclaration" }
|
check(psi is KtDeclaration) { "PSI of kotlin declaration should be KtDeclaration" }
|
||||||
val containingDeclaration = psi.parentOfType<KtDeclaration>()
|
val containingDeclaration = psi.parentOfType<KtDeclaration>()
|
||||||
?: error("Containing declaration should present for non-toplevel declaration")
|
?: error("Containing declaration should present for non-toplevel declaration")
|
||||||
return with(analysisSession) {
|
return with(analysisSession) {
|
||||||
val containingSymbol = symbolProvider.getSymbol(containingDeclaration)
|
val containingSymbol = containingDeclaration.getSymbol()
|
||||||
check(containingSymbol is KtSymbolWithKind)
|
check(containingSymbol is KtSymbolWithKind)
|
||||||
containingSymbol
|
containingSymbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContainingDeclarationForLibrarySymbol(symbol: KtSymbolWithKind): KtSymbolWithKind {
|
private fun getContainingDeclarationForLibrarySymbol(symbol: KtSymbolWithKind): KtSymbolWithKind = with(analysisSession) {
|
||||||
require(symbol.origin == KtSymbolOrigin.LIBRARY)
|
require(symbol.origin == KtSymbolOrigin.LIBRARY)
|
||||||
check(symbol.symbolKind == KtSymbolKind.MEMBER)
|
check(symbol.symbolKind == KtSymbolKind.MEMBER)
|
||||||
val containingClassId = symbol.containingNonLocalClassIdIfMember ?: error("containingClassId should not be null for member declaration")
|
val containingClassId =
|
||||||
val containingClass = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(containingClassId)
|
symbol.containingNonLocalClassIdIfMember ?: error("containingClassId should not be null for member declaration")
|
||||||
|
val containingClass = containingClassId.getCorrespondingToplevelClassOrObjectSymbol()
|
||||||
return containingClass ?: error("Class with id $containingClassId should exists")
|
return containingClass ?: error("Class with id $containingClassId should exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.idea.frontend.api.fir.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirOfType
|
||||||
|
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtSmartCastProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
internal class KtFirTypeProvider(
|
||||||
|
override val analysisSession: KtFirAnalysisSession
|
||||||
|
) : KtTypeProvider(), KtFirAnalysisSessionComponent {
|
||||||
|
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType = withValidityAssertion {
|
||||||
|
val firDeclaration = declaration.getOrBuildFirOfType<FirCallableDeclaration<*>>(firResolveState)
|
||||||
|
firDeclaration.returnTypeRef.coneType.asKtType()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getKtExpressionType(expression: KtExpression): KtType = withValidityAssertion {
|
||||||
|
expression.getOrBuildFirOfType<FirExpression>(firResolveState).typeRef.coneType.asKtType()
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -16,9 +16,9 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
|||||||
internal class KtFirSimpleNameReference(
|
internal class KtFirSimpleNameReference(
|
||||||
expression: KtSimpleNameExpression
|
expression: KtSimpleNameExpression
|
||||||
) : KtSimpleNameReference(expression), KtFirReference {
|
) : KtSimpleNameReference(expression), KtFirReference {
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
return FirReferenceResolveHelper.resolveSimpleNameReference(this, analysisSession)
|
return FirReferenceResolveHelper.resolveSimpleNameReference(this@KtFirSimpleNameReference, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
||||||
|
|||||||
+4
-4
@@ -19,10 +19,10 @@ import org.jetbrains.kotlin.psi.KtExpression
|
|||||||
class KtFirArrayAccessReference(
|
class KtFirArrayAccessReference(
|
||||||
expression: KtArrayAccessExpression
|
expression: KtArrayAccessExpression
|
||||||
) : KtArrayAccessReference(expression), KtFirReference {
|
) : KtArrayAccessReference(expression), KtFirReference {
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
val fir = element.getOrBuildFirSafe<FirFunctionCall>(analysisSession.firResolveState) ?: return emptyList()
|
val fir = element.getOrBuildFirSafe<FirFunctionCall>(firResolveState) ?: return emptyList()
|
||||||
return listOfNotNull(fir.getCalleeSymbol()?.fir?.buildSymbol(analysisSession.firSymbolBuilder))
|
return listOfNotNull(fir.getCalleeSymbol()?.fir?.buildSymbol(firSymbolBuilder))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) {
|
override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) {
|
||||||
|
|||||||
+4
-4
@@ -17,9 +17,9 @@ class KtFirConstructorDelegationReference(
|
|||||||
expression: KtConstructorDelegationReferenceExpression
|
expression: KtConstructorDelegationReferenceExpression
|
||||||
) : KtConstructorDelegationReference(expression), KtFirReference {
|
) : KtConstructorDelegationReference(expression), KtFirReference {
|
||||||
|
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
val fir = expression.getOrBuildFirSafe<FirDelegatedConstructorCall>(analysisSession.firResolveState) ?: return emptyList()
|
val fir = expression.getOrBuildFirSafe<FirDelegatedConstructorCall>(firResolveState) ?: return emptyList()
|
||||||
return listOfNotNull(fir.calleeReference.getResolvedKtSymbolOfNameReference(analysisSession.firSymbolBuilder))
|
return listOfNotNull(fir.calleeReference.getResolvedKtSymbolOfNameReference(firSymbolBuilder))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -20,10 +20,10 @@ class KtFirDestructuringDeclarationReference(
|
|||||||
) : KtDestructuringDeclarationReference(element), KtFirReference {
|
) : KtDestructuringDeclarationReference(element), KtFirReference {
|
||||||
override fun canRename(): Boolean = false //todo
|
override fun canRename(): Boolean = false //todo
|
||||||
|
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
val fir = expression.getOrBuildFirSafe<FirProperty>(analysisSession.firResolveState) ?: return emptyList()
|
val fir = expression.getOrBuildFirSafe<FirProperty>(firResolveState) ?: return emptyList()
|
||||||
val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return emptyList()
|
val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return emptyList()
|
||||||
return listOfNotNull(componentFunctionSymbol.fir.buildSymbol(analysisSession.firSymbolBuilder))
|
return listOfNotNull(componentFunctionSymbol.fir.buildSymbol(firSymbolBuilder))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -18,20 +18,20 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|||||||
import org.jetbrains.kotlin.psi.KtForExpression
|
import org.jetbrains.kotlin.psi.KtForExpression
|
||||||
|
|
||||||
open class KtFirForLoopInReference(expression: KtForExpression) : KtForLoopInReference(expression), KtFirReference {
|
open class KtFirForLoopInReference(expression: KtForExpression) : KtForLoopInReference(expression), KtFirReference {
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>(analysisSession.firResolveState) ?: return emptyList()
|
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>(firResolveState) ?: return emptyList()
|
||||||
val condition = firLoop.condition as? FirFunctionCall
|
val condition = firLoop.condition as? FirFunctionCall
|
||||||
val iterator = run {
|
val iterator = this@KtFirForLoopInReference.run {
|
||||||
val callee = (condition?.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference
|
val callee = (condition?.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference
|
||||||
(callee?.getResolvedSymbolOfNameReference()?.fir as? FirProperty)?.getInitializerFunctionCall()
|
(callee?.getResolvedSymbolOfNameReference()?.fir as? FirProperty)?.getInitializerFunctionCall()
|
||||||
}
|
}
|
||||||
val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference()
|
val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference()
|
||||||
val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall()
|
val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall()
|
||||||
return listOfNotNull(
|
return listOfNotNull(
|
||||||
iterator?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
iterator?.fir?.buildSymbol(firSymbolBuilder),
|
||||||
hasNext?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
hasNext?.fir?.buildSymbol(firSymbolBuilder),
|
||||||
next?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
next?.fir?.buildSymbol(firSymbolBuilder),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,8 +16,8 @@ class KtFirInvokeFunctionReference(expression: KtCallExpression) : KtInvokeFunct
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
val call = analysisSession.resolveCall(expression) ?: return emptyList()
|
val call = expression.resolveCall() ?: return emptyList()
|
||||||
if (call is VariableAsFunctionLikeCallInfo) {
|
if (call is VariableAsFunctionLikeCallInfo) {
|
||||||
return listOf(call.invokeFunction)
|
return listOf(call.invokeFunction)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -21,15 +21,15 @@ import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
|||||||
class KtFirPropertyDelegationMethodsReference(
|
class KtFirPropertyDelegationMethodsReference(
|
||||||
element: KtPropertyDelegate
|
element: KtPropertyDelegate
|
||||||
) : KtPropertyDelegationMethodsReference(element), KtFirReference {
|
) : KtPropertyDelegationMethodsReference(element), KtFirReference {
|
||||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||||
check(analysisSession is KtFirAnalysisSession)
|
check(this is KtFirAnalysisSession)
|
||||||
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>(analysisSession.firResolveState) ?: return emptyList()
|
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>(firResolveState) ?: return emptyList()
|
||||||
if (property.delegate == null) return emptyList()
|
if (property.delegate == null) return emptyList()
|
||||||
val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol()
|
val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol()
|
||||||
val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol()
|
val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol()
|
||||||
return listOfNotNull(
|
return listOfNotNull(
|
||||||
getValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
getValueSymbol?.fir?.buildSymbol(firSymbolBuilder),
|
||||||
setValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder)
|
setValueSymbol?.fir?.buildSymbol(firSymbolBuilder)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|||||||
|
|
||||||
interface KtFirReference : KtReference, KtSymbolBasedReference {
|
interface KtFirReference : KtReference, KtSymbolBasedReference {
|
||||||
fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> =
|
fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> =
|
||||||
resolveToSymbols(analysisSession).mapNotNull(KtSymbol::psi)
|
analysisSession.resolveToSymbols().mapNotNull(KtSymbol::psi)
|
||||||
|
|
||||||
override val resolver get() = KtFirReferenceResolver
|
override val resolver get() = KtFirReferenceResolver
|
||||||
}
|
}
|
||||||
+2
-2
@@ -23,7 +23,7 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas
|
|||||||
|
|
||||||
val renderedSymbols = executeOnPooledThreadInReadAction {
|
val renderedSymbols = executeOnPooledThreadInReadAction {
|
||||||
analyze(fakeKtFile) {
|
analyze(fakeKtFile) {
|
||||||
val symbols = createSymbols(symbolData, this)
|
val symbols = createSymbols(symbolData)
|
||||||
symbols.map { DebugSymbolRenderer.render(it) }
|
symbols.map { DebugSymbolRenderer.render(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas
|
|||||||
KotlinTestUtils.assertEqualsToFile(File(path), actual)
|
KotlinTestUtils.assertEqualsToFile(File(path), actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List<KtSymbol>
|
protected abstract fun KtAnalysisSession.createSymbols(symbolData: SymbolData): List<KtSymbol>
|
||||||
|
|
||||||
override fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor =
|
override fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor =
|
||||||
KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
|
|||||||
+7
-8
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object SymbolByFqName {
|
object SymbolByFqName {
|
||||||
@@ -36,25 +35,25 @@ object SymbolByFqName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class SymbolData {
|
sealed class SymbolData {
|
||||||
abstract fun toSymbols(analysisSession: KtAnalysisSession): List<KtSymbol>
|
abstract fun KtAnalysisSession.toSymbols(): List<KtSymbol>
|
||||||
|
|
||||||
data class ClassData(val classId: ClassId) : SymbolData() {
|
data class ClassData(val classId: ClassId) : SymbolData() {
|
||||||
override fun toSymbols(analysisSession: KtAnalysisSession): List<KtSymbol> {
|
override fun KtAnalysisSession.toSymbols(): List<KtSymbol> {
|
||||||
val symbol = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId) ?: error("Class $classId is not found")
|
val symbol = classId.getCorrespondingToplevelClassOrObjectSymbol() ?: error("Class $classId is not found")
|
||||||
return listOf(symbol)
|
return listOf(symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CallableData(val callableId: CallableId) : SymbolData() {
|
data class CallableData(val callableId: CallableId) : SymbolData() {
|
||||||
override fun toSymbols(analysisSession: KtAnalysisSession): List<KtSymbol> {
|
override fun KtAnalysisSession.toSymbols(): List<KtSymbol> {
|
||||||
val classId = callableId.classId
|
val classId = callableId.classId
|
||||||
val symbols = if (classId == null) {
|
val symbols = if (classId == null) {
|
||||||
analysisSession.symbolProvider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName).toList()
|
callableId.packageName.getContainingCallableSymbolsWithName(callableId.callableName).toList()
|
||||||
} else {
|
} else {
|
||||||
val classSymbol =
|
val classSymbol =
|
||||||
analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId)
|
classId.getCorrespondingToplevelClassOrObjectSymbol()
|
||||||
?: error("Class $classId is not found")
|
?: error("Class $classId is not found")
|
||||||
analysisSession.scopeProvider.getDeclaredMemberScope(classSymbol).getCallableSymbols()
|
classSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||||
.filter { (it as? KtNamedSymbol)?.name == callableId.callableName }
|
.filter { (it as? KtNamedSymbol)?.name == callableId.callableName }
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -43,8 +43,8 @@ abstract class AbstractResolveCallTest : @Suppress("DEPRECATION") KotlinLightCod
|
|||||||
val callInfos = analyze(file as KtFile) {
|
val callInfos = analyze(file as KtFile) {
|
||||||
elements.map { element ->
|
elements.map { element ->
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtCallExpression -> resolveCall(element)
|
is KtCallExpression -> element.resolveCall()
|
||||||
is KtBinaryExpression -> resolveCall(element)
|
is KtBinaryExpression -> element.resolveCall()
|
||||||
else -> error("Selected should be either KtCallExpression or KtBinaryExpression but was $element")
|
else -> error("Selected should be either KtCallExpression or KtBinaryExpression but was $element")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -12,9 +12,9 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||||
|
|
||||||
abstract class AbstractMemberScopeByFqNameTest : AbstractSymbolsByFqNameBuildingTest() {
|
abstract class AbstractMemberScopeByFqNameTest : AbstractSymbolsByFqNameBuildingTest() {
|
||||||
override fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List<KtSymbol> {
|
override fun KtAnalysisSession.createSymbols(symbolData: SymbolData): List<KtSymbol> {
|
||||||
val symbols = symbolData.toSymbols(analysisSession)
|
val symbols = with(symbolData) { toSymbols() }
|
||||||
val classSymbol = symbols.singleOrNull() as? KtClassOrObjectSymbol ?: error("Should be a single class symbol, but $symbols found")
|
val classSymbol = symbols.singleOrNull() as? KtClassOrObjectSymbol ?: error("Should be a single class symbol, but $symbols found")
|
||||||
return analysisSession.scopeProvider.getMemberScope(classSymbol).getAllSymbols().toList()
|
return classSymbol.getMemberScope().getAllSymbols().toList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-2
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.frontend.api.symbols
|
package org.jetbrains.kotlin.idea.frontend.api.symbols
|
||||||
|
|
||||||
import com.intellij.testFramework.LightProjectDescriptor
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName
|
import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -13,6 +12,6 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
abstract class AbstractSymbolFromLibraryPointerRestoreTest : AbstractSymbolPointerRestoreTest() {
|
abstract class AbstractSymbolFromLibraryPointerRestoreTest : AbstractSymbolPointerRestoreTest() {
|
||||||
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> {
|
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> {
|
||||||
val symbolData = SymbolByFqName.getSymbolDataFromFile(filePath)
|
val symbolData = SymbolByFqName.getSymbolDataFromFile(filePath)
|
||||||
return symbolData.toSymbols(this)
|
return with(symbolData) { toSymbols() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -13,6 +13,6 @@ import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
|||||||
abstract class AbstractSymbolFromSourcePointerRestoreTest : AbstractSymbolPointerRestoreTest() {
|
abstract class AbstractSymbolFromSourcePointerRestoreTest : AbstractSymbolPointerRestoreTest() {
|
||||||
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> =
|
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> =
|
||||||
ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
||||||
symbolProvider.getSymbol(declaration)
|
declaration.getSymbol()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -64,7 +64,7 @@ abstract class AbstractSymbolPointerRestoreTest : KotlinLightCodeInsightFixtureT
|
|||||||
executeOnPooledThreadInReadAction {
|
executeOnPooledThreadInReadAction {
|
||||||
analyze(ktFile) {
|
analyze(ktFile) {
|
||||||
val restored = pointersWithRendered.map { (pointer, expectedRender) ->
|
val restored = pointersWithRendered.map { (pointer, expectedRender) ->
|
||||||
val restored = pointer.restoreSymbol(this) ?: error("Symbol $expectedRender was not not restored correctly")
|
val restored = pointer.restoreSymbol() ?: error("Symbol $expectedRender was not not restored correctly")
|
||||||
DebugSymbolRenderer.render(restored)
|
DebugSymbolRenderer.render(restored)
|
||||||
}
|
}
|
||||||
val actualRestored = SymbolByFqName.textWithRenderedSymbolData(
|
val actualRestored = SymbolByFqName.textWithRenderedSymbolData(
|
||||||
|
|||||||
+2
-2
@@ -10,6 +10,6 @@ import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.SymbolData
|
import org.jetbrains.kotlin.idea.frontend.api.SymbolData
|
||||||
|
|
||||||
abstract class AbstractSymbolsByFqNameBuildingTest : AbstractSymbolByFqNameTest() {
|
abstract class AbstractSymbolsByFqNameBuildingTest : AbstractSymbolByFqNameTest() {
|
||||||
override fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List<KtSymbol> =
|
override fun KtAnalysisSession.createSymbols(symbolData: SymbolData): List<KtSymbol> =
|
||||||
symbolData.toSymbols(analysisSession)
|
with(symbolData) { toSymbols() }
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,7 +27,7 @@ abstract class AbstractSymbolsByPsiBuildingTest : KotlinLightCodeInsightFixtureT
|
|||||||
val renderedSymbols = executeOnPooledThreadInReadAction {
|
val renderedSymbols = executeOnPooledThreadInReadAction {
|
||||||
analyze(ktFile) {
|
analyze(ktFile) {
|
||||||
val declarationSymbols = ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
val declarationSymbols = ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
||||||
symbolProvider.getSymbol(declaration)
|
declaration.getSymbol()
|
||||||
}
|
}
|
||||||
declarationSymbols.map(DebugSymbolRenderer::render)
|
declarationSymbols.map(DebugSymbolRenderer::render)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -30,8 +30,8 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
val property = fakeKtFile.declarations.single() as KtFunction
|
val property = fakeKtFile.declarations.single() as KtFunction
|
||||||
val renderedType = executeOnPooledThreadInReadAction {
|
val renderedType = executeOnPooledThreadInReadAction {
|
||||||
analyze(fakeKtFile) {
|
analyze(fakeKtFile) {
|
||||||
val ktType = getReturnTypeForKtDeclaration(property)
|
val ktType = property.getReturnKtType()
|
||||||
KtTypeRenderer.render(ktType, rendererOptions)
|
ktType.render(rendererOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(expected, renderedType)
|
assertEquals(expected, renderedType)
|
||||||
@@ -46,8 +46,8 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
val property = fakeKtFile.declarations.single() as KtProperty
|
val property = fakeKtFile.declarations.single() as KtProperty
|
||||||
val renderedType = executeOnPooledThreadInReadAction {
|
val renderedType = executeOnPooledThreadInReadAction {
|
||||||
analyze(fakeKtFile) {
|
analyze(fakeKtFile) {
|
||||||
val ktType = getReturnTypeForKtDeclaration(property)
|
val ktType = property.getReturnKtType()
|
||||||
KtTypeRenderer.render(ktType, rendererOptions)
|
ktType.render(rendererOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals(expected, renderedType)
|
assertEquals(expected, renderedType)
|
||||||
|
|||||||
Reference in New Issue
Block a user