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
|
||||
|
||||
import com.intellij.codeInsight.completion.*
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import com.intellij.patterns.PlatformPatterns
|
||||
import com.intellij.patterns.PsiJavaPatterns
|
||||
import com.intellij.util.ProcessingContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtLabelReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
@@ -38,40 +37,38 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
|
||||
|
||||
val possibleReceiver = nameExpression.getQualifiedExpressionForSelector()?.receiverExpression
|
||||
|
||||
val originalSession = getAnalysisSessionFor(originalFile)
|
||||
val sessionForCompletion = originalSession.createContextDependentCopy()
|
||||
val scopeProvider = sessionForCompletion.scopeProvider
|
||||
with(getAnalysisSessionFor(originalFile).createContextDependentCopy()) {
|
||||
val (implicitScopes, implicitReceivers) = originalFile.getScopeContextForPosition(nameExpression)
|
||||
|
||||
val (implicitScopes, implicitReceivers) = scopeProvider.getScopeContextForPosition(originalFile, nameExpression)
|
||||
val typeOfPossibleReceiver = possibleReceiver?.getKtType()
|
||||
val possibleReceiverScope = typeOfPossibleReceiver?.let { it.getTypeScope() }
|
||||
|
||||
val typeOfPossibleReceiver = possibleReceiver?.let { sessionForCompletion.getKtExpressionType(it) }
|
||||
val possibleReceiverScope = typeOfPossibleReceiver?.let { sessionForCompletion.scopeProvider.getScopeForType(it) }
|
||||
fun addToCompletion(symbol: KtSymbol) {
|
||||
if (symbol !is KtNamedSymbol) return
|
||||
result.addElement(lookupElementFactory.createLookupElement(symbol))
|
||||
}
|
||||
|
||||
fun addToCompletion(symbol: KtSymbol) {
|
||||
if (symbol !is KtNamedSymbol) return
|
||||
result.addElement(lookupElementFactory.createLookupElement(symbol))
|
||||
}
|
||||
if (possibleReceiverScope != null) {
|
||||
val nonExtensionMembers = possibleReceiverScope
|
||||
.getCallableSymbols()
|
||||
.filterNot { it.isExtension }
|
||||
|
||||
if (possibleReceiverScope != null) {
|
||||
val nonExtensionMembers = possibleReceiverScope
|
||||
.getCallableSymbols()
|
||||
.filterNot { it.isExtension }
|
||||
val extensionNonMembers = implicitScopes
|
||||
.getCallableSymbols()
|
||||
.filter { it.isExtension && it.canBeCalledWith(listOf(typeOfPossibleReceiver)) }
|
||||
|
||||
val extensionNonMembers = implicitScopes
|
||||
.getCallableSymbols()
|
||||
.filter { it.isExtension && it.canBeCalledWith(listOf(typeOfPossibleReceiver)) }
|
||||
nonExtensionMembers.forEach(::addToCompletion)
|
||||
extensionNonMembers.forEach(::addToCompletion)
|
||||
} else {
|
||||
val extensionNonMembers = implicitScopes
|
||||
.getCallableSymbols()
|
||||
.filter { !it.isExtension || it.canBeCalledWith(implicitReceivers) }
|
||||
|
||||
nonExtensionMembers.forEach(::addToCompletion)
|
||||
extensionNonMembers.forEach(::addToCompletion)
|
||||
} else {
|
||||
val extensionNonMembers = implicitScopes
|
||||
.getCallableSymbols()
|
||||
.filter { !it.isExtension || it.canBeCalledWith(implicitReceivers) }
|
||||
extensionNonMembers.forEach(::addToCompletion)
|
||||
|
||||
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) {
|
||||
val diagnostics = analysisSession.getDiagnosticsForElement(element)
|
||||
private fun highlightDiagnostics(element: KtElement, analysisSession: KtAnalysisSession, holder: AnnotationHolder) = with(analysisSession) {
|
||||
val diagnostics = element.getDiagnostics()
|
||||
if (diagnostics.isEmpty()) return
|
||||
|
||||
if (diagnostics.none(Diagnostic::isValid)) return
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@ internal class ExpressionsSmartcastHighlightingVisitor(
|
||||
analysisSession: KtAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitExpression(expression: KtExpression) {
|
||||
analysisSession.getImplicitReceiverSmartCasts(expression).forEach { (types, kind) ->
|
||||
override fun visitExpression(expression: KtExpression) = with(analysisSession) {
|
||||
expression.getImplicitReceiverSmartCasts().forEach { (types, kind) ->
|
||||
val receiverName = when (kind) {
|
||||
ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.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
|
||||
}
|
||||
}
|
||||
analysisSession.getSmartCastedToTypes(expression)?.forEach { type ->
|
||||
expression.getSmartCasts()?.forEach { type ->
|
||||
createInfoAnnotation(
|
||||
getSmartCastTarget(expression),
|
||||
KotlinIdeaAnalysisBundle.message(
|
||||
|
||||
+5
-5
@@ -21,13 +21,13 @@ internal class FunctionCallHighlightingVisitor(
|
||||
analysisSession: KtAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) = with(analysisSession) {
|
||||
(expression.operationReference as? KtReferenceExpression)
|
||||
?.takeIf {
|
||||
// do not highlight assignment statement
|
||||
(it as? KtOperationReferenceExpression)?.operationSignTokenType != KtTokens.EQ
|
||||
}?.let { callee ->
|
||||
analysisSession.resolveCall(expression)
|
||||
expression.resolveCall()
|
||||
?.takeIf { callInfo ->
|
||||
// ignore arithmetic-like operator calls
|
||||
(callInfo.targetFunction as? KtFunctionSymbol)?.isOperator != true
|
||||
@@ -41,12 +41,12 @@ internal class FunctionCallHighlightingVisitor(
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
override fun visitCallExpression(expression: KtCallExpression) = with(analysisSession) {
|
||||
expression.calleeExpression
|
||||
?.takeUnless { it is KtLambdaExpression }
|
||||
?.takeUnless { it is KtCallExpression /* KT-16159 */}
|
||||
?.takeUnless { it is KtCallExpression /* KT-16159 */ }
|
||||
?.let { callee ->
|
||||
analysisSession.resolveCall(expression)?.let { callInfo ->
|
||||
expression.resolveCall()?.let { callInfo ->
|
||||
getTextAttributesForCal(callInfo)?.let { attributes ->
|
||||
highlightName(callee, attributes)
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,9 +20,9 @@ class AddFunctionReturnTypeIntention :
|
||||
element.typeReference == null && !element.hasBlockBody()
|
||||
|
||||
override fun KtAnalysisSession.analyzeAndGetData(element: KtNamedFunction): TypeCandidate? {
|
||||
val returnType = getReturnTypeForKtDeclaration(element)
|
||||
val returnType = element.getReturnKtType()
|
||||
val approximated = approximateTypeToUpperDenotable(returnType) ?: return null
|
||||
return TypeCandidate(KtTypeRenderer.render(approximated))
|
||||
return TypeCandidate(approximated.render())
|
||||
}
|
||||
|
||||
private tailrec fun approximateTypeToUpperDenotable(type: KtType): KtDenotableType? = when (type) {
|
||||
|
||||
+87
-18
@@ -6,10 +6,17 @@
|
||||
package org.jetbrains.kotlin.idea.frontend.api
|
||||
|
||||
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.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.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleReference
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
/**
|
||||
@@ -25,24 +32,86 @@ import org.jetbrains.kotlin.psi.*
|
||||
* To create analysis session consider using [analyze]
|
||||
*/
|
||||
abstract class KtAnalysisSession(override val token: ValidityToken) : ValidityTokenOwner {
|
||||
abstract val symbolProvider: KtSymbolProvider
|
||||
abstract val scopeProvider: KtScopeProvider
|
||||
abstract val containingDeclarationProvider: KtSymbolContainingDeclarationProvider
|
||||
protected abstract val smartCastProvider: KtSmartCastProvider
|
||||
protected abstract val typeProvider: KtTypeProvider
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
interface KtSymbolBasedReference : KtReference {
|
||||
fun resolveToSymbols(analysisSession: KtAnalysisSession): 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()
|
||||
fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol>
|
||||
}
|
||||
+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.
|
||||
*/
|
||||
|
||||
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.KtPackageSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class KtScopeProvider : ValidityTokenOwner {
|
||||
abstract class KtScopeProvider : KtAnalysisSessionComponent() {
|
||||
abstract fun getMemberScope(classSymbol: KtClassOrObjectSymbol): KtMemberScope
|
||||
abstract fun getDeclaredMemberScope(classSymbol: KtClassOrObjectSymbol): KtDeclaredMemberScope
|
||||
abstract fun getPackageScope(packageSymbol: KtPackageSymbol): KtPackageScope
|
||||
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
|
||||
}
|
||||
+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.
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
abstract class KtSymbolContainingDeclarationProvider {
|
||||
abstract class KtSymbolContainingDeclarationProvider : KtAnalysisSessionComponent() {
|
||||
/**
|
||||
* Returns containing declaration for symbol:
|
||||
* 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
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return analysisSession.symbolProvider.getSymbol(psi) as S?
|
||||
return with(analysisSession) { psi.getSymbol() } as S?
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+3
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||
abstract class KtSymbolPointer<out S : KtSymbol> {
|
||||
/**
|
||||
* @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?
|
||||
}
|
||||
|
||||
|
||||
+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.name.ClassId
|
||||
|
||||
object KtTypeRenderer {
|
||||
private object KtTypeRenderer {
|
||||
fun render(type: KtType, options: KtTypeRendererOptions = KtTypeRendererOptions.DEFAULT): String = type.withValidityAssertion {
|
||||
buildString { render(type, options) }
|
||||
}
|
||||
@@ -108,4 +108,8 @@ data class KtTypeRendererOptions(
|
||||
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
|
||||
|
||||
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.transformers.firClassLike
|
||||
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.LowLevelFirApiFacade
|
||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.scopes.KtFirScopeProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbolContainingDeclarationProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ReadActionConfinementValidityToken
|
||||
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.utils.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
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.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.threadLocal
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolProvider
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
internal class KtFirAnalysisSession
|
||||
private constructor(
|
||||
@@ -45,85 +28,23 @@ private constructor(
|
||||
token: ValidityToken,
|
||||
val isContextSession: Boolean,
|
||||
) : 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 {
|
||||
assertIsValid()
|
||||
}
|
||||
|
||||
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>? = withValidityAssertion {
|
||||
// TODO filter out not used smartcasts
|
||||
expression.getOrBuildFirSafe<FirExpressionWithSmartcast>(firResolveState)?.typesFromSmartCast?.map { it.asTypeInfo() }
|
||||
}
|
||||
private val project = element.project
|
||||
private val firScopeStorage = FirScopeRegistry()
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast> = withValidityAssertion {
|
||||
// TODO filter out not used smartcasts
|
||||
val qualifiedExpression = expression.getOrBuildFirSafe<FirQualifiedAccessExpression>(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.asTypeInfo() },
|
||||
ImplicitReceiverSmartcastKind.DISPATCH
|
||||
)
|
||||
}?.let(::add)
|
||||
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
||||
ImplicitReceiverSmartCast(
|
||||
smartCasted.typesFromSmartCast.map { it.asTypeInfo() },
|
||||
ImplicitReceiverSmartcastKind.EXTENSION
|
||||
)
|
||||
}?.let(::add)
|
||||
}
|
||||
}
|
||||
override val smartCastProvider: KtSmartCastProvider = KtFirSmartcastProvider(this)
|
||||
override val typeProvider: KtTypeProvider = KtFirTypeProvider(this)
|
||||
override val diagnosticProvider: KtDiagnosticProvider = KtFirDiagnosticProvider(this)
|
||||
override val containingDeclarationProvider = KtFirSymbolContainingDeclarationProvider(this)
|
||||
override val callResolver: KtCallResolver = KtFirCallResolver(this)
|
||||
override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, firScopeStorage) }
|
||||
override val symbolProvider: KtSymbolProvider =
|
||||
KtFirSymbolProvider(token, firResolveState.firIdeLibrariesSession.firSymbolProvider, firResolveState, firSymbolBuilder)
|
||||
|
||||
|
||||
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 {
|
||||
check(!isContextSession) { "Cannot create context-dependent copy of KtAnalysis session from a context dependent one" }
|
||||
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 {
|
||||
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")
|
||||
internal fun createForElement(element: KtElement): KtFirAnalysisSession {
|
||||
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.
|
||||
*/
|
||||
|
||||
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 org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
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.low.level.api.FirModuleResolveState
|
||||
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.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.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.types.KtFirType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||
@@ -41,7 +50,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import java.util.*
|
||||
|
||||
internal class KtFirScopeProvider(
|
||||
override val token: ValidityToken,
|
||||
override val analysisSession: KtAnalysisSession,
|
||||
private val builder: KtSymbolByFirBuilder,
|
||||
private val project: Project,
|
||||
firResolveState: FirModuleResolveState,
|
||||
@@ -89,7 +98,7 @@ internal class KtFirScopeProvider(
|
||||
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" }
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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 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.markers.KtSymbolKind
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithKind
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
class KtFirSymbolContainingDeclarationProvider(
|
||||
private val analysisSession: KtAnalysisSession
|
||||
) : KtSymbolContainingDeclarationProvider() {
|
||||
internal class KtFirSymbolContainingDeclarationProvider(
|
||||
override val analysisSession: KtFirAnalysisSession
|
||||
) : KtSymbolContainingDeclarationProvider(), KtFirAnalysisSessionComponent {
|
||||
override fun getContainingDeclaration(symbol: KtSymbolWithKind): KtSymbolWithKind? {
|
||||
if (symbol is KtPackageSymbol) 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)
|
||||
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" }
|
||||
val containingDeclaration = psi.parentOfType<KtDeclaration>()
|
||||
?: error("Containing declaration should present for non-toplevel declaration")
|
||||
return with(analysisSession) {
|
||||
val containingSymbol = symbolProvider.getSymbol(containingDeclaration)
|
||||
val containingSymbol = containingDeclaration.getSymbol()
|
||||
check(containingSymbol is KtSymbolWithKind)
|
||||
containingSymbol
|
||||
}
|
||||
}
|
||||
|
||||
private fun getContainingDeclarationForLibrarySymbol(symbol: KtSymbolWithKind): KtSymbolWithKind {
|
||||
private fun getContainingDeclarationForLibrarySymbol(symbol: KtSymbolWithKind): KtSymbolWithKind = with(analysisSession) {
|
||||
require(symbol.origin == KtSymbolOrigin.LIBRARY)
|
||||
check(symbol.symbolKind == KtSymbolKind.MEMBER)
|
||||
val containingClassId = symbol.containingNonLocalClassIdIfMember ?: error("containingClassId should not be null for member declaration")
|
||||
val containingClass = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(containingClassId)
|
||||
val 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")
|
||||
}
|
||||
}
|
||||
+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(
|
||||
expression: KtSimpleNameExpression
|
||||
) : KtSimpleNameReference(expression), KtFirReference {
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
return FirReferenceResolveHelper.resolveSimpleNameReference(this, analysisSession)
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
return FirReferenceResolveHelper.resolveSimpleNameReference(this@KtFirSimpleNameReference, this)
|
||||
}
|
||||
|
||||
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
||||
|
||||
+4
-4
@@ -19,10 +19,10 @@ import org.jetbrains.kotlin.psi.KtExpression
|
||||
class KtFirArrayAccessReference(
|
||||
expression: KtArrayAccessExpression
|
||||
) : KtArrayAccessReference(expression), KtFirReference {
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
val fir = element.getOrBuildFirSafe<FirFunctionCall>(analysisSession.firResolveState) ?: return emptyList()
|
||||
return listOfNotNull(fir.getCalleeSymbol()?.fir?.buildSymbol(analysisSession.firSymbolBuilder))
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
val fir = element.getOrBuildFirSafe<FirFunctionCall>(firResolveState) ?: return emptyList()
|
||||
return listOfNotNull(fir.getCalleeSymbol()?.fir?.buildSymbol(firSymbolBuilder))
|
||||
}
|
||||
|
||||
override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) {
|
||||
|
||||
+4
-4
@@ -17,9 +17,9 @@ class KtFirConstructorDelegationReference(
|
||||
expression: KtConstructorDelegationReferenceExpression
|
||||
) : KtConstructorDelegationReference(expression), KtFirReference {
|
||||
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
val fir = expression.getOrBuildFirSafe<FirDelegatedConstructorCall>(analysisSession.firResolveState) ?: return emptyList()
|
||||
return listOfNotNull(fir.calleeReference.getResolvedKtSymbolOfNameReference(analysisSession.firSymbolBuilder))
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
val fir = expression.getOrBuildFirSafe<FirDelegatedConstructorCall>(firResolveState) ?: return emptyList()
|
||||
return listOfNotNull(fir.calleeReference.getResolvedKtSymbolOfNameReference(firSymbolBuilder))
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,10 +20,10 @@ class KtFirDestructuringDeclarationReference(
|
||||
) : KtDestructuringDeclarationReference(element), KtFirReference {
|
||||
override fun canRename(): Boolean = false //todo
|
||||
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
val fir = expression.getOrBuildFirSafe<FirProperty>(analysisSession.firResolveState) ?: return emptyList()
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
val fir = expression.getOrBuildFirSafe<FirProperty>(firResolveState) ?: 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
|
||||
|
||||
open class KtFirForLoopInReference(expression: KtForExpression) : KtForLoopInReference(expression), KtFirReference {
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>(analysisSession.firResolveState) ?: return emptyList()
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>(firResolveState) ?: return emptyList()
|
||||
val condition = firLoop.condition as? FirFunctionCall
|
||||
val iterator = run {
|
||||
val iterator = this@KtFirForLoopInReference.run {
|
||||
val callee = (condition?.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference
|
||||
(callee?.getResolvedSymbolOfNameReference()?.fir as? FirProperty)?.getInitializerFunctionCall()
|
||||
}
|
||||
val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference()
|
||||
val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall()
|
||||
return listOfNotNull(
|
||||
iterator?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
||||
hasNext?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
||||
next?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
||||
iterator?.fir?.buildSymbol(firSymbolBuilder),
|
||||
hasNext?.fir?.buildSymbol(firSymbolBuilder),
|
||||
next?.fir?.buildSymbol(firSymbolBuilder),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@ class KtFirInvokeFunctionReference(expression: KtCallExpression) : KtInvokeFunct
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
val call = analysisSession.resolveCall(expression) ?: return emptyList()
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
val call = expression.resolveCall() ?: return emptyList()
|
||||
if (call is VariableAsFunctionLikeCallInfo) {
|
||||
return listOf(call.invokeFunction)
|
||||
}
|
||||
|
||||
+5
-5
@@ -21,15 +21,15 @@ import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
class KtFirPropertyDelegationMethodsReference(
|
||||
element: KtPropertyDelegate
|
||||
) : KtPropertyDelegationMethodsReference(element), KtFirReference {
|
||||
override fun resolveToSymbols(analysisSession: KtAnalysisSession): Collection<KtSymbol> {
|
||||
check(analysisSession is KtFirAnalysisSession)
|
||||
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>(analysisSession.firResolveState) ?: return emptyList()
|
||||
override fun KtAnalysisSession.resolveToSymbols(): Collection<KtSymbol> {
|
||||
check(this is KtFirAnalysisSession)
|
||||
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>(firResolveState) ?: return emptyList()
|
||||
if (property.delegate == null) return emptyList()
|
||||
val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol()
|
||||
val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol()
|
||||
return listOfNotNull(
|
||||
getValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder),
|
||||
setValueSymbol?.fir?.buildSymbol(analysisSession.firSymbolBuilder)
|
||||
getValueSymbol?.fir?.buildSymbol(firSymbolBuilder),
|
||||
setValueSymbol?.fir?.buildSymbol(firSymbolBuilder)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||
|
||||
interface KtFirReference : KtReference, KtSymbolBasedReference {
|
||||
fun getResolvedToPsi(analysisSession: KtAnalysisSession): Collection<PsiElement> =
|
||||
resolveToSymbols(analysisSession).mapNotNull(KtSymbol::psi)
|
||||
analysisSession.resolveToSymbols().mapNotNull(KtSymbol::psi)
|
||||
|
||||
override val resolver get() = KtFirReferenceResolver
|
||||
}
|
||||
+2
-2
@@ -23,7 +23,7 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas
|
||||
|
||||
val renderedSymbols = executeOnPooledThreadInReadAction {
|
||||
analyze(fakeKtFile) {
|
||||
val symbols = createSymbols(symbolData, this)
|
||||
val symbols = createSymbols(symbolData)
|
||||
symbols.map { DebugSymbolRenderer.render(it) }
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ abstract class AbstractSymbolByFqNameTest : KotlinLightCodeInsightFixtureTestCas
|
||||
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 =
|
||||
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.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import java.io.File
|
||||
|
||||
object SymbolByFqName {
|
||||
@@ -36,25 +35,25 @@ object SymbolByFqName {
|
||||
}
|
||||
|
||||
sealed class SymbolData {
|
||||
abstract fun toSymbols(analysisSession: KtAnalysisSession): List<KtSymbol>
|
||||
abstract fun KtAnalysisSession.toSymbols(): List<KtSymbol>
|
||||
|
||||
data class ClassData(val classId: ClassId) : SymbolData() {
|
||||
override fun toSymbols(analysisSession: KtAnalysisSession): List<KtSymbol> {
|
||||
val symbol = analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId) ?: error("Class $classId is not found")
|
||||
override fun KtAnalysisSession.toSymbols(): List<KtSymbol> {
|
||||
val symbol = classId.getCorrespondingToplevelClassOrObjectSymbol() ?: error("Class $classId is not found")
|
||||
return listOf(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
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 symbols = if (classId == null) {
|
||||
analysisSession.symbolProvider.getTopLevelCallableSymbols(callableId.packageName, callableId.callableName).toList()
|
||||
callableId.packageName.getContainingCallableSymbolsWithName(callableId.callableName).toList()
|
||||
} else {
|
||||
val classSymbol =
|
||||
analysisSession.symbolProvider.getClassOrObjectSymbolByClassId(classId)
|
||||
classId.getCorrespondingToplevelClassOrObjectSymbol()
|
||||
?: error("Class $classId is not found")
|
||||
analysisSession.scopeProvider.getDeclaredMemberScope(classSymbol).getCallableSymbols()
|
||||
classSymbol.getDeclaredMemberScope().getCallableSymbols()
|
||||
.filter { (it as? KtNamedSymbol)?.name == callableId.callableName }
|
||||
.toList()
|
||||
}
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ abstract class AbstractResolveCallTest : @Suppress("DEPRECATION") KotlinLightCod
|
||||
val callInfos = analyze(file as KtFile) {
|
||||
elements.map { element ->
|
||||
when (element) {
|
||||
is KtCallExpression -> resolveCall(element)
|
||||
is KtBinaryExpression -> resolveCall(element)
|
||||
is KtCallExpression -> element.resolveCall()
|
||||
is KtBinaryExpression -> element.resolveCall()
|
||||
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
|
||||
|
||||
abstract class AbstractMemberScopeByFqNameTest : AbstractSymbolsByFqNameBuildingTest() {
|
||||
override fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List<KtSymbol> {
|
||||
val symbols = symbolData.toSymbols(analysisSession)
|
||||
override fun KtAnalysisSession.createSymbols(symbolData: SymbolData): List<KtSymbol> {
|
||||
val symbols = with(symbolData) { toSymbols() }
|
||||
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
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.SymbolByFqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -13,6 +12,6 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
abstract class AbstractSymbolFromLibraryPointerRestoreTest : AbstractSymbolPointerRestoreTest() {
|
||||
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> {
|
||||
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() {
|
||||
override fun KtAnalysisSession.collectSymbols(filePath: String, ktFile: KtFile): List<KtSymbol> =
|
||||
ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
||||
symbolProvider.getSymbol(declaration)
|
||||
declaration.getSymbol()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -64,7 +64,7 @@ abstract class AbstractSymbolPointerRestoreTest : KotlinLightCodeInsightFixtureT
|
||||
executeOnPooledThreadInReadAction {
|
||||
analyze(ktFile) {
|
||||
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)
|
||||
}
|
||||
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
|
||||
|
||||
abstract class AbstractSymbolsByFqNameBuildingTest : AbstractSymbolByFqNameTest() {
|
||||
override fun createSymbols(symbolData: SymbolData, analysisSession: KtAnalysisSession): List<KtSymbol> =
|
||||
symbolData.toSymbols(analysisSession)
|
||||
override fun KtAnalysisSession.createSymbols(symbolData: SymbolData): List<KtSymbol> =
|
||||
with(symbolData) { toSymbols() }
|
||||
}
|
||||
+1
-1
@@ -27,7 +27,7 @@ abstract class AbstractSymbolsByPsiBuildingTest : KotlinLightCodeInsightFixtureT
|
||||
val renderedSymbols = executeOnPooledThreadInReadAction {
|
||||
analyze(ktFile) {
|
||||
val declarationSymbols = ktFile.collectDescendantsOfType<KtDeclaration>().map { declaration ->
|
||||
symbolProvider.getSymbol(declaration)
|
||||
declaration.getSymbol()
|
||||
}
|
||||
declarationSymbols.map(DebugSymbolRenderer::render)
|
||||
}
|
||||
|
||||
+4
-4
@@ -30,8 +30,8 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
val property = fakeKtFile.declarations.single() as KtFunction
|
||||
val renderedType = executeOnPooledThreadInReadAction {
|
||||
analyze(fakeKtFile) {
|
||||
val ktType = getReturnTypeForKtDeclaration(property)
|
||||
KtTypeRenderer.render(ktType, rendererOptions)
|
||||
val ktType = property.getReturnKtType()
|
||||
ktType.render(rendererOptions)
|
||||
}
|
||||
}
|
||||
assertEquals(expected, renderedType)
|
||||
@@ -46,8 +46,8 @@ class KtTypeRendererTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
val property = fakeKtFile.declarations.single() as KtProperty
|
||||
val renderedType = executeOnPooledThreadInReadAction {
|
||||
analyze(fakeKtFile) {
|
||||
val ktType = getReturnTypeForKtDeclaration(property)
|
||||
KtTypeRenderer.render(ktType, rendererOptions)
|
||||
val ktType = property.getReturnKtType()
|
||||
ktType.render(rendererOptions)
|
||||
}
|
||||
}
|
||||
assertEquals(expected, renderedType)
|
||||
|
||||
Reference in New Issue
Block a user