[FIR] Get rid of obsolete TODOs in :fir:resolve module
This commit is contained in:
committed by
Space Team
parent
e6fbcb5567
commit
213b39f213
@@ -228,7 +228,6 @@ fun BodyResolveComponents.typeForQualifier(resolvedQualifier: FirResolvedQualifi
|
|||||||
typeForQualifierByDeclaration(declaration, resultType, session)?.let { return it }
|
typeForQualifierByDeclaration(declaration, resultType, session)?.let { return it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Handle no value type here
|
|
||||||
return session.builtinTypes.unitType
|
return session.builtinTypes.unitType
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +348,6 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: FirBasedSymbol<*>): Fir
|
|||||||
returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
|
returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
|
||||||
}
|
}
|
||||||
is FirClassifierSymbol<*> -> {
|
is FirClassifierSymbol<*> -> {
|
||||||
// TODO: unhack
|
|
||||||
buildResolvedTypeRef {
|
buildResolvedTypeRef {
|
||||||
source = null
|
source = null
|
||||||
type = symbol.constructType(emptyArray(), isNullable = false)
|
type = symbol.constructType(emptyArray(), isNullable = false)
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class FirSamResolver(
|
|||||||
val syntheticFunctionSymbol = classSymbol.createSyntheticConstructorSymbol()
|
val syntheticFunctionSymbol = classSymbol.createSyntheticConstructorSymbol()
|
||||||
|
|
||||||
val newTypeParameters = firRegularClass.typeParameters.map { typeParameter ->
|
val newTypeParameters = firRegularClass.typeParameters.map { typeParameter ->
|
||||||
val declaredTypeParameter = typeParameter.symbol.fir // TODO: or really declared?
|
val declaredTypeParameter = typeParameter.symbol.fir
|
||||||
FirTypeParameterBuilder().apply {
|
FirTypeParameterBuilder().apply {
|
||||||
source = declaredTypeParameter.source
|
source = declaredTypeParameter.source
|
||||||
moduleData = session.moduleData
|
moduleData = session.moduleData
|
||||||
@@ -143,7 +143,7 @@ class FirSamResolver(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) {
|
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) {
|
||||||
val declared = oldTypeParameter.symbol.fir // TODO: or really declared?
|
val declared = oldTypeParameter.symbol.fir
|
||||||
newTypeParameter.bounds += declared.symbol.resolvedBounds.map { typeRef ->
|
newTypeParameter.bounds += declared.symbol.resolvedBounds.map { typeRef ->
|
||||||
buildResolvedTypeRef {
|
buildResolvedTypeRef {
|
||||||
source = typeRef.source
|
source = typeRef.source
|
||||||
|
|||||||
+4
-4
@@ -134,7 +134,7 @@ abstract class AbstractConeCallConflictResolver(
|
|||||||
hasVarargs = false,
|
hasVarargs = false,
|
||||||
numDefaults = 0,
|
numDefaults = 0,
|
||||||
isExpect = (variable as? FirProperty)?.isExpect == true,
|
isExpect = (variable as? FirProperty)?.isExpect == true,
|
||||||
isSyntheticMember = false // TODO
|
isSyntheticMember = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ abstract class AbstractConeCallConflictResolver(
|
|||||||
hasVarargs = constructor.valueParameters.any { it.isVararg },
|
hasVarargs = constructor.valueParameters.any { it.isVararg },
|
||||||
numDefaults = call.numDefaults,
|
numDefaults = call.numDefaults,
|
||||||
isExpect = constructor.isExpect,
|
isExpect = constructor.isExpect,
|
||||||
isSyntheticMember = false // TODO
|
isSyntheticMember = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ abstract class AbstractConeCallConflictResolver(
|
|||||||
hasVarargs = function.valueParameters.any { it.isVararg },
|
hasVarargs = function.valueParameters.any { it.isVararg },
|
||||||
numDefaults = call.numDefaults,
|
numDefaults = call.numDefaults,
|
||||||
isExpect = function.isExpect,
|
isExpect = function.isExpect,
|
||||||
isSyntheticMember = false // TODO
|
isSyntheticMember = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ abstract class AbstractConeCallConflictResolver(
|
|||||||
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
|
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
|
||||||
emptyList(),
|
emptyList(),
|
||||||
hasExtensionReceiver = false,
|
hasExtensionReceiver = false,
|
||||||
0, // TODO
|
0,
|
||||||
hasVarargs = false,
|
hasVarargs = false,
|
||||||
numDefaults = 0,
|
numDefaults = 0,
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true,
|
isExpect = (klass as? FirRegularClass)?.isExpect == true,
|
||||||
|
|||||||
@@ -110,10 +110,7 @@ fun Candidate.resolveArgumentExpression(
|
|||||||
)
|
)
|
||||||
else
|
else
|
||||||
preprocessCallableReference(argument, expectedType, context)
|
preprocessCallableReference(argument, expectedType, context)
|
||||||
// TODO:!
|
|
||||||
is FirAnonymousFunctionExpression -> preprocessLambdaArgument(csBuilder, argument, expectedType, context, sink)
|
is FirAnonymousFunctionExpression -> preprocessLambdaArgument(csBuilder, argument, expectedType, context, sink)
|
||||||
// TODO:!
|
|
||||||
//TODO: Collection literal
|
|
||||||
is FirWrappedArgumentExpression -> resolveArgumentExpression(
|
is FirWrappedArgumentExpression -> resolveArgumentExpression(
|
||||||
csBuilder,
|
csBuilder,
|
||||||
argument.expression,
|
argument.expression,
|
||||||
@@ -344,7 +341,6 @@ private fun checkApplicabilityForArgumentType(
|
|||||||
) {
|
) {
|
||||||
if (expectedType == null) return
|
if (expectedType == null) return
|
||||||
|
|
||||||
// todo run this approximation only once for call
|
|
||||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argumentTypeBeforeCapturing, expectedType, context.session)
|
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(argumentTypeBeforeCapturing, expectedType, context.session)
|
||||||
|
|
||||||
fun subtypeError(actualExpectedType: ConeKotlinType): ResolutionDiagnostic {
|
fun subtypeError(actualExpectedType: ConeKotlinType): ResolutionDiagnostic {
|
||||||
@@ -422,7 +418,7 @@ private fun checkApplicabilityForArgumentType(
|
|||||||
val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, context.session.typeContext)
|
val nullableExpectedType = expectedType.withNullability(ConeNullability.NULLABLE, context.session.typeContext)
|
||||||
|
|
||||||
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) {
|
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, nullableExpectedType, position)) {
|
||||||
sink.reportDiagnostic(UnsafeCall(argumentType)) // TODO
|
sink.reportDiagnostic(UnsafeCall(argumentType))
|
||||||
} else {
|
} else {
|
||||||
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
|
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
|
||||||
sink.reportDiagnostic(InapplicableWrongReceiver(expectedType, argumentType))
|
sink.reportDiagnostic(InapplicableWrongReceiver(expectedType, argumentType))
|
||||||
@@ -496,8 +492,6 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
|
|||||||
): ConeKotlinType? {
|
): ConeKotlinType? {
|
||||||
if (candidateExpectedType.isSomeFunctionType(session)) return null
|
if (candidateExpectedType.isSomeFunctionType(session)) return null
|
||||||
|
|
||||||
// TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
|
||||||
|
|
||||||
val expectedFunctionType = context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType)
|
val expectedFunctionType = context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType)
|
||||||
?: return null
|
?: return null
|
||||||
return runIf(argument.isFunctional(session, scopeSession, expectedFunctionType, context.returnTypeCalculator)) {
|
return runIf(argument.isFunctional(session, scopeSession, expectedFunctionType, context.returnTypeCalculator)) {
|
||||||
@@ -527,8 +521,6 @@ private fun getExpectedTypeWithImplicintIntegerCoercion(
|
|||||||
}?.resolvedReturnType
|
}?.resolvedReturnType
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: consider adding a check that argument could be converted to the parameter type (maybe difficult for platform types)
|
|
||||||
|
|
||||||
return argumentType?.withNullability(candidateExpectedType.nullability, session.typeContext)
|
return argumentType?.withNullability(candidateExpectedType.nullability, session.typeContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -210,10 +210,10 @@ private fun processConstructors(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: why don't we use declared member scope at this point?
|
scope?.processDeclaredConstructors {
|
||||||
scope?.processDeclaredConstructors {
|
if (includeInnerConstructors || !it.fir.isInner) {
|
||||||
if (includeInnerConstructors || !it.fir.isInner) {
|
processor(it)
|
||||||
processor(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
|
|||||||
|
|
||||||
// bad function -- error on declaration side
|
// bad function -- error on declaration side
|
||||||
if (csBuilder.hasContradiction) {
|
if (csBuilder.hasContradiction) {
|
||||||
sink.yieldDiagnostic(InapplicableCandidate) //TODO: auto report it
|
sink.yieldDiagnostic(InapplicableCandidate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
|||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
val receiverKind = candidate.explicitReceiverKind
|
val receiverKind = candidate.explicitReceiverKind
|
||||||
val explicitReceiver = callInfo.explicitReceiver
|
val explicitReceiver = callInfo.explicitReceiver
|
||||||
// TODO: add invoke cases
|
|
||||||
when (receiverKind) {
|
when (receiverKind) {
|
||||||
NO_EXPLICIT_RECEIVER -> {
|
NO_EXPLICIT_RECEIVER -> {
|
||||||
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) {
|
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier && !explicitReceiver.isSuperReferenceExpression()) {
|
||||||
@@ -71,7 +70,6 @@ internal object CheckExplicitReceiverConsistency : ResolutionStage() {
|
|||||||
if (explicitReceiver == null) {
|
if (explicitReceiver == null) {
|
||||||
return sink.yieldDiagnostic(InapplicableWrongReceiver())
|
return sink.yieldDiagnostic(InapplicableWrongReceiver())
|
||||||
}
|
}
|
||||||
// Here we should also check additional invoke receiver
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +266,6 @@ object CheckDslScopeViolation : ResolutionStage() {
|
|||||||
context,
|
context,
|
||||||
{ getDslMarkersOfImplicitReceiver(thisReference.boundSymbol, receiver.typeRef.coneType, context) }
|
{ getDslMarkersOfImplicitReceiver(thisReference.boundSymbol, receiver.typeRef.coneType, context) }
|
||||||
) {
|
) {
|
||||||
// TODO: is there better alternative?
|
|
||||||
// Here we rely on the fact that receiver expression of implicit receiver value can not be changed
|
// Here we rely on the fact that receiver expression of implicit receiver value can not be changed
|
||||||
// during resolution of one single call
|
// during resolution of one single call
|
||||||
it.receiverExpression == receiver
|
it.receiverExpression == receiver
|
||||||
@@ -550,7 +547,6 @@ internal object CheckVisibility : CheckerStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration is FirConstructor) {
|
if (declaration is FirConstructor) {
|
||||||
// TODO: Should be some other form
|
|
||||||
val classSymbol = declaration.returnTypeRef.coneTypeUnsafe<ConeClassLikeType>().lookupTag.toSymbol(context.session)
|
val classSymbol = declaration.returnTypeRef.coneTypeUnsafe<ConeClassLikeType>().lookupTag.toSymbol(context.session)
|
||||||
|
|
||||||
if (classSymbol is FirRegularClassSymbol) {
|
if (classSymbol is FirRegularClassSymbol) {
|
||||||
@@ -621,10 +617,8 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() {
|
internal object PostponedVariablesInitializerResolutionStage : ResolutionStage() {
|
||||||
|
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
val argumentMapping = candidate.argumentMapping ?: return
|
val argumentMapping = candidate.argumentMapping ?: return
|
||||||
// TODO: convert type argument mapping to map [FirTypeParameterSymbol, FirTypedProjection?]
|
|
||||||
if (candidate.typeArgumentMapping is TypeArgumentMapping.Mapped) return
|
if (candidate.typeArgumentMapping is TypeArgumentMapping.Mapped) return
|
||||||
for (parameter in argumentMapping.values) {
|
for (parameter in argumentMapping.values) {
|
||||||
if (!parameter.hasBuilderInferenceAnnotation(context.session)) continue
|
if (!parameter.hasBuilderInferenceAnnotation(context.session)) continue
|
||||||
|
|||||||
+4
-8
@@ -449,8 +449,9 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should be `getOrCreateIfRealAndUnchanged(flow from LHS, flow, leftOperand)`, otherwise the statement will
|
// Ideally it should be `getOrCreateIfRealAndUnchanged(flow from LHS, flow, leftOperand)`, otherwise the statement will
|
||||||
// be added even if the value has changed in the RHS. Currently the only previous node is the RHS.
|
// be added even if the value has changed in the RHS. Currently, the only previous node is the RHS.
|
||||||
|
// But seems like everything works and with current implementation
|
||||||
val leftOperandVariable = variableStorage.getOrCreateIfReal(flow, leftOperand)
|
val leftOperandVariable = variableStorage.getOrCreateIfReal(flow, leftOperand)
|
||||||
val rightOperandVariable = variableStorage.getOrCreateIfReal(flow, rightOperand)
|
val rightOperandVariable = variableStorage.getOrCreateIfReal(flow, rightOperand)
|
||||||
if (leftOperandVariable == null && rightOperandVariable == null) return
|
if (leftOperandVariable == null && rightOperandVariable == null) return
|
||||||
@@ -751,8 +752,6 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
// Otherwise if the result is non-null, then `b` executed, which implies `a` is not null
|
// Otherwise if the result is non-null, then `b` executed, which implies `a` is not null
|
||||||
// and every statement from `b` holds.
|
// and every statement from `b` holds.
|
||||||
val expressionVariable = variableStorage.getOrCreate(flow, safeCall)
|
val expressionVariable = variableStorage.getOrCreate(flow, safeCall)
|
||||||
// TODO? if the callee has non-null return type, then safe-call == null => receiver == null
|
|
||||||
// if (x?.toString() == null) { /* x == null */ }
|
|
||||||
// TODO? all new implications in previous node's flow are valid here if receiver != null
|
// TODO? all new implications in previous node's flow are valid here if receiver != null
|
||||||
// (that requires a second level of implications: receiver != null => condition => effect).
|
// (that requires a second level of implications: receiver != null => condition => effect).
|
||||||
flow.addAllConditionally(expressionVariable notEq null, node.lastPreviousNode.flow)
|
flow.addAllConditionally(expressionVariable notEq null, node.lastPreviousNode.flow)
|
||||||
@@ -842,8 +841,6 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
if (conditionalEffects.isEmpty()) return
|
if (conditionalEffects.isEmpty()) return
|
||||||
|
|
||||||
val arguments = qualifiedAccess.orderedArguments(callee) ?: return
|
val arguments = qualifiedAccess.orderedArguments(callee) ?: return
|
||||||
// TODO: should be `getOrCreateIfRealAndUnchanged(last flow of argument i, flow, it)`
|
|
||||||
// ^-- good luck finding that
|
|
||||||
val argumentVariables = Array(arguments.size) { i -> arguments[i]?.let { variableStorage.getOrCreateIfReal(flow, it) } }
|
val argumentVariables = Array(arguments.size) { i -> arguments[i]?.let { variableStorage.getOrCreateIfReal(flow, it) } }
|
||||||
if (argumentVariables.all { it == null }) return
|
if (argumentVariables.all { it == null }) return
|
||||||
|
|
||||||
@@ -899,7 +896,6 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
if (property.isLocal || property.isVal) {
|
if (property.isLocal || property.isVal) {
|
||||||
exitVariableInitialization(flow, assignment.rValue, property, assignment.lValue, hasExplicitType = false)
|
exitVariableInitialization(flow, assignment.rValue, property, assignment.lValue, hasExplicitType = false)
|
||||||
} else {
|
} else {
|
||||||
// TODO: add unstable smartcast for non-local var
|
|
||||||
val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment)
|
val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, assignment)
|
||||||
if (variable != null) {
|
if (variable != null) {
|
||||||
logicSystem.recordNewAssignment(flow, variable, context.newAssignmentIndex())
|
logicSystem.recordNewAssignment(flow, variable, context.newAssignmentIndex())
|
||||||
@@ -946,7 +942,7 @@ abstract class FirDataFlowAnalyzer(
|
|||||||
|
|
||||||
if (isAssignment) {
|
if (isAssignment) {
|
||||||
// `propertyVariable` can be an alias to `initializerVariable`, in which case this will add
|
// `propertyVariable` can be an alias to `initializerVariable`, in which case this will add
|
||||||
// a redundant type statement which is fine...probably. TODO: store initial type within the variable?
|
// a redundant type statement which is fine...probably
|
||||||
flow.addTypeStatement(flow.unwrapVariable(propertyVariable) typeEq initializer.typeRef.coneType)
|
flow.addTypeStatement(flow.unwrapVariable(propertyVariable) typeEq initializer.typeRef.coneType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -137,7 +137,6 @@ internal class FirLocalVariableAssignmentAnalyzer {
|
|||||||
val (info, prohibitSmartCasts) = enterScope(klass.symbol, klass is FirAnonymousObject)
|
val (info, prohibitSmartCasts) = enterScope(klass.symbol, klass is FirAnonymousObject)
|
||||||
if (klass is FirAnonymousObject && info != null) {
|
if (klass is FirAnonymousObject && info != null) {
|
||||||
// Assignments in initializers and methods invalidate smart casts in other members.
|
// Assignments in initializers and methods invalidate smart casts in other members.
|
||||||
// TODO: initializers shouldn't invalidate smart casts in themselves.
|
|
||||||
prohibitSmartCasts.addAll(info.assignedInside)
|
prohibitSmartCasts.addAll(info.assignedInside)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-24
@@ -269,7 +269,7 @@ class ControlFlowGraphBuilder {
|
|||||||
// Postponed exit node was needed so we could create lambda->call edges without having the subgraph ready. If it
|
// Postponed exit node was needed so we could create lambda->call edges without having the subgraph ready. If it
|
||||||
// doesn't exist, then we probably can't do that anymore, and the lambda won't be called-in-place in the CFG.
|
// doesn't exist, then we probably can't do that anymore, and the lambda won't be called-in-place in the CFG.
|
||||||
// TODO: verify & enable this assertion?
|
// TODO: verify & enable this assertion?
|
||||||
//assert(invocationKind?.canBeVisited() != true) { "no exit node for calledInPlace($invocationKind) lambda" }
|
// assert(invocationKind?.canBeVisited() != true) { "no exit node for calledInPlace($invocationKind) lambda" }
|
||||||
return Triple(exitNode, null, graph)
|
return Triple(exitNode, null, graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +310,6 @@ class ControlFlowGraphBuilder {
|
|||||||
} else {
|
} else {
|
||||||
for ((exit, kind) in currentLevelExits) {
|
for ((exit, kind) in currentLevelExits) {
|
||||||
// Do not add data flow edges from non-terminating lambdas; there is no "dead data flow only"
|
// Do not add data flow edges from non-terminating lambdas; there is no "dead data flow only"
|
||||||
// `EdgeKind`. TODO?
|
|
||||||
if (kind.usedInCfa || !exit.isDead) {
|
if (kind.usedInCfa || !exit.isDead) {
|
||||||
// Since `node` is a union node, it is dead iff any input is dead. For once, `propagateDeadness`
|
// Since `node` is a union node, it is dead iff any input is dead. For once, `propagateDeadness`
|
||||||
// semantics are correct without an `updateDeadStatus`.
|
// semantics are correct without an `updateDeadStatus`.
|
||||||
@@ -397,7 +396,6 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val localClassEnterNode = when {
|
val localClassEnterNode = when {
|
||||||
// TODO: enum classes cannot be local so this is mostly fine, but it looks hacky. Maybe handle FirEnumEntry?
|
|
||||||
klass is FirAnonymousObject && klass.classKind != ClassKind.ENUM_ENTRY -> createAnonymousObjectEnterNode(klass)
|
klass is FirAnonymousObject && klass.classKind != ClassKind.ENUM_ENTRY -> createAnonymousObjectEnterNode(klass)
|
||||||
// Local classes are only initialized on first use, so they look pretty much like named functions:
|
// Local classes are only initialized on first use, so they look pretty much like named functions:
|
||||||
// control flow enters here and never leaves, and assignments invalidate smart casts.
|
// control flow enters here and never leaves, and assignments invalidate smart casts.
|
||||||
@@ -511,14 +509,8 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(enterNode, exitNode, preferredKind = EdgeKind.DeadForward, propagateDeadness = false)
|
addEdge(enterNode, exitNode, preferredKind = EdgeKind.DeadForward, propagateDeadness = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Here we're assuming that the methods are called after the object is constructed, which is really not true
|
// Here we're assuming that the methods are called after the object is constructed, which is really not true
|
||||||
// (init blocks can call them). But FE1.0 did so too, hence the following code compiles and prints 0:
|
// But it's fine, since Kotlin intentionally does not support analysis of "leaked this" bugs
|
||||||
// val x: Int
|
|
||||||
// object {
|
|
||||||
// fun bar() = x
|
|
||||||
// init { x = bar() }
|
|
||||||
// }
|
|
||||||
// println(x)
|
|
||||||
for (graph in calledLater) {
|
for (graph in calledLater) {
|
||||||
addEdgeToSubGraph(exitNode, graph.enterNode)
|
addEdgeToSubGraph(exitNode, graph.enterNode)
|
||||||
}
|
}
|
||||||
@@ -534,7 +526,6 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
return createAnonymousObjectExpressionExitNode(anonymousObjectExpression).also {
|
return createAnonymousObjectExpressionExitNode(anonymousObjectExpression).also {
|
||||||
val exitNode = klass.controlFlowGraphReference?.controlFlowGraph?.exitNode
|
val exitNode = klass.controlFlowGraphReference?.controlFlowGraph?.exitNode
|
||||||
// TODO: `lastNode` should be `AnonymousObjectEnterNode`, but delegate properties are somewhat broken.
|
|
||||||
if (exitNode != null && lastNode is AnonymousObjectEnterNode) {
|
if (exitNode != null && lastNode is AnonymousObjectEnterNode) {
|
||||||
addEdge(exitNode, it)
|
addEdge(exitNode, it)
|
||||||
// Fake edge to enforce ordering.
|
// Fake edge to enforce ordering.
|
||||||
@@ -879,7 +870,6 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
// These edges should really be from `enterTryMainBlockNode`, but there is no practical difference
|
// These edges should really be from `enterTryMainBlockNode`, but there is no practical difference
|
||||||
// so w/e. In fact, `enterTryExpressionNode` is just 100% redundant.
|
// so w/e. In fact, `enterTryExpressionNode` is just 100% redundant.
|
||||||
// TODO: this is more or less `addExceptionEdgesFrom(enterTryExpressionNode)`. Hmm.
|
|
||||||
for (catchEnterNode in catchNodes.top()) {
|
for (catchEnterNode in catchNodes.top()) {
|
||||||
addEdge(enterTryExpressionNode, catchEnterNode)
|
addEdge(enterTryExpressionNode, catchEnterNode)
|
||||||
}
|
}
|
||||||
@@ -904,8 +894,6 @@ class ControlFlowGraphBuilder {
|
|||||||
addEdge(node, nextNode, propagateDeadness = false)
|
addEdge(node, nextNode, propagateDeadness = false)
|
||||||
for (catchEnterNode in catchNodes.pop().asReversed()) {
|
for (catchEnterNode in catchNodes.pop().asReversed()) {
|
||||||
catchBlocksInProgress.push(catchEnterNode)
|
catchBlocksInProgress.push(catchEnterNode)
|
||||||
// TODO: figure out if this edge is correct.
|
|
||||||
// try { x = /* something non-throwing like variable read */ } catch (...) { /* can assume assignment didn't happen? */ }
|
|
||||||
addEdge(node, catchEnterNode, propagateDeadness = false)
|
addEdge(node, catchEnterNode, propagateDeadness = false)
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
@@ -915,7 +903,6 @@ class ControlFlowGraphBuilder {
|
|||||||
val catchEnterNode = catchBlocksInProgress.pop()
|
val catchEnterNode = catchBlocksInProgress.pop()
|
||||||
assert(catchEnterNode.fir == catch)
|
assert(catchEnterNode.fir == catch)
|
||||||
if (tryExitNodes.top().fir.finallyBlock != null) {
|
if (tryExitNodes.top().fir.finallyBlock != null) {
|
||||||
// TODO: not sure this does anything?
|
|
||||||
addEdge(catchEnterNode, finallyEnterNodes.top(), propagateDeadness = false, label = UncaughtExceptionPath)
|
addEdge(catchEnterNode, finallyEnterNodes.top(), propagateDeadness = false, label = UncaughtExceptionPath)
|
||||||
}
|
}
|
||||||
lastNodes.push(catchEnterNode)
|
lastNodes.push(catchEnterNode)
|
||||||
@@ -946,10 +933,6 @@ class ControlFlowGraphBuilder {
|
|||||||
val exitNode = createFinallyBlockExitNode(enterNode.fir)
|
val exitNode = createFinallyBlockExitNode(enterNode.fir)
|
||||||
popAndAddEdge(exitNode)
|
popAndAddEdge(exitNode)
|
||||||
addEdge(exitNode, tryExitNode, isDead = enterNode.allNormalInputsAreDead)
|
addEdge(exitNode, tryExitNode, isDead = enterNode.allNormalInputsAreDead)
|
||||||
// TODO: there should also be edges to outer catch blocks? Control flow can go like this:
|
|
||||||
// try { try { throw E2() } catch (e: E1) { } finally { } } catch (e: E2) { }
|
|
||||||
// \-----------------------------^ \-----------------^
|
|
||||||
// Wait, that's just `addExceptionEdgesFrom(exitNode)` again!
|
|
||||||
val nextExitLevel = levelOfNextExceptionCatchingGraph()
|
val nextExitLevel = levelOfNextExceptionCatchingGraph()
|
||||||
val nextFinally = finallyEnterNodes.topOrNull()?.takeIf { it.level > nextExitLevel }
|
val nextFinally = finallyEnterNodes.topOrNull()?.takeIf { it.level > nextExitLevel }
|
||||||
if (nextFinally != null) {
|
if (nextFinally != null) {
|
||||||
@@ -984,7 +967,12 @@ class ControlFlowGraphBuilder {
|
|||||||
for (node in nodes) {
|
for (node in nodes) {
|
||||||
when {
|
when {
|
||||||
// TODO: this check is imprecise and can add redundant edges:
|
// TODO: this check is imprecise and can add redundant edges:
|
||||||
// x@{ try { return@x } finally {}; try {} finally { /* return@x target is in nonDirectJumps */ }
|
// x@{
|
||||||
|
// try {
|
||||||
|
// return@x
|
||||||
|
// } finally {}
|
||||||
|
// }
|
||||||
|
// try {} finally { /* return@x target is in nonDirectJumps */ }
|
||||||
node.level < minLevel || node !in nonDirectJumps -> continue
|
node.level < minLevel || node !in nonDirectJumps -> continue
|
||||||
// TODO: if the input to finally with that label is dead, then so should be the exit probably
|
// TODO: if the input to finally with that label is dead, then so should be the exit probably
|
||||||
node.returnPathIsBackwards -> addBackEdge(this, node, label = node)
|
node.returnPathIsBackwards -> addBackEdge(this, node, label = node)
|
||||||
@@ -1038,7 +1026,7 @@ class ControlFlowGraphBuilder {
|
|||||||
|
|
||||||
// this is a workaround to make function call dead when call is completed _after_ building its node in the graph
|
// this is a workaround to make function call dead when call is completed _after_ building its node in the graph
|
||||||
// this happens when completing the last call in try/catch blocks
|
// this happens when completing the last call in try/catch blocks
|
||||||
// todo this doesn't make fully 'right' Nothing node (doesn't support going to catch and pass through finally)
|
// TODO: this doesn't make fully 'right' Nothing node (doesn't support going to catch and pass through finally)
|
||||||
// because doing those afterwards is quite challenging
|
// because doing those afterwards is quite challenging
|
||||||
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
|
// it would be much easier if we could build calls after full completion only, at least for Nothing calls
|
||||||
// @returns `true` if node actually returned Nothing
|
// @returns `true` if node actually returned Nothing
|
||||||
@@ -1164,7 +1152,6 @@ class ControlFlowGraphBuilder {
|
|||||||
fun enterFakeExpression(): FakeExpressionEnterNode {
|
fun enterFakeExpression(): FakeExpressionEnterNode {
|
||||||
// Things like annotations and `contract { ... }` use normal call resolution, but aren't real expressions
|
// Things like annotations and `contract { ... }` use normal call resolution, but aren't real expressions
|
||||||
// and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away.
|
// and are never evaluated. We'll push all nodes created in the process into a stub graph, then throw it away.
|
||||||
// TODO: don't waste time creating the nodes in the first place
|
|
||||||
return enterGraph(null, "<compile-time expression graph>", ControlFlowGraph.Kind.FakeCall) {
|
return enterGraph(null, "<compile-time expression graph>", ControlFlowGraph.Kind.FakeCall) {
|
||||||
createFakeExpressionEnterNode() to createFakeExpressionEnterNode()
|
createFakeExpressionEnterNode() to createFakeExpressionEnterNode()
|
||||||
}
|
}
|
||||||
@@ -1188,7 +1175,6 @@ class ControlFlowGraphBuilder {
|
|||||||
// ----------------------------------- Block -----------------------------------
|
// ----------------------------------- Block -----------------------------------
|
||||||
|
|
||||||
fun enterInitBlock(initBlock: FirAnonymousInitializer): InitBlockEnterNode {
|
fun enterInitBlock(initBlock: FirAnonymousInitializer): InitBlockEnterNode {
|
||||||
// TODO: questionable moment that we should pass data flow from init to init
|
|
||||||
return enterGraph(initBlock, "init block", ControlFlowGraph.Kind.ClassInitializer) {
|
return enterGraph(initBlock, "init block", ControlFlowGraph.Kind.ClassInitializer) {
|
||||||
createInitBlockEnterNode(it) to createInitBlockExitNode(it)
|
createInitBlockEnterNode(it) to createInitBlockExitNode(it)
|
||||||
}.also { addEdgeIfLocalClassMember(it) }
|
}.also { addEdgeIfLocalClassMember(it) }
|
||||||
|
|||||||
-2
@@ -125,8 +125,6 @@ class FirControlFlowGraphRenderVisitor(
|
|||||||
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
|
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
|
||||||
if (controlFlowGraph.isSubGraph) return
|
if (controlFlowGraph.isSubGraph) return
|
||||||
|
|
||||||
// TODO: nodes are already in a topological order, but grouping nodes into clusters requires something more.
|
|
||||||
// But what exactly? And is there a way to do `renderNodes` differently so that any topological order is ok?
|
|
||||||
val nodes = DFS.topologicalOrder(listOf(controlFlowGraph.enterNode)) { it.followingNodes }
|
val nodes = DFS.topologicalOrder(listOf(controlFlowGraph.enterNode)) { it.followingNodes }
|
||||||
.associateWithTo(linkedMapOf()) { nodeCounter++ }
|
.associateWithTo(linkedMapOf()) { nodeCounter++ }
|
||||||
printer.renderNodes(nodes)
|
printer.renderNodes(nodes)
|
||||||
|
|||||||
+2
-3
@@ -233,7 +233,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
|
|||||||
is ResolvedCallableReferenceAtom ->
|
is ResolvedCallableReferenceAtom ->
|
||||||
argument.reviseExpectedType(revisedExpectedType)
|
argument.reviseExpectedType(revisedExpectedType)
|
||||||
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
||||||
argument.transformToResolvedLambda(c.getBuilder(), resolutionContext, revisedExpectedType, null /*TODO()*/)
|
argument.transformToResolvedLambda(c.getBuilder(), resolutionContext, revisedExpectedType)
|
||||||
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
|
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +338,6 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
|
|||||||
fun ConeTypeVariable?.toTypeConstructor(): TypeConstructorMarker? =
|
fun ConeTypeVariable?.toTypeConstructor(): TypeConstructorMarker? =
|
||||||
this?.typeConstructor?.takeIf { it in notFixedTypeVariables.keys }
|
this?.typeConstructor?.takeIf { it in notFixedTypeVariables.keys }
|
||||||
|
|
||||||
// TODO: non-top-level variables?
|
|
||||||
fun PostponedAtomWithRevisableExpectedType.collectNotFixedVariables() {
|
fun PostponedAtomWithRevisableExpectedType.collectNotFixedVariables() {
|
||||||
revisedExpectedType?.lowerBoundIfFlexible()?.asArgumentList()?.let { typeArgumentList ->
|
revisedExpectedType?.lowerBoundIfFlexible()?.asArgumentList()?.let { typeArgumentList ->
|
||||||
for (typeArgument in typeArgumentList) {
|
for (typeArgument in typeArgumentList) {
|
||||||
@@ -402,7 +401,7 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
|
|||||||
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
|
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
|
||||||
)
|
)
|
||||||
val variable = variableWithConstraints.typeVariable
|
val variable = variableWithConstraints.typeVariable
|
||||||
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable)) // TODO: obtain atom for diagnostics
|
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+1
-1
@@ -92,7 +92,7 @@ abstract class FirInferenceSessionForChainedResolve(
|
|||||||
lowerSubstituted,
|
lowerSubstituted,
|
||||||
upperSubstituted,
|
upperSubstituted,
|
||||||
this.constraintKind,
|
this.constraintKind,
|
||||||
ConeBuilderInferenceSubstitutionConstraintPosition(this) // TODO
|
ConeBuilderInferenceSubstitutionConstraintPosition(this)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-2
@@ -63,8 +63,6 @@ class PostponedArgumentsAnalyzer(
|
|||||||
analyzeLambda(c, argument.transformToResolvedLambda(c.getBuilder(), resolutionContext), candidate, completionMode)
|
analyzeLambda(c, argument.transformToResolvedLambda(c.getBuilder(), resolutionContext), candidate, completionMode)
|
||||||
|
|
||||||
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
|
is ResolvedCallableReferenceAtom -> processCallableReference(argument, candidate)
|
||||||
|
|
||||||
// is ResolvedCollectionLiteralAtom -> TODO("Not supported")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -412,7 +412,6 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
|||||||
userTypeRef: FirUserTypeRef,
|
userTypeRef: FirUserTypeRef,
|
||||||
qualifierPartArgumentsCount: Int?
|
qualifierPartArgumentsCount: Int?
|
||||||
): ConeErrorType? {
|
): ConeErrorType? {
|
||||||
// TODO: It should be TYPE_ARGUMENTS_NOT_ALLOWED diagnostics when parameterClass is null
|
|
||||||
val actualTypeParametersCount = getActualTypeParametersCount(parameterClass ?: symbol.fir)
|
val actualTypeParametersCount = getActualTypeParametersCount(parameterClass ?: symbol.fir)
|
||||||
|
|
||||||
if (qualifierPartArgumentsCount == null || actualTypeParametersCount != qualifierPartArgumentsCount) {
|
if (qualifierPartArgumentsCount == null || actualTypeParametersCount != qualifierPartArgumentsCount) {
|
||||||
|
|||||||
-4
@@ -163,8 +163,6 @@ private class FirApplySupertypesTransformer(
|
|||||||
private fun applyResolvedSupertypesToClass(firClass: FirClass) {
|
private fun applyResolvedSupertypesToClass(firClass: FirClass) {
|
||||||
if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef || it is FirImplicitBuiltinTypeRef }) {
|
if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef || it is FirImplicitBuiltinTypeRef }) {
|
||||||
val supertypeRefs = getResolvedSupertypeRefs(firClass)
|
val supertypeRefs = getResolvedSupertypeRefs(firClass)
|
||||||
|
|
||||||
// TODO: Replace with an immutable version or transformer
|
|
||||||
firClass.replaceSuperTypeRefs(supertypeRefs)
|
firClass.replaceSuperTypeRefs(supertypeRefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +194,6 @@ private class FirApplySupertypesTransformer(
|
|||||||
"Expected single supertypeRefs, but found ${supertypeRefs.size} in ${typeAlias.symbol.classId}"
|
"Expected single supertypeRefs, but found ${supertypeRefs.size} in ${typeAlias.symbol.classId}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace with an immutable version or transformer
|
|
||||||
typeAlias.replaceExpandedTypeRef(supertypeRefs[0])
|
typeAlias.replaceExpandedTypeRef(supertypeRefs[0])
|
||||||
return typeAlias
|
return typeAlias
|
||||||
}
|
}
|
||||||
@@ -521,7 +518,6 @@ open class FirSupertypeResolverVisitor(
|
|||||||
expandedTypeRef: FirTypeRef,
|
expandedTypeRef: FirTypeRef,
|
||||||
resolveRecursively: Boolean,
|
resolveRecursively: Boolean,
|
||||||
): List<FirResolvedTypeRef> {
|
): List<FirResolvedTypeRef> {
|
||||||
// TODO: this if is a temporary hack for built-in types (because we can't load file for them)
|
|
||||||
if (expandedTypeRef is FirResolvedTypeRef) {
|
if (expandedTypeRef is FirResolvedTypeRef) {
|
||||||
return listOf(expandedTypeRef)
|
return listOf(expandedTypeRef)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -41,7 +41,7 @@ internal fun remapArgumentsWithVararg(
|
|||||||
var indexAfterVarargs = argumentList.size
|
var indexAfterVarargs = argumentList.size
|
||||||
val newArgumentMapping = linkedMapOf<FirExpression, FirValueParameter>()
|
val newArgumentMapping = linkedMapOf<FirExpression, FirValueParameter>()
|
||||||
val varargArgument = buildVarargArgumentsExpression {
|
val varargArgument = buildVarargArgumentsExpression {
|
||||||
//todo ideally we should use here a source from the use-site and not from the declaration-site
|
// TODO: ideally we should use here a source from the use-site and not from the declaration-site
|
||||||
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType, KtFakeSourceElementKind.VarargArgument)
|
this.varargElementType = varargParameterTypeRef.withReplacedConeType(varargElementType, KtFakeSourceElementKind.VarargArgument)
|
||||||
this.typeRef = varargParameterTypeRef.withReplacedConeType(varargArrayType, KtFakeSourceElementKind.VarargArgument)
|
this.typeRef = varargParameterTypeRef.withReplacedConeType(varargArrayType, KtFakeSourceElementKind.VarargArgument)
|
||||||
var startOffset = Int.MAX_VALUE
|
var startOffset = Int.MAX_VALUE
|
||||||
|
|||||||
+1
-3
@@ -434,8 +434,7 @@ open class FirDeclarationsResolveTransformer(
|
|||||||
return variable
|
return variable
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This enum might actually be a boolean (resolve setter/don't resolve setter)
|
// In IDE there's a need to resolve setter's parameter types on the implicit-resolution stage
|
||||||
// But for some reason, in IDE there's a need to resolve setter's parameter types on the implicit-resolution stage
|
|
||||||
// See ad183434137939a0c9eeea2f7df9ef522672a18e commit.
|
// See ad183434137939a0c9eeea2f7df9ef522672a18e commit.
|
||||||
// But for delegate inference case, we don't need both body of the setter and its parameter resolved (SKIP mode)
|
// But for delegate inference case, we don't need both body of the setter and its parameter resolved (SKIP mode)
|
||||||
private enum class SetterResolutionMode {
|
private enum class SetterResolutionMode {
|
||||||
@@ -630,7 +629,6 @@ open class FirDeclarationsResolveTransformer(
|
|||||||
return context.withSimpleFunction(simpleFunction, session) {
|
return context.withSimpleFunction(simpleFunction, session) {
|
||||||
doTransformTypeParameters(simpleFunction)
|
doTransformTypeParameters(simpleFunction)
|
||||||
|
|
||||||
// TODO: I think it worth creating something like runAllPhasesForLocalFunction
|
|
||||||
if (containingDeclaration != null && containingDeclaration !is FirClass) {
|
if (containingDeclaration != null && containingDeclaration !is FirClass) {
|
||||||
// For class members everything should be already prepared
|
// For class members everything should be already prepared
|
||||||
prepareSignatureForBodyResolve(simpleFunction)
|
prepareSignatureForBodyResolve(simpleFunction)
|
||||||
|
|||||||
-1
@@ -104,7 +104,6 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
|
|||||||
qualifiedAccessExpression.transformTypeArguments(transformer, ResolutionMode.ContextIndependent)
|
qualifiedAccessExpression.transformTypeArguments(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
|
||||||
var result = when (val callee = qualifiedAccessExpression.calleeReference) {
|
var result = when (val callee = qualifiedAccessExpression.calleeReference) {
|
||||||
// TODO: there was FirExplicitThisReference
|
|
||||||
is FirThisReference -> {
|
is FirThisReference -> {
|
||||||
val labelName = callee.labelName
|
val labelName = callee.labelName
|
||||||
val implicitReceiver = implicitReceiverStack[labelName]
|
val implicitReceiver = implicitReceiverStack[labelName]
|
||||||
|
|||||||
-1
@@ -301,7 +301,6 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
|
private fun <T : FirContractDescriptionOwner> transformOwnerOfErrorContract(owner: T): T {
|
||||||
// TODO
|
|
||||||
dataFlowAnalyzer.exitContractDescription()
|
dataFlowAnalyzer.exitContractDescription()
|
||||||
return owner
|
return owner
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -244,7 +244,6 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
|
|||||||
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
|
annotationCall.replaceAnnotationTypeRef(transformedAnnotationType)
|
||||||
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
|
annotationCall.replaceAnnotationResolvePhase(FirAnnotationResolvePhase.CompilerRequiredAnnotations)
|
||||||
|
|
||||||
// TODO: what if we have type alias here?
|
|
||||||
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
|
if (transformedAnnotationType.coneTypeSafe<ConeClassLikeType>()?.lookupTag?.classId in REQUIRED_ANNOTATIONS_WITH_ARGUMENTS) {
|
||||||
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
|
argumentsTransformer.transformAnnotation(annotationCall, ResolutionMode.ContextDependent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ private fun doCreateImportingScopes(
|
|||||||
else ->
|
else ->
|
||||||
FirPackageMemberScope(file.packageFqName, session, excludedNames = excludedNamesInPackage)
|
FirPackageMemberScope(file.packageFqName, session, excludedNames = excludedNamesInPackage)
|
||||||
},
|
},
|
||||||
// TODO: explicit simple importing scope should have highest priority (higher than inner scopes added in process)
|
|
||||||
FirExplicitSimpleImportingScope(file.imports, session, scopeSession)
|
FirExplicitSimpleImportingScope(file.imports, session, scopeSession)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user