Reformat 'frontend' module according to new codestyle

This commit is contained in:
Dmitry Savvinov
2018-01-16 10:57:56 +03:00
parent b567817d1f
commit e5f0ffb0c2
204 changed files with 3869 additions and 3395 deletions
@@ -77,19 +77,23 @@ open class AnalysisResult protected constructor(
companion object { companion object {
val EMPTY: AnalysisResult = success(BindingContext.EMPTY, ErrorUtils.getErrorModule()) val EMPTY: AnalysisResult = success(BindingContext.EMPTY, ErrorUtils.getErrorModule())
@JvmStatic fun success(bindingContext: BindingContext, module: ModuleDescriptor): AnalysisResult { @JvmStatic
fun success(bindingContext: BindingContext, module: ModuleDescriptor): AnalysisResult {
return AnalysisResult(bindingContext, module, true) return AnalysisResult(bindingContext, module, true)
} }
@JvmStatic fun success(bindingContext: BindingContext, module: ModuleDescriptor, shouldGenerateCode: Boolean): AnalysisResult { @JvmStatic
fun success(bindingContext: BindingContext, module: ModuleDescriptor, shouldGenerateCode: Boolean): AnalysisResult {
return AnalysisResult(bindingContext, module, shouldGenerateCode) return AnalysisResult(bindingContext, module, shouldGenerateCode)
} }
@JvmStatic fun internalError(bindingContext: BindingContext, error: Throwable): AnalysisResult { @JvmStatic
fun internalError(bindingContext: BindingContext, error: Throwable): AnalysisResult {
return InternalError(bindingContext, error) return InternalError(bindingContext, error)
} }
@JvmStatic fun compilationError(bindingContext: BindingContext): AnalysisResult { @JvmStatic
fun compilationError(bindingContext: BindingContext): AnalysisResult {
return CompilationError(bindingContext) return CompilationError(bindingContext)
} }
} }
@@ -122,14 +122,17 @@ class ConstructorConsistencyChecker private constructor(
fun handleLeakingThis(expression: KtExpression) { fun handleLeakingThis(expression: KtExpression) {
if (!finalClass) { if (!finalClass) {
trace.record(BindingContext.LEAKING_THIS, target(expression), trace.record(
LeakingThisDescriptor.NonFinalClass(classDescriptor, classOrObject)) BindingContext.LEAKING_THIS, target(expression),
} LeakingThisDescriptor.NonFinalClass(classDescriptor, classOrObject)
else { )
} else {
val uninitializedProperty = firstUninitializedNotNullProperty() val uninitializedProperty = firstUninitializedNotNullProperty()
if (uninitializedProperty != null) { if (uninitializedProperty != null) {
trace.record(BindingContext.LEAKING_THIS, target(expression), trace.record(
LeakingThisDescriptor.PropertyIsNull(uninitializedProperty, classOrObject)) BindingContext.LEAKING_THIS, target(expression),
LeakingThisDescriptor.PropertyIsNull(uninitializedProperty, classOrObject)
)
} }
} }
} }
@@ -153,8 +156,7 @@ class ConstructorConsistencyChecker private constructor(
if (!safeCallUsage(element)) { if (!safeCallUsage(element)) {
handleLeakingThis(element) handleLeakingThis(element)
} }
} } else if (element is KtReferenceExpression) {
else if (element is KtReferenceExpression) {
if (!safeReferenceUsage(element)) { if (!safeReferenceUsage(element)) {
handleLeakingThis(element) handleLeakingThis(element)
} }
@@ -106,22 +106,26 @@ interface ControlFlowBuilder {
instructionElement: KtElement, instructionElement: KtElement,
valueElement: KtElement?, valueElement: KtElement?,
inputValues: List<PseudoValue>, inputValues: List<PseudoValue>,
kind: MagicKind): MagicInstruction kind: MagicKind
): MagicInstruction
fun merge( fun merge(
expression: KtExpression, expression: KtExpression,
inputValues: List<PseudoValue>): MergeInstruction inputValues: List<PseudoValue>
): MergeInstruction
fun readVariable( fun readVariable(
expression: KtExpression, expression: KtExpression,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction receiverValues: Map<PseudoValue, ReceiverValue>
): ReadValueInstruction
fun call( fun call(
valueElement: KtElement, valueElement: KtElement,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
receiverValues: Map<PseudoValue, ReceiverValue>, receiverValues: Map<PseudoValue, ReceiverValue>,
arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction arguments: Map<PseudoValue, ValueParameterDescriptor>
): CallInstruction
enum class PredefinedOperation { enum class PredefinedOperation {
AND, AND,
@@ -132,7 +136,8 @@ interface ControlFlowBuilder {
fun predefinedOperation( fun predefinedOperation(
expression: KtExpression, expression: KtExpression,
operation: PredefinedOperation, operation: PredefinedOperation,
inputValues: List<PseudoValue>): OperationInstruction inputValues: List<PseudoValue>
): OperationInstruction
fun read(element: KtElement, target: AccessTarget, receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction fun read(element: KtElement, target: AccessTarget, receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction
@@ -141,5 +146,6 @@ interface ControlFlowBuilder {
lValue: KtElement, lValue: KtElement,
rValue: PseudoValue, rValue: PseudoValue,
target: AccessTarget, target: AccessTarget,
receiverValues: Map<PseudoValue, ReceiverValue>) receiverValues: Map<PseudoValue, ReceiverValue>
)
} }
@@ -49,7 +49,8 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
instructionElement: KtElement, instructionElement: KtElement,
valueElement: KtElement?, valueElement: KtElement?,
inputValues: List<PseudoValue>, inputValues: List<PseudoValue>,
kind: MagicKind): MagicInstruction = delegateBuilder.magic(instructionElement, valueElement, inputValues, kind) kind: MagicKind
): MagicInstruction = delegateBuilder.magic(instructionElement, valueElement, inputValues, kind)
override fun merge(expression: KtExpression, inputValues: List<PseudoValue>): MergeInstruction = override fun merge(expression: KtExpression, inputValues: List<PseudoValue>): MergeInstruction =
delegateBuilder.merge(expression, inputValues) delegateBuilder.merge(expression, inputValues)
@@ -57,20 +58,23 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
override fun readVariable( override fun readVariable(
expression: KtExpression, expression: KtExpression,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
receiverValues: Map<PseudoValue, ReceiverValue>): ReadValueInstruction = receiverValues: Map<PseudoValue, ReceiverValue>
): ReadValueInstruction =
delegateBuilder.readVariable(expression, resolvedCall, receiverValues) delegateBuilder.readVariable(expression, resolvedCall, receiverValues)
override fun call( override fun call(
valueElement: KtElement, valueElement: KtElement,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
receiverValues: Map<PseudoValue, ReceiverValue>, receiverValues: Map<PseudoValue, ReceiverValue>,
arguments: Map<PseudoValue, ValueParameterDescriptor>): CallInstruction = arguments: Map<PseudoValue, ValueParameterDescriptor>
): CallInstruction =
delegateBuilder.call(valueElement, resolvedCall, receiverValues, arguments) delegateBuilder.call(valueElement, resolvedCall, receiverValues, arguments)
override fun predefinedOperation( override fun predefinedOperation(
expression: KtExpression, expression: KtExpression,
operation: ControlFlowBuilder.PredefinedOperation, operation: ControlFlowBuilder.PredefinedOperation,
inputValues: List<PseudoValue>): OperationInstruction = delegateBuilder.predefinedOperation(expression, operation, inputValues) inputValues: List<PseudoValue>
): OperationInstruction = delegateBuilder.predefinedOperation(expression, operation, inputValues)
override fun createUnboundLabel(): Label = delegateBuilder.createUnboundLabel() override fun createUnboundLabel(): Label = delegateBuilder.createUnboundLabel()
@@ -164,7 +168,8 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
lValue: KtElement, lValue: KtElement,
rValue: PseudoValue, rValue: PseudoValue,
target: AccessTarget, target: AccessTarget,
receiverValues: Map<PseudoValue, ReceiverValue>) { receiverValues: Map<PseudoValue, ReceiverValue>
) {
delegateBuilder.write(assignment, lValue, rValue, target, receiverValues) delegateBuilder.write(assignment, lValue, rValue, target, receiverValues)
} }
@@ -161,8 +161,7 @@ class ControlFlowInformationProvider private constructor(
override fun visitInstruction(instruction: Instruction) { override fun visitInstruction(instruction: Instruction) {
if (instruction is KtElementInstruction) { if (instruction is KtElementInstruction) {
returnedExpressions.add(instruction.element) returnedExpressions.add(instruction.element)
} } else {
else {
throw IllegalStateException("$instruction precedes the exit point") throw IllegalStateException("$instruction precedes the exit point")
} }
} }
@@ -252,8 +251,7 @@ class ControlFlowInformationProvider private constructor(
if (instruction.dead) { if (instruction.dead) {
unreachableElements.add(element) unreachableElements.add(element)
} } else {
else {
reachableElements.add(element) reachableElements.add(element)
} }
} }
@@ -274,8 +272,7 @@ class ControlFlowInformationProvider private constructor(
val reportedDiagnosticMap = hashMapOf<Instruction, DiagnosticFactory<*>>() val reportedDiagnosticMap = hashMapOf<Instruction, DiagnosticFactory<*>>()
pseudocode.traverse(TraversalOrder.FORWARD, initializers) { pseudocode.traverse(TraversalOrder.FORWARD, initializers) { instruction: Instruction,
instruction: Instruction,
enterData: ReadOnlyInitControlFlowInfo, enterData: ReadOnlyInitControlFlowInfo,
exitData: ReadOnlyInitControlFlowInfo -> exitData: ReadOnlyInitControlFlowInfo ->
@@ -291,8 +288,10 @@ class ControlFlowInformationProvider private constructor(
} }
if (instruction !is WriteValueInstruction) return@traverse if (instruction !is WriteValueInstruction) return@traverse
val element = instruction.lValue as? KtExpression ?: return@traverse val element = instruction.lValue as? KtExpression ?: return@traverse
var error = checkValReassignment(ctxt, element, instruction, var error = checkValReassignment(
varWithValReassignErrorGenerated) ctxt, element, instruction,
varWithValReassignErrorGenerated
)
if (!error && processClassOrObject) { if (!error && processClassOrObject) {
error = checkAssignmentBeforeDeclaration(ctxt, element) error = checkAssignmentBeforeDeclaration(ctxt, element)
} }
@@ -333,8 +332,7 @@ class ControlFlowInformationProvider private constructor(
if (!isDefinitelyInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) { if (!isDefinitelyInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
if (variableDescriptor !is PropertyDescriptor) { if (variableDescriptor !is PropertyDescriptor) {
variableDescriptor?.let { varWithUninitializedErrorGenerated.add(it) } variableDescriptor?.let { varWithUninitializedErrorGenerated.add(it) }
} } else if (variableDescriptor.isLateInit) {
else if (variableDescriptor.isLateInit) {
trace.record(MUST_BE_LATEINIT, variableDescriptor) trace.record(MUST_BE_LATEINIT, variableDescriptor)
return return
} }
@@ -352,7 +350,8 @@ class ControlFlowInformationProvider private constructor(
report(Errors.UNINITIALIZED_ENUM_COMPANION.on(element, container), ctxt) report(Errors.UNINITIALIZED_ENUM_COMPANION.on(element, container), ctxt)
} }
} }
else -> {} else -> {
}
} }
} }
is VariableDescriptor -> is VariableDescriptor ->
@@ -424,8 +423,12 @@ class ControlFlowInformationProvider private constructor(
if (Visibilities.isVisible(receiverValue, variableDescriptor, descriptor) if (Visibilities.isVisible(receiverValue, variableDescriptor, descriptor)
&& setterDescriptor != null && setterDescriptor != null
&& !Visibilities.isVisible(receiverValue, setterDescriptor, descriptor)) { && !Visibilities.isVisible(receiverValue, setterDescriptor, descriptor)) {
report(Errors.INVISIBLE_SETTER.on(expression, variableDescriptor, setterDescriptor.visibility, report(
setterDescriptor), ctxt) Errors.INVISIBLE_SETTER.on(
expression, variableDescriptor, setterDescriptor.visibility,
setterDescriptor
), ctxt
)
return true return true
} }
} }
@@ -462,16 +465,13 @@ class ControlFlowInformationProvider private constructor(
if (captured && !mayBeInitializedNotHere && hasBackingField && isThisOrNoDispatchReceiver) { if (captured && !mayBeInitializedNotHere && hasBackingField && isThisOrNoDispatchReceiver) {
if (variableDescriptor.containingDeclaration is ClassDescriptor) { if (variableDescriptor.containingDeclaration is ClassDescriptor) {
report(Errors.CAPTURED_MEMBER_VAL_INITIALIZATION.on(expression, variableDescriptor), ctxt) report(Errors.CAPTURED_MEMBER_VAL_INITIALIZATION.on(expression, variableDescriptor), ctxt)
} } else {
else {
report(Errors.CAPTURED_VAL_INITIALIZATION.on(expression, variableDescriptor), ctxt) report(Errors.CAPTURED_VAL_INITIALIZATION.on(expression, variableDescriptor), ctxt)
} }
} } else {
else {
if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) { if (KtPsiUtil.isBackingFieldReference(variableDescriptor)) {
reportValReassigned(expression, variableDescriptor, ctxt) reportValReassigned(expression, variableDescriptor, ctxt)
} } else {
else {
report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt) report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor), ctxt)
} }
} }
@@ -502,8 +502,7 @@ class ControlFlowInformationProvider private constructor(
report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, ctxt.variableDescriptor), ctxt) report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, ctxt.variableDescriptor), ctxt)
} }
true true
} } else {
else {
false false
} }
@@ -533,8 +532,7 @@ class ControlFlowInformationProvider private constructor(
val variable = if (expression is KtDotQualifiedExpression && val variable = if (expression is KtDotQualifiedExpression &&
expression.receiverExpression is KtThisExpression) { expression.receiverExpression is KtThisExpression) {
expression.selectorExpression expression.selectorExpression
} } else {
else {
expression expression
} }
if (variable is KtSimpleNameExpression) { if (variable is KtSimpleNameExpression) {
@@ -566,15 +564,15 @@ class ControlFlowInformationProvider private constructor(
val reportedDiagnosticMap = hashMapOf<Instruction, DiagnosticFactory<*>>() val reportedDiagnosticMap = hashMapOf<Instruction, DiagnosticFactory<*>>()
val unusedValueExpressions = hashMapOf<KtExpression, Pair<VariableDescriptor, VariableUseContext>>() val unusedValueExpressions = hashMapOf<KtExpression, Pair<VariableDescriptor, VariableUseContext>>()
val usedValueExpressions = hashSetOf<KtExpression>() val usedValueExpressions = hashSetOf<KtExpression>()
pseudocode.traverse(TraversalOrder.BACKWARD, variableStatusData) { pseudocode.traverse(TraversalOrder.BACKWARD, variableStatusData) { instruction: Instruction,
instruction: Instruction,
enterData: ReadOnlyUseControlFlowInfo, enterData: ReadOnlyUseControlFlowInfo,
_: ReadOnlyUseControlFlowInfo -> _: ReadOnlyUseControlFlowInfo ->
val ctxt = VariableUseContext(instruction, reportedDiagnosticMap) val ctxt = VariableUseContext(instruction, reportedDiagnosticMap)
val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false) val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false)
val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny( val variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
instruction, trace.bindingContext) instruction, trace.bindingContext
)
if (variableDescriptor == null if (variableDescriptor == null
|| !declaredVariables.contains(variableDescriptor) || !declaredVariables.contains(variableDescriptor)
|| !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) { || !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) {
@@ -587,8 +585,7 @@ class ControlFlowInformationProvider private constructor(
val expressionInQuestion = instruction.element as? KtExpression ?: return@traverse val expressionInQuestion = instruction.element as? KtExpression ?: return@traverse
if (variableUseState != READ) { if (variableUseState != READ) {
unusedValueExpressions.put(expressionInQuestion, variableDescriptor to ctxt) unusedValueExpressions.put(expressionInQuestion, variableDescriptor to ctxt)
} } else {
else {
usedValueExpressions.add(expressionInQuestion) usedValueExpressions.add(expressionInQuestion)
} }
} }
@@ -637,11 +634,9 @@ class ControlFlowInformationProvider private constructor(
element is KtParameter -> element is KtParameter ->
processUnusedParameter(ctxt, element, variableDescriptor) processUnusedParameter(ctxt, element, variableDescriptor)
} }
} } else if (variableUseState === ONLY_WRITTEN_NEVER_READ && KtPsiUtil.isRemovableVariableDeclaration(element)) {
else if (variableUseState === ONLY_WRITTEN_NEVER_READ && KtPsiUtil.isRemovableVariableDeclaration(element)) {
report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on(element, variableDescriptor), ctxt) report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on(element, variableDescriptor), ctxt)
} } else if (variableUseState === WRITTEN_AFTER_READ && element is KtVariableDeclaration) {
else if (variableUseState === WRITTEN_AFTER_READ && element is KtVariableDeclaration) {
when (element) { when (element) {
is KtProperty -> is KtProperty ->
element.initializer?.let { element.initializer?.let {
@@ -691,8 +686,7 @@ class ControlFlowInformationProvider private constructor(
} }
if (anonymous) { if (anonymous) {
report(UNUSED_ANONYMOUS_PARAMETER.on(element, variableDescriptor), ctxt) report(UNUSED_ANONYMOUS_PARAMETER.on(element, variableDescriptor), ctxt)
} } else {
else {
report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt) report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt)
} }
} }
@@ -711,10 +705,12 @@ class ControlFlowInformationProvider private constructor(
if (element.isUsedAsStatement(trace.bindingContext) && instruction.sideEffectFree) { if (element.isUsedAsStatement(trace.bindingContext) && instruction.sideEffectFree) {
val context = VariableContext(instruction, reportedDiagnosticMap) val context = VariableContext(instruction, reportedDiagnosticMap)
report(when (element) { report(
when (element) {
is KtLambdaExpression -> Errors.UNUSED_LAMBDA_EXPRESSION.on(element) is KtLambdaExpression -> Errors.UNUSED_LAMBDA_EXPRESSION.on(element)
else -> Errors.UNUSED_EXPRESSION.on(element) else -> Errors.UNUSED_EXPRESSION.on(element)
}, context) }, context
)
} }
} }
} }
@@ -745,8 +741,7 @@ class ControlFlowInformationProvider private constructor(
if (thenExpression == null || elseExpression == null) { if (thenExpression == null || elseExpression == null) {
trace.report(INVALID_IF_AS_EXPRESSION.on(element.ifKeyword)) trace.report(INVALID_IF_AS_EXPRESSION.on(element.ifKeyword))
} } else {
else {
checkImplicitCastOnConditionalExpression(element) checkImplicitCastOnConditionalExpression(element)
} }
} }
@@ -811,8 +806,7 @@ class ControlFlowInformationProvider private constructor(
if (usedAsExpression && missingCases.isNotEmpty()) { if (usedAsExpression && missingCases.isNotEmpty()) {
if (elseEntry != null) continue if (elseEntry != null) continue
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases)) trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
} } else if (subjectExpression != null) {
else if (subjectExpression != null) {
val subjectType = trace.getType(subjectExpression) val subjectType = trace.getType(subjectExpression)
if (elseEntry != null) { if (elseEntry != null) {
if (missingCases.isEmpty() && subjectType != null && !subjectType.isFlexible()) { if (missingCases.isEmpty() && subjectType != null && !subjectType.isFlexible()) {
@@ -985,8 +979,7 @@ class ControlFlowInformationProvider private constructor(
if (sameErrorForAllCopies) { if (sameErrorForAllCopies) {
trace.report(diagnostic) trace.report(diagnostic)
} }
} } else {
else {
//only one reporting required //only one reporting required
if (!alreadyReported) { if (!alreadyReported) {
trace.report(diagnostic) trace.report(diagnostic)
@@ -1035,15 +1028,16 @@ class ControlFlowInformationProvider private constructor(
getParentOfType(element, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtClassInitializer::class.java) getParentOfType(element, KtDeclarationWithBody::class.java, KtClassOrObject::class.java, KtClassInitializer::class.java)
fun getDeclarationDescriptorIncludingConstructors(context: BindingContext, declaration: KtDeclaration?): DeclarationDescriptor? { fun getDeclarationDescriptorIncludingConstructors(context: BindingContext, declaration: KtDeclaration?): DeclarationDescriptor? {
val descriptor = context.get(DECLARATION_TO_DESCRIPTOR, val descriptor = context.get(
(declaration as? KtClassInitializer)?.containingDeclaration ?: declaration) DECLARATION_TO_DESCRIPTOR,
(declaration as? KtClassInitializer)?.containingDeclaration ?: declaration
)
return if (descriptor is ClassDescriptor && declaration is KtClassInitializer) { return if (descriptor is ClassDescriptor && declaration is KtClassInitializer) {
// For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer, // For a class primary constructor, we cannot directly get ConstructorDescriptor by KtClassInitializer,
// so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor // so we have to do additional conversion: KtClassInitializer -> KtClassOrObject -> ClassDescriptor -> ConstructorDescriptor
descriptor.unsubstitutedPrimaryConstructor descriptor.unsubstitutedPrimaryConstructor
?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor ?: (descriptor as? ClassDescriptorWithResolutionScopes)?.scopeForInitializerResolution?.ownerDescriptor
} } else {
else {
descriptor descriptor
} }
} }
@@ -1084,8 +1078,7 @@ class ControlFlowInformationProvider private constructor(
val resultingExpression = getResultingExpression(expression) val resultingExpression = getResultingExpression(expression)
if (resultingExpression is KtIfExpression || resultingExpression is KtWhenExpression) { if (resultingExpression is KtIfExpression || resultingExpression is KtWhenExpression) {
collectResultingExpressionsOfConditionalExpressionRec(resultingExpression, resultingExpressions) collectResultingExpressionsOfConditionalExpressionRec(resultingExpression, resultingExpressions)
} } else {
else {
resultingExpressions.add(resultingExpression) resultingExpressions.add(resultingExpression)
} }
} }
@@ -1106,8 +1099,7 @@ class ControlFlowInformationProvider private constructor(
private fun combineKinds(kind: TailRecursionKind, existingKind: TailRecursionKind?): TailRecursionKind { private fun combineKinds(kind: TailRecursionKind, existingKind: TailRecursionKind?): TailRecursionKind {
return if (existingKind == null || existingKind == kind) { return if (existingKind == null || existingKind == kind) {
kind kind
} } else {
else {
when { when {
check(kind, existingKind, IN_TRY, TAIL_CALL) -> IN_TRY check(kind, existingKind, IN_TRY, TAIL_CALL) -> IN_TRY
check(kind, existingKind, IN_TRY, NON_TAIL) -> IN_TRY check(kind, existingKind, IN_TRY, NON_TAIL) -> IN_TRY
@@ -88,8 +88,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
generateImplicitReturnValue(bodyExpression, subroutine) generateImplicitReturnValue(bodyExpression, subroutine)
} }
} }
} } else {
else {
cfpVisitor.generateInstructions(subroutine) cfpVisitor.generateInstructions(subroutine)
} }
return builder.exitSubroutine(subroutine, invocationKind) return builder.exitSubroutine(subroutine, invocationKind)
@@ -155,8 +154,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (subjectExpression != null) { if (subjectExpression != null) {
// todo: this can be replaced by equals() invocation (when corresponding resolved call is recorded) // todo: this can be replaced by equals() invocation (when corresponding resolved call is recorded)
createNonSyntheticValue(condition, MagicKind.EQUALS_IN_WHEN_CONDITION, subjectExpression, expression) createNonSyntheticValue(condition, MagicKind.EQUALS_IN_WHEN_CONDITION, subjectExpression, expression)
} } else {
else {
copyValue(expression, condition) copyValue(expression, condition)
} }
} }
@@ -276,8 +274,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val resolvedCall = expression.getResolvedCall(trace.bindingContext) val resolvedCall = expression.getResolvedCall(trace.bindingContext)
if (resolvedCall is VariableAsFunctionResolvedCall) { if (resolvedCall is VariableAsFunctionResolvedCall) {
generateCall(resolvedCall.variableCall) generateCall(resolvedCall.variableCall)
} } else {
else {
if (resolvedCall == null) { if (resolvedCall == null) {
val qualifier = trace.bindingContext[BindingContext.QUALIFIER, expression] val qualifier = trace.bindingContext[BindingContext.QUALIFIER, expression]
if (qualifier != null && generateQualifier(expression, qualifier)) return if (qualifier != null && generateQualifier(expression, qualifier)) return
@@ -305,11 +302,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val right = expression.right val right = expression.right
if (operationType === ANDAND || operationType === OROR) { if (operationType === ANDAND || operationType === OROR) {
generateBooleanOperation(expression) generateBooleanOperation(expression)
} } else if (operationType === EQ) {
else if (operationType === EQ) {
visitAssignment(left, getDeferredValue(right), expression) visitAssignment(left, getDeferredValue(right), expression)
} } else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
val resolvedCall = expression.getResolvedCall(trace.bindingContext) val resolvedCall = expression.getResolvedCall(trace.bindingContext)
if (resolvedCall != null) { if (resolvedCall != null) {
val rhsValue = generateCall(resolvedCall).outputValue val rhsValue = generateCall(resolvedCall).outputValue
@@ -321,12 +316,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
*/ */
visitAssignment(left, getValueAsFunction(rhsValue), expression) visitAssignment(left, getValueAsFunction(rhsValue), expression)
} }
} } else {
else {
generateBothArgumentsAndMark(expression) generateBothArgumentsAndMark(expression)
} }
} } else if (operationType === ELVIS) {
else if (operationType === ELVIS) {
generateInstructions(left) generateInstructions(left)
mark(expression) mark(expression)
val afterElvis = builder.createUnboundLabel("after elvis operator") val afterElvis = builder.createUnboundLabel("after elvis operator")
@@ -334,8 +327,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
generateInstructions(right) generateInstructions(right)
builder.bindLabel(afterElvis) builder.bindLabel(afterElvis)
mergeValues(listOf(left, right).filterNotNull(), expression) mergeValues(listOf(left, right).filterNotNull(), expression)
} } else {
else {
if (!generateCall(expression)) { if (!generateCall(expression)) {
generateBothArgumentsAndMark(expression) generateBothArgumentsAndMark(expression)
} }
@@ -351,8 +343,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
generateInstructions(left) generateInstructions(left)
if (operationType === ANDAND) { if (operationType === ANDAND) {
builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left)) builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left))
} } else {
else {
builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left)) builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left))
} }
generateInstructions(right) generateInstructions(right)
@@ -405,8 +396,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (accessTarget is AccessTarget.Call) { if (accessTarget is AccessTarget.Call) {
receiverValues = getReceiverValues(accessTarget.resolvedCall) receiverValues = getReceiverValues(accessTarget.resolvedCall)
} }
} } else if (left is KtProperty) {
else if (left is KtProperty) {
accessTarget = getDeclarationAccessTarget(left) accessTarget = getDeclarationAccessTarget(left)
} }
@@ -470,8 +460,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val parameterDescriptor = argumentMapping.valueParameter val parameterDescriptor = argumentMapping.valueParameter
if (valueArgument !== rhsArgument) { if (valueArgument !== rhsArgument) {
argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues) argumentValues = generateValueArgument(valueArgument, parameterDescriptor, argumentValues)
} } else {
else {
val rhsValue = rhsDeferredValue.invoke() val rhsValue = rhsDeferredValue.invoke()
if (rhsValue != null) { if (rhsValue != null) {
argumentValues = argumentValues.plus(rhsValue, parameterDescriptor) argumentValues = argumentValues.plus(rhsValue, parameterDescriptor)
@@ -525,8 +514,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val rhsValue: PseudoValue? = if (resolvedCall != null) { val rhsValue: PseudoValue? = if (resolvedCall != null) {
generateCall(resolvedCall).outputValue generateCall(resolvedCall).outputValue
} } else {
else {
generateInstructions(baseExpression) generateInstructions(baseExpression)
createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, baseExpression) createNonSyntheticValue(expression, MagicKind.UNRESOLVED_CALL, baseExpression)
} }
@@ -553,8 +541,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (thenBranch != null) { if (thenBranch != null) {
branches.add(thenBranch) branches.add(thenBranch)
generateInstructions(thenBranch) generateInstructions(thenBranch)
} } else {
else {
builder.loadUnit(expression) builder.loadUnit(expression)
} }
val resultLabel = builder.createUnboundLabel("'if' expression result") val resultLabel = builder.createUnboundLabel("'if' expression result")
@@ -564,8 +551,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (elseBranch != null) { if (elseBranch != null) {
branches.add(elseBranch) branches.add(elseBranch)
generateInstructions(elseBranch) generateInstructions(elseBranch)
} } else {
else {
builder.loadUnit(expression) builder.loadUnit(expression)
} }
builder.bindLabel(resultLabel) builder.bindLabel(resultLabel)
@@ -684,8 +670,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
builder.enterBlockScope(catchClause) builder.enterBlockScope(catchClause)
if (!isFirst) { if (!isFirst) {
builder.bindLabel(catchLabels.remove()) builder.bindLabel(catchLabels.remove())
} } else {
else {
isFirst = false isFirst = false
} }
val catchParameter = catchClause.catchParameter val catchParameter = catchClause.catchParameter
@@ -713,8 +698,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
mark(expression) mark(expression)
if (!CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace.bindingContext, true)) { if (!CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace.bindingContext, true)) {
builder.jumpOnFalse(loopInfo.exitPoint, expression, builder.getBoundValue(condition)) builder.jumpOnFalse(loopInfo.exitPoint, expression, builder.getBoundValue(condition))
} } else {
else {
assert(condition != null) { "Invalid while condition: " + expression.text } assert(condition != null) { "Invalid while condition: " + expression.text }
createSyntheticValue(condition!!, MagicKind.VALUE_CONSUMER, condition) createSyntheticValue(condition!!, MagicKind.VALUE_CONSUMER, condition)
} }
@@ -741,8 +725,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
builder.exitBlockScope(expression) builder.exitBlockScope(expression)
if (!CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace.bindingContext, true)) { if (!CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace.bindingContext, true)) {
builder.jumpOnTrue(loopInfo.entryPoint, expression, builder.getBoundValue(expression.condition)) builder.jumpOnTrue(loopInfo.entryPoint, expression, builder.getBoundValue(expression.condition))
} } else {
else {
assert(condition != null) { "Invalid do / while condition: " + expression.text } assert(condition != null) { "Invalid do / while condition: " + expression.text }
createSyntheticValue(condition!!, MagicKind.VALUE_CONSUMER, condition) createSyntheticValue(condition!!, MagicKind.VALUE_CONSUMER, condition)
builder.jump(loopInfo.entryPoint, expression) builder.jump(loopInfo.entryPoint, expression)
@@ -795,8 +778,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val destructuringDeclaration = loopParameter.destructuringDeclaration val destructuringDeclaration = loopParameter.destructuringDeclaration
if (destructuringDeclaration != null) { if (destructuringDeclaration != null) {
visitDestructuringDeclaration(destructuringDeclaration, false) visitDestructuringDeclaration(destructuringDeclaration, false)
} } else {
else {
builder.declareParameter(loopParameter) builder.declareParameter(loopParameter)
} }
} }
@@ -819,8 +801,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
for (entry in destructuringDeclaration.entries) { for (entry in destructuringDeclaration.entries) {
generateInitializer(entry, value) generateInitializer(entry, value)
} }
} } else {
else {
generateInitializer(loopParameter, value) generateInitializer(loopParameter, value)
} }
} }
@@ -857,8 +838,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val parentBody = parentLoop.body val parentBody = parentLoop.body
return if (parentBody != null && parentBody.textRange.contains(expression.textRange)) { return if (parentBody != null && parentBody.textRange.contains(expression.textRange)) {
parentLoop parentLoop
} } else {
else {
getNearestLoopExpression(parentLoop) getNearestLoopExpression(parentLoop)
} }
} }
@@ -871,20 +851,19 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel) val labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel)
loop = if (labeledElement is KtLoopExpression) { loop = if (labeledElement is KtLoopExpression) {
labeledElement labeledElement
} } else {
else {
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.text)) trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.text))
null null
} }
} } else {
else {
loop = getCorrespondingLoopWithoutLabel(expression) loop = getCorrespondingLoopWithoutLabel(expression)
if (loop == null) { if (loop == null) {
trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression)) trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression))
} } else {
else { val whenExpression = PsiTreeUtil.getParentOfType(
val whenExpression = PsiTreeUtil.getParentOfType(expression, KtWhenExpression::class.java, true, expression, KtWhenExpression::class.java, true,
KtLoopExpression::class.java) KtLoopExpression::class.java
)
if (whenExpression != null) { if (whenExpression != null) {
trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression)) trace.report(BREAK_OR_CONTINUE_IN_WHEN.on(expression))
} }
@@ -931,8 +910,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression)) trace.report(BREAK_OR_CONTINUE_JUMPS_ACROSS_FUNCTION_BOUNDARY.on(jumpExpression))
} }
false false
} } else {
else {
true true
} }
} }
@@ -953,12 +931,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (labeledElement != null) { if (labeledElement != null) {
assert(labeledElement is KtElement) assert(labeledElement is KtElement)
labeledElement as KtElement? labeledElement as KtElement?
} } else {
else {
null null
} }
} } else {
else {
builder.returnSubroutine builder.returnSubroutine
// TODO : a context check // TODO : a context check
} }
@@ -967,12 +943,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val returnValue = if (returnedExpression != null) builder.getBoundValue(returnedExpression) else null val returnValue = if (returnedExpression != null) builder.getBoundValue(returnedExpression) else null
if (returnValue == null) { if (returnValue == null) {
builder.returnNoValue(expression, subroutine) builder.returnNoValue(expression, subroutine)
} } else {
else {
builder.returnValue(expression, returnValue, subroutine) builder.returnValue(expression, returnValue, subroutine)
} }
} } else {
else {
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression) createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, returnedExpression)
} }
} }
@@ -1018,8 +992,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
} }
if (statements.isEmpty()) { if (statements.isEmpty()) {
builder.loadUnit(expression) builder.loadUnit(expression)
} } else {
else {
copyValue(statements.lastOrNull(), expression) copyValue(statements.lastOrNull(), expression)
} }
if (declareBlockScope) { if (declareBlockScope) {
@@ -1035,8 +1008,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
private fun visitFunction(function: KtFunction, invocationKind: InvocationKind? = null) { private fun visitFunction(function: KtFunction, invocationKind: InvocationKind? = null) {
if (invocationKind == null) { if (invocationKind == null) {
processLocalDeclaration(function) processLocalDeclaration(function)
} } else {
else {
visitInlinedFunction(function, invocationKind) visitInlinedFunction(function, invocationKind)
} }
@@ -1093,16 +1065,14 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (selectorExpression is KtCallExpression || selectorExpression is KtSimpleNameExpression) { if (selectorExpression is KtCallExpression || selectorExpression is KtSimpleNameExpression) {
if (!safe) { if (!safe) {
generateInstructions(selectorExpression) generateInstructions(selectorExpression)
} } else {
else {
val resultLabel = builder.createUnboundLabel("result of call") val resultLabel = builder.createUnboundLabel("result of call")
builder.jumpOnFalse(resultLabel, expression, null) builder.jumpOnFalse(resultLabel, expression, null)
generateInstructions(selectorExpression) generateInstructions(selectorExpression)
builder.bindLabel(resultLabel) builder.bindLabel(resultLabel)
} }
copyValue(selectorExpression, expression) copyValue(selectorExpression, expression)
} } else {
else {
generateInstructions(receiverExpression) generateInstructions(receiverExpression)
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression) createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, receiverExpression)
} }
@@ -1185,9 +1155,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
entry, entry,
resolvedCall, resolvedCall,
getReceiverValues(resolvedCall), getReceiverValues(resolvedCall),
emptyMap()).outputValue emptyMap()
} ).outputValue
else { } else {
initializer?.let { createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, it) } initializer?.let { createSyntheticValue(entry, MagicKind.UNRESOLVED_CALL, it) }
} }
@@ -1211,8 +1181,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (getBoundOrUnreachableValue(left) != null) { if (getBoundOrUnreachableValue(left) != null) {
createNonSyntheticValue(expression, MagicKind.CAST, left) createNonSyntheticValue(expression, MagicKind.CAST, left)
} }
} } else {
else {
visitKtElement(expression) visitKtElement(expression)
createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left) createNonSyntheticValue(expression, MagicKind.UNSUPPORTED_ELEMENT, left)
} }
@@ -1376,8 +1345,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val classDescriptor = trace[BindingContext.DECLARATION_TO_DESCRIPTOR, entryOrObject] val classDescriptor = trace[BindingContext.DECLARATION_TO_DESCRIPTOR, entryOrObject]
if (classDescriptor is ClassDescriptor) { if (classDescriptor is ClassDescriptor) {
builder.declareEntryOrObject(entryOrObject) builder.declareEntryOrObject(entryOrObject)
builder.write(entryOrObject, entryOrObject, createSyntheticValue(entryOrObject, MagicKind.FAKE_INITIALIZER), builder.write(
AccessTarget.Declaration(FakeCallableDescriptorForObject(classDescriptor)), emptyMap()) entryOrObject, entryOrObject, createSyntheticValue(entryOrObject, MagicKind.FAKE_INITIALIZER),
AccessTarget.Declaration(FakeCallableDescriptorForObject(classDescriptor)), emptyMap()
)
generateInstructions(entryOrObject) generateInstructions(entryOrObject)
} }
} }
@@ -1431,7 +1402,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
} }
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) { override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
val classOrObject = PsiTreeUtil.getParentOfType(constructor, KtClassOrObject::class.java) ?: error("Guaranteed by parsing contract") val classOrObject =
PsiTreeUtil.getParentOfType(constructor, KtClassOrObject::class.java) ?: error("Guaranteed by parsing contract")
processParameters(constructor.valueParameters) processParameters(constructor.valueParameters)
generateCallOrMarkUnresolved(constructor.getDelegationCall()) generateCallOrMarkUnresolved(constructor.getDelegationCall())
@@ -1493,8 +1465,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression) is DoubleColonLHS.Expression) { trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression) is DoubleColonLHS.Expression) {
generateInstructions(receiverExpression) generateInstructions(receiverExpression)
createNonSyntheticValue(expression, MagicKind.BOUND_CALLABLE_REFERENCE, receiverExpression) createNonSyntheticValue(expression, MagicKind.BOUND_CALLABLE_REFERENCE, receiverExpression)
} } else {
else {
createNonSyntheticValue(expression, MagicKind.UNBOUND_CALLABLE_REFERENCE) createNonSyntheticValue(expression, MagicKind.UNBOUND_CALLABLE_REFERENCE)
} }
} }
@@ -1541,8 +1512,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
val argumentExpression = argument.getArgumentExpression() val argumentExpression = argument.getArgumentExpression()
if (argumentMapping is ArgumentMatch) { if (argumentMapping is ArgumentMatch) {
parameterValues = generateValueArgument(argument, argumentMapping.valueParameter, parameterValues) parameterValues = generateValueArgument(argument, argumentMapping.valueParameter, parameterValues)
} } else if (argumentExpression != null) {
else if (argumentExpression != null) {
generateInstructions(argumentExpression) generateInstructions(argumentExpression)
createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression) createSyntheticValue(argumentExpression, MagicKind.VALUE_CONSUMER, argumentExpression)
} }
@@ -1551,7 +1521,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
if (resolvedCall.resultingDescriptor is VariableDescriptor) { if (resolvedCall.resultingDescriptor is VariableDescriptor) {
// If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated. // If a callee of the call is just a variable (without 'invoke'), 'read variable' is generated.
// todo : process arguments for such a case (KT-5387) // todo : process arguments for such a case (KT-5387)
val callExpression = callElement as? KtExpression ?: error("Variable-based call without callee expression: " + callElement.text) val callExpression =
callElement as? KtExpression ?: error("Variable-based call without callee expression: " + callElement.text)
assert(parameterValues.isEmpty()) { "Variable-based call with non-empty argument list: " + callElement.text } assert(parameterValues.isEmpty()) { "Variable-based call with non-empty argument list: " + callElement.text }
return builder.readVariable(callExpression, resolvedCall, receivers) return builder.readVariable(callExpression, resolvedCall, receivers)
} }
@@ -69,7 +69,8 @@ fun <I : ControlFlowInfo<*, *>> Pseudocode.collectData(
do { do {
collectDataFromSubgraph( collectDataFromSubgraph(
traversalOrder, edgesMap, traversalOrder, edgesMap,
mergeEdges, updateEdge, Collections.emptyList<Instruction>(), changed, false) mergeEdges, updateEdge, Collections.emptyList<Instruction>(), changed, false
)
} while (changed.any { it.value }) } while (changed.any { it.value })
return edgesMap return edgesMap
@@ -92,7 +93,8 @@ private fun <I : ControlFlowInfo<*, *>> Pseudocode.collectDataFromSubgraph(
if (!isLocal && isStart) if (!isLocal && isStart)
continue continue
val previousInstructions = getPreviousIncludingSubGraphInstructions(instruction, traversalOrder, startInstruction, previousSubGraphInstructions) val previousInstructions =
getPreviousIncludingSubGraphInstructions(instruction, traversalOrder, startInstruction, previousSubGraphInstructions)
if (instruction is LocalFunctionDeclarationInstruction) { if (instruction is LocalFunctionDeclarationInstruction) {
val subroutinePseudocode = instruction.body val subroutinePseudocode = instruction.body
@@ -125,8 +127,11 @@ private fun <I : ControlFlowInfo<*, *>> Pseudocode.collectDataFromSubgraph(
for (previousInstruction in previousInstructions) { for (previousInstruction in previousInstructions) {
val previousData = edgesMap[previousInstruction] val previousData = edgesMap[previousInstruction]
if (previousData != null) { if (previousData != null) {
incomingEdgesData.add(updateEdge( incomingEdgesData.add(
previousInstruction, instruction, previousData.outgoing)) updateEdge(
previousInstruction, instruction, previousData.outgoing
)
)
} }
} }
val mergedData = mergeEdges(instruction, incomingEdgesData) val mergedData = mergeEdges(instruction, incomingEdgesData)
@@ -159,8 +164,7 @@ private fun <I : ControlFlowInfo<*, *>> updateEdgeDataForInstruction(
if (previousValue != newValue && newValue != null) { if (previousValue != newValue && newValue != null) {
changed[instruction] = true changed[instruction] = true
edgesMap.put(instruction, newValue) edgesMap.put(instruction, newValue)
} } else {
else {
changed[instruction] = false changed[instruction] = false
} }
} }
@@ -189,7 +193,8 @@ fun traverseFollowingInstructions(
if (!visited.add(instruction)) continue if (!visited.add(instruction)) continue
when (handler?.let { it(instruction) } ?: TraverseInstructionResult.CONTINUE) { when (handler?.let { it(instruction) } ?: TraverseInstructionResult.CONTINUE) {
TraverseInstructionResult.CONTINUE -> instruction.getNextInstructions(order).forEach { stack.push(it) } TraverseInstructionResult.CONTINUE -> instruction.getNextInstructions(order).forEach { stack.push(it) }
TraverseInstructionResult.SKIP -> {} TraverseInstructionResult.SKIP -> {
}
TraverseInstructionResult.HALT -> return false TraverseInstructionResult.HALT -> return false
} }
} }
@@ -109,7 +109,12 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
override val reversedInstructions: List<Instruction> override val reversedInstructions: List<Instruction>
get() { get() {
val traversedInstructions = linkedSetOf<Instruction>() val traversedInstructions = linkedSetOf<Instruction>()
traverseFollowingInstructions(if (this.isInlined) instructions.last() else sinkInstruction, traversedInstructions, BACKWARD, null) traverseFollowingInstructions(
if (this.isInlined) instructions.last() else sinkInstruction,
traversedInstructions,
BACKWARD,
null
)
if (traversedInstructions.size < instructions.size) { if (traversedInstructions.size < instructions.size) {
val simplyReversedInstructions = instructions.reversed() val simplyReversedInstructions = instructions.reversed()
for (instruction in simplyReversedInstructions) { for (instruction in simplyReversedInstructions) {
@@ -266,8 +271,7 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
if (instruction.onTrue) { if (instruction.onTrue) {
instruction.nextOnFalse = nextInstruction instruction.nextOnFalse = nextInstruction
instruction.nextOnTrue = jumpTarget instruction.nextOnTrue = jumpTarget
} } else {
else {
instruction.nextOnFalse = jumpTarget instruction.nextOnFalse = jumpTarget
instruction.nextOnTrue = nextInstruction instruction.nextOnTrue = nextInstruction
} }
@@ -286,7 +290,8 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
body.parent = this@PseudocodeImpl body.parent = this@PseudocodeImpl
body.postProcess() body.postProcess()
// Don't add edge to next instruction if flow can't reach exit of inlined declaration // Don't add edge to next instruction if flow can't reach exit of inlined declaration
instruction.next = if (body.instructions.contains(body.exitInstruction)) getNextPosition(currentPosition) else sinkInstruction instruction.next =
if (body.instructions.contains(body.exitInstruction)) getNextPosition(currentPosition) else sinkInstruction
} }
override fun visitSubroutineExit(instruction: SubroutineExitInstruction) { override fun visitSubroutineExit(instruction: SubroutineExitInstruction) {
@@ -305,7 +310,8 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
private fun collectReachableInstructions() { private fun collectReachableInstructions() {
val reachableFromThisPseudocode = hashSetOf<Instruction>() val reachableFromThisPseudocode = hashSetOf<Instruction>()
traverseFollowingInstructions(enterInstruction, reachableFromThisPseudocode, FORWARD traverseFollowingInstructions(
enterInstruction, reachableFromThisPseudocode, FORWARD
) { instruction -> ) { instruction ->
if (instruction is MagicInstruction && instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) { if (instruction is MagicInstruction && instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) {
return@traverseFollowingInstructions TraverseInstructionResult.SKIP return@traverseFollowingInstructions TraverseInstructionResult.SKIP
@@ -363,7 +369,8 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
private fun repeatInternal( private fun repeatInternal(
originalPseudocode: PseudocodeImpl, originalPseudocode: PseudocodeImpl,
startLabel: Label?, finishLabel: Label?, startLabel: Label?, finishLabel: Label?,
labelCountArg: Int): Int { labelCountArg: Int
): Int {
var labelCount = labelCountArg var labelCount = labelCountArg
val startIndex = startLabel?.targetInstructionIndex ?: 0 val startIndex = startLabel?.targetInstructionIndex ?: 0
val finishIndex = finishLabel?.targetInstructionIndex ?: originalPseudocode.mutableInstructionList.size val finishIndex = finishLabel?.targetInstructionIndex ?: originalPseudocode.mutableInstructionList.size
@@ -401,9 +408,11 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
} }
} }
if (finishIndex < originalPseudocode.mutableInstructionList.size) { if (finishIndex < originalPseudocode.mutableInstructionList.size) {
repeatLabelsBindingForInstruction(originalPseudocode.mutableInstructionList[finishIndex], repeatLabelsBindingForInstruction(
originalPseudocode.mutableInstructionList[finishIndex],
originalToCopy, originalToCopy,
originalLabelsForInstruction) originalLabelsForInstruction
)
} }
return labelCount return labelCount
} }
@@ -411,7 +420,8 @@ class PseudocodeImpl(override val correspondingElement: KtElement, override val
private fun repeatLabelsBindingForInstruction( private fun repeatLabelsBindingForInstruction(
originalInstruction: Instruction, originalInstruction: Instruction,
originalToCopy: Map<Label, PseudocodeLabel>, originalToCopy: Map<Label, PseudocodeLabel>,
originalLabelsForInstruction: Multimap<Instruction, Label>) { originalLabelsForInstruction: Multimap<Instruction, Label>
) {
for (originalLabel in originalLabelsForInstruction.get(originalInstruction)) { for (originalLabel in originalLabelsForInstruction.get(originalInstruction)) {
bindLabel(originalToCopy[originalLabel]!!) bindLabel(originalToCopy[originalLabel]!!)
} }
@@ -36,11 +36,15 @@ class PseudocodeLabel internal constructor(
val index = targetInstructionIndex val index = targetInstructionIndex
when { when {
index < 0 -> index < 0 ->
error("resolveToInstruction: unbound label $name " + error(
"in subroutine ${correspondingElement.text} with instructions $instructionList") "resolveToInstruction: unbound label $name " +
"in subroutine ${correspondingElement.text} with instructions $instructionList"
)
index >= instructionList.size -> index >= instructionList.size ->
error("resolveToInstruction: incorrect index $index for label $name " + error(
"in subroutine ${correspondingElement.text} with instructions $instructionList") "resolveToInstruction: incorrect index $index for label $name " +
"in subroutine ${correspondingElement.text} with instructions $instructionList"
)
else -> else ->
return instructionList[index] return instructionList[index]
} }
@@ -32,11 +32,13 @@ sealed class AccessTarget {
override fun hashCode() = descriptor.hashCode() override fun hashCode() = descriptor.hashCode()
} }
class Call(val resolvedCall: ResolvedCall<*>) : AccessTarget() { class Call(val resolvedCall: ResolvedCall<*>) : AccessTarget() {
override fun equals(other: Any?) = other is Call && resolvedCall == other.resolvedCall override fun equals(other: Any?) = other is Call && resolvedCall == other.resolvedCall
override fun hashCode() = resolvedCall.hashCode() override fun hashCode() = resolvedCall.hashCode()
} }
object BlackBox : AccessTarget() object BlackBox : AccessTarget()
} }
@@ -30,7 +30,8 @@ class ConditionalJumpInstruction(
val onTrue: Boolean, val onTrue: Boolean,
blockScope: BlockScope, blockScope: BlockScope,
targetLabel: Label, targetLabel: Label,
private val conditionValue: PseudoValue?) : AbstractJumpInstruction(element, targetLabel, blockScope) { private val conditionValue: PseudoValue?
) : AbstractJumpInstruction(element, targetLabel, blockScope) {
private var _nextOnTrue: Instruction? = null private var _nextOnTrue: Instruction? = null
private var _nextOnFalse: Instruction? = null private var _nextOnFalse: Instruction? = null
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithRe
class SubroutineSinkInstruction( class SubroutineSinkInstruction(
val subroutine: KtElement, val subroutine: KtElement,
blockScope: BlockScope, blockScope: BlockScope,
private val debugLabel: String) : InstructionImpl(blockScope) { private val debugLabel: String
) : InstructionImpl(blockScope) {
override val nextInstructions: Collection<Instruction> override val nextInstructions: Collection<Instruction>
get() = Collections.emptyList() get() = Collections.emptyList()
@@ -71,7 +71,9 @@ class ContractDeserializerImpl(private val configuration: DeserializationConfigu
return when (type!!) { return when (type!!) {
ProtoBuf.Effect.EffectType.RETURNS_CONSTANT -> { ProtoBuf.Effect.EffectType.RETURNS_CONSTANT -> {
val argument = proto.effectConstructorArgumentList.getOrNull(0) val argument = proto.effectConstructorArgumentList.getOrNull(0)
val returnValue = if (argument == null) ConstantReference.WILDCARD else deserializeExpression(argument) as? ConstantReference ?: return null val returnValue =
if (argument == null) ConstantReference.WILDCARD else deserializeExpression(argument) as? ConstantReference
?: return null
ReturnsEffectDeclaration(returnValue) ReturnsEffectDeclaration(returnValue)
} }
@@ -65,8 +65,10 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)) return ConditionalDataFlowInfo.EMPTY if (!languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)) return ConditionalDataFlowInfo.EMPTY
if (leftExpression == null || rightExpression == null) return ConditionalDataFlowInfo.EMPTY if (leftExpression == null || rightExpression == null) return ConditionalDataFlowInfo.EMPTY
val leftComputation = getNonTrivialComputation(leftExpression, bindingTrace, moduleDescriptor) ?: return ConditionalDataFlowInfo.EMPTY val leftComputation =
val rightComputation = getNonTrivialComputation(rightExpression, bindingTrace, moduleDescriptor) ?: return ConditionalDataFlowInfo.EMPTY getNonTrivialComputation(leftExpression, bindingTrace, moduleDescriptor) ?: return ConditionalDataFlowInfo.EMPTY
val rightComputation =
getNonTrivialComputation(rightExpression, bindingTrace, moduleDescriptor) ?: return ConditionalDataFlowInfo.EMPTY
val effects = EqualsFunctor(false).invokeWithArguments(leftComputation, rightComputation) val effects = EqualsFunctor(false).invokeWithArguments(leftComputation, rightComputation)
@@ -66,9 +66,18 @@ class EffectsExtractingVisitor(
val descriptor = resolvedCall.resultingDescriptor val descriptor = resolvedCall.resultingDescriptor
return when { return when {
descriptor.isEqualsDescriptor() -> CallComputation(DefaultBuiltIns.Instance.booleanType, EqualsFunctor(false).invokeWithArguments(arguments)) descriptor.isEqualsDescriptor() -> CallComputation(
descriptor is ValueDescriptor -> ESDataFlowValue(descriptor, (element as KtExpression).createDataFlowValue() ?: return UNKNOWN_COMPUTATION) DefaultBuiltIns.Instance.booleanType,
descriptor is FunctionDescriptor -> CallComputation(descriptor.returnType, descriptor.getFunctor()?.invokeWithArguments(arguments) ?: emptyList()) EqualsFunctor(false).invokeWithArguments(arguments)
)
descriptor is ValueDescriptor -> ESDataFlowValue(
descriptor,
(element as KtExpression).createDataFlowValue() ?: return UNKNOWN_COMPUTATION
)
descriptor is FunctionDescriptor -> CallComputation(
descriptor.returnType,
descriptor.getFunctor()?.invokeWithArguments(arguments) ?: emptyList()
)
else -> UNKNOWN_COMPUTATION else -> UNKNOWN_COMPUTATION
} }
} }
@@ -85,8 +94,8 @@ class EffectsExtractingVisitor(
val type: KotlinType = bindingContext.getType(expression) ?: return UNKNOWN_COMPUTATION val type: KotlinType = bindingContext.getType(expression) ?: return UNKNOWN_COMPUTATION
val compileTimeConstant: CompileTimeConstant<*> val compileTimeConstant: CompileTimeConstant<*> =
= bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression) ?: return UNKNOWN_COMPUTATION bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression) ?: return UNKNOWN_COMPUTATION
val value: Any? = compileTimeConstant.getValue(type) val value: Any? = compileTimeConstant.getValue(type)
return when (value) { return when (value) {
@@ -99,7 +108,10 @@ class EffectsExtractingVisitor(
override fun visitIsExpression(expression: KtIsExpression, data: Unit): Computation { override fun visitIsExpression(expression: KtIsExpression, data: Unit): Computation {
val rightType: KotlinType = trace[BindingContext.TYPE, expression.typeReference] ?: return UNKNOWN_COMPUTATION val rightType: KotlinType = trace[BindingContext.TYPE, expression.typeReference] ?: return UNKNOWN_COMPUTATION
val arg = extractOrGetCached(expression.leftHandSide) val arg = extractOrGetCached(expression.leftHandSide)
return CallComputation(DefaultBuiltIns.Instance.booleanType, IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg))) return CallComputation(
DefaultBuiltIns.Instance.booleanType,
IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg))
)
} }
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): Computation { override fun visitBinaryExpression(expression: KtBinaryExpression, data: Unit): Computation {
@@ -32,8 +32,7 @@ internal class PsiConstantParser(val trace: BindingTrace) : KtVisitor<ConstantRe
override fun visitConstantExpression(expression: KtConstantExpression, data: Unit?): ConstantReference? { override fun visitConstantExpression(expression: KtConstantExpression, data: Unit?): ConstantReference? {
val type: KotlinType = trace.getType(expression) ?: return null val type: KotlinType = trace.getType(expression) ?: return null
val compileTimeConstant: CompileTimeConstant<*> val compileTimeConstant: CompileTimeConstant<*> = trace.get(BindingContext.COMPILE_TIME_VALUE, expression) ?: return null
= trace.get(BindingContext.COMPILE_TIME_VALUE, expression) ?: return null
val value: Any? = compileTimeConstant.getValue(type) val value: Any? = compileTimeConstant.getValue(type)
return when (value) { return when (value) {
@@ -89,12 +89,22 @@ internal class PsiContractParserDispatcher(val trace: BindingTrace, val contract
if (expression == null) return null if (expression == null) return null
val descriptor = expression.getResolvedCall(trace.bindingContext)?.resultingDescriptor ?: return null val descriptor = expression.getResolvedCall(trace.bindingContext)?.resultingDescriptor ?: return null
if (descriptor !is ParameterDescriptor) { if (descriptor !is ParameterDescriptor) {
trace.report(Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(expression, "only references to parameters are allowed in contract description")) trace.report(
Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(
expression,
"only references to parameters are allowed in contract description"
)
)
return null return null
} }
if (descriptor is ReceiverParameterDescriptor && descriptor.type.constructor.declarationDescriptor?.isFromContractDsl() == true) { if (descriptor is ReceiverParameterDescriptor && descriptor.type.constructor.declarationDescriptor?.isFromContractDsl() == true) {
trace.report(Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(expression, "only references to parameters are allowed. Did you miss label on <this>?")) trace.report(
Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(
expression,
"only references to parameters are allowed. Did you miss label on <this>?"
)
)
} }
return if (KotlinBuiltIns.isBoolean(descriptor.type)) return if (KotlinBuiltIns.isBoolean(descriptor.type))
@@ -39,13 +39,18 @@ internal class PsiReturnsEffectParser(
if (!descriptor.isReturnsEffectDescriptor()) return null if (!descriptor.isReturnsEffectDescriptor()) return null
val argumentExpression = resolvedCall.firstArgumentAsExpressionOrNull() val argumentExpression = resolvedCall.firstArgumentAsExpressionOrNull()
val constantValue = if (argumentExpression == null) val constantValue = if (argumentExpression == null) {
ConstantReference.WILDCARD ConstantReference.WILDCARD
else { } else {
// Note that we distinguish absence of an argument and unparsed argument // Note that we distinguish absence of an argument and unparsed argument
val constant = contractParserDispatcher.parseConstant(argumentExpression) val constant = contractParserDispatcher.parseConstant(argumentExpression)
if (constant == null) { if (constant == null) {
trace.report(Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(argumentExpression, "only true/false/null constants in Returns-effect are currently supported")) trace.report(
Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(
argumentExpression,
"only true/false/null constants in Returns-effect are currently supported"
)
)
return null return null
} }
constant constant
@@ -47,7 +47,8 @@ class AnnotationSplitter(
companion object { companion object {
private val TARGET_PRIORITIES = setOf(CONSTRUCTOR_PARAMETER, PROPERTY, FIELD) private val TARGET_PRIORITIES = setOf(CONSTRUCTOR_PARAMETER, PROPERTY, FIELD)
@JvmStatic fun create( @JvmStatic
fun create(
storageManager: StorageManager, storageManager: StorageManager,
annotations: Annotations, annotations: Annotations,
targets: Set<AnnotationUseSiteTarget> targets: Set<AnnotationUseSiteTarget>
@@ -55,7 +56,8 @@ class AnnotationSplitter(
return AnnotationSplitter(storageManager, annotations, { targets }) return AnnotationSplitter(storageManager, annotations, { targets })
} }
@JvmStatic fun getTargetSet(parameter: Boolean, context: BindingContext, wrapper: PropertyWrapper): Set<AnnotationUseSiteTarget> { @JvmStatic
fun getTargetSet(parameter: Boolean, context: BindingContext, wrapper: PropertyWrapper): Set<AnnotationUseSiteTarget> {
val descriptor = wrapper.descriptor val descriptor = wrapper.descriptor
assert(descriptor != null) assert(descriptor != null)
val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false val hasBackingField = context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false
@@ -63,7 +65,8 @@ class AnnotationSplitter(
return getTargetSet(parameter, descriptor!!.isVar, hasBackingField, hasDelegate) return getTargetSet(parameter, descriptor!!.isVar, hasBackingField, hasDelegate)
} }
@JvmStatic fun getTargetSet( @JvmStatic
fun getTargetSet(
parameter: Boolean, isVar: Boolean, hasBackingField: Boolean, hasDelegate: Boolean parameter: Boolean, isVar: Boolean, hasBackingField: Boolean, hasDelegate: Boolean
): Set<AnnotationUseSiteTarget> = hashSetOf(PROPERTY, PROPERTY_GETTER).apply { ): Set<AnnotationUseSiteTarget> = hashSetOf(PROPERTY, PROPERTY_GETTER).apply {
if (parameter) add(CONSTRUCTOR_PARAMETER) if (parameter) add(CONSTRUCTOR_PARAMETER)
@@ -46,8 +46,10 @@ sealed class LocalVariableAccessorDescriptor(
} }
private fun createValueParameter(name: Name, type: KotlinType): ValueParameterDescriptorImpl { private fun createValueParameter(name: Name, type: KotlinType): ValueParameterDescriptorImpl {
return ValueParameterDescriptorImpl(this, null, 0, Annotations.EMPTY, name, type, return ValueParameterDescriptorImpl(
false, false, false, null, SourceElement.NO_SOURCE) this, null, 0, Annotations.EMPTY, name, type,
false, false, false, null, SourceElement.NO_SOURCE
)
} }
} }
@@ -28,12 +28,16 @@ class SyntheticFieldDescriptor private constructor(
val propertyDescriptor: PropertyDescriptor, val propertyDescriptor: PropertyDescriptor,
accessorDescriptor: PropertyAccessorDescriptor, accessorDescriptor: PropertyAccessorDescriptor,
property: KtProperty property: KtProperty
): LocalVariableDescriptor(accessorDescriptor, Annotations.EMPTY, SyntheticFieldDescriptor.NAME, ) : LocalVariableDescriptor(
accessorDescriptor, Annotations.EMPTY, SyntheticFieldDescriptor.NAME,
propertyDescriptor.type, propertyDescriptor.isVar, false, false, propertyDescriptor.type, propertyDescriptor.isVar, false, false,
property.toSourceElement()) { property.toSourceElement()
) {
constructor(accessorDescriptor: PropertyAccessorDescriptor, constructor(
property: KtProperty): this(accessorDescriptor.correspondingProperty, accessorDescriptor, property) accessorDescriptor: PropertyAccessorDescriptor,
property: KtProperty
) : this(accessorDescriptor.correspondingProperty, accessorDescriptor, property)
override fun getDispatchReceiverParameter() = null override fun getDispatchReceiverParameter() = null
@@ -53,18 +53,15 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
val callPosition = this.callPosition val callPosition = this.callPosition
val (resolvedCall, correspondingNotApproximatedTypeByDescriptor: (CallableDescriptor) -> KotlinType?) = when (callPosition) { val (resolvedCall, correspondingNotApproximatedTypeByDescriptor: (CallableDescriptor) -> KotlinType?) = when (callPosition) {
is CallPosition.ValueArgumentPosition -> Pair( is CallPosition.ValueArgumentPosition -> Pair(
callPosition.resolvedCall, { callPosition.resolvedCall, { f: CallableDescriptor ->
f: CallableDescriptor ->
getEffectiveExpectedType(f.valueParameters[callPosition.valueParameter.index], callPosition.valueArgument, this) getEffectiveExpectedType(f.valueParameters[callPosition.valueParameter.index], callPosition.valueArgument, this)
}) })
is CallPosition.ExtensionReceiverPosition -> Pair( is CallPosition.ExtensionReceiverPosition -> Pair(
callPosition.resolvedCall, { callPosition.resolvedCall, { f: CallableDescriptor ->
f: CallableDescriptor ->
f.extensionReceiverParameter?.type f.extensionReceiverParameter?.type
}) })
is CallPosition.PropertyAssignment -> Pair( is CallPosition.PropertyAssignment -> Pair(
callPosition.leftPart.getResolvedCall(trace.bindingContext) ?: return false, { callPosition.leftPart.getResolvedCall(trace.bindingContext) ?: return false, { f: CallableDescriptor ->
f: CallableDescriptor ->
(f as? PropertyDescriptor)?.setter?.valueParameters?.get(0)?.type (f as? PropertyDescriptor)?.setter?.valueParameters?.get(0)?.type
}) })
is CallPosition.Unknown -> return false is CallPosition.Unknown -> return false
@@ -87,8 +84,7 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
if (expectedType.isNothing()) { if (expectedType.isNothing()) {
if (callPosition is CallPosition.PropertyAssignment) { if (callPosition is CallPosition.PropertyAssignment) {
trace.report(Errors.SETTER_PROJECTED_OUT.on(callPosition.leftPart ?: return false, resolvedCall.resultingDescriptor)) trace.report(Errors.SETTER_PROJECTED_OUT.on(callPosition.leftPart ?: return false, resolvedCall.resultingDescriptor))
} } else {
else {
val call = resolvedCall.call val call = resolvedCall.call
val reportOn = val reportOn =
if (resolvedCall is VariableAsFunctionResolvedCall) if (resolvedCall is VariableAsFunctionResolvedCall)
@@ -98,14 +94,16 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
trace.reportDiagnosticOnce(Errors.MEMBER_PROJECTED_OUT.on(reportOn ?: call.callElement, callableDescriptor, receiverType)) trace.reportDiagnosticOnce(Errors.MEMBER_PROJECTED_OUT.on(reportOn ?: call.callElement, callableDescriptor, receiverType))
} }
} } else {
else {
// expressionType can be null when reporting CONSTANT_EXPECTED_TYPE_MISMATCH (see addAll.kt test) // expressionType can be null when reporting CONSTANT_EXPECTED_TYPE_MISMATCH (see addAll.kt test)
expressionType ?: return false expressionType ?: return false
trace.report( trace.report(
Errors.TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS.on( Errors.TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS.on(
expression, TypeMismatchDueToTypeProjectionsData( expression, TypeMismatchDueToTypeProjectionsData(
expectedType, expressionType, receiverType, callableDescriptor))) expectedType, expressionType, receiverType, callableDescriptor
)
)
)
} }
@@ -149,13 +147,18 @@ inline fun reportOnDeclaration(trace: BindingTrace, descriptor: DeclarationDescr
trace.report(what(psiElement)) trace.report(what(psiElement))
} }
} }
inline fun reportOnDeclarationOrFail(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (PsiElement) -> Diagnostic) { inline fun reportOnDeclarationOrFail(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (PsiElement) -> Diagnostic) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement -> DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement ->
trace.report(what(psiElement)) trace.report(what(psiElement))
} ?: throw AssertionError("No declaration for $descriptor") } ?: throw AssertionError("No declaration for $descriptor")
} }
inline fun <reified T : KtDeclaration> reportOnDeclarationAs(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (T) -> Diagnostic) { inline fun <reified T : KtDeclaration> reportOnDeclarationAs(
trace: BindingTrace,
descriptor: DeclarationDescriptor,
what: (T) -> Diagnostic
) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement -> DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement ->
(psiElement as? T)?.let { (psiElement as? T)?.let {
trace.report(what(it)) trace.report(what(it))
@@ -58,8 +58,7 @@ class LanguageFeatureMessageRenderer @JvmOverloads constructor(
if (hintUrl != null) { if (hintUrl != null) {
if (useHtml) { if (useHtml) {
sb.append(" (").append("see more <a href=\"").append(hintUrl).append("\">here</a>)") sb.append(" (").append("see more <a href=\"").append(hintUrl).append("\">here</a>)")
} } else {
else {
sb.append(" (see: ").append(hintUrl).append(")") sb.append(" (see: ").append(hintUrl).append(")")
} }
} }
@@ -30,6 +30,7 @@ interface PreprocessedVirtualFileFactoryExtension {
"org.jetbrains.kotlin.preprocessedVirtualFileFactoryExtension", "org.jetbrains.kotlin.preprocessedVirtualFileFactoryExtension",
PreprocessedVirtualFileFactoryExtension::class.java PreprocessedVirtualFileFactoryExtension::class.java
) )
fun isPassThrough(): Boolean fun isPassThrough(): Boolean
fun createPreprocessedFile(file: VirtualFile?): VirtualFile? fun createPreprocessedFile(file: VirtualFile?): VirtualFile?
@@ -45,6 +46,7 @@ class PreprocessedFileCreator(val project: Project) {
fun create(file: VirtualFile): VirtualFile = validExts.firstNotNullResult { it.createPreprocessedFile(file) } ?: file fun create(file: VirtualFile): VirtualFile = validExts.firstNotNullResult { it.createPreprocessedFile(file) } ?: file
// unused now, but could be used in the IDE at some point // unused now, but could be used in the IDE at some point
fun createLight(file: LightVirtualFile): LightVirtualFile = validExts.firstNotNullResult { it.createPreprocessedLightFile(file) } ?: file fun createLight(file: LightVirtualFile): LightVirtualFile =
validExts.firstNotNullResult { it.createPreprocessedLightFile(file) } ?: file
} }
@@ -41,8 +41,7 @@ enum class KDocKnownTag private constructor(val isReferenceRequired: Boolean, va
} }
try { try {
return valueOf(tagName.toString().toUpperCase()) return valueOf(tagName.toString().toUpperCase())
} } catch (ignored: IllegalArgumentException) {
catch (ignored: IllegalArgumentException) {
} }
return null return null
@@ -292,9 +292,11 @@ private object DebugTextBuildingVisitor : KtVisitor<String, Unit>() {
private fun StringBuilder.appendInn(target: Any?, prefix: String = "", suffix: String = "") { private fun StringBuilder.appendInn(target: Any?, prefix: String = "", suffix: String = "") {
if (target == null) return if (target == null) return
append(prefix) append(prefix)
append(when (target) { append(
when (target) {
is KtElement -> target.getDebugText() is KtElement -> target.getDebugText()
else -> target.toString() else -> target.toString()
}) }
)
append(suffix) append(suffix)
} }
@@ -29,23 +29,26 @@ object EditCommaSeparatedListHelper {
} }
@JvmOverloads @JvmOverloads
fun <TItem: KtElement> addItemAfter(list: KtElement, allItems: List<TItem>, item: TItem, anchor: TItem?, prefix: KtToken = KtTokens.LPAR): TItem { fun <TItem : KtElement> addItemAfter(
list: KtElement,
allItems: List<TItem>,
item: TItem,
anchor: TItem?,
prefix: KtToken = KtTokens.LPAR
): TItem {
assert(anchor == null || anchor.parent == list) assert(anchor == null || anchor.parent == list)
if (allItems.isEmpty()) { if (allItems.isEmpty()) {
return if (list.firstChild?.node?.elementType == prefix) { return if (list.firstChild?.node?.elementType == prefix) {
list.addAfter(item, list.firstChild) as TItem list.addAfter(item, list.firstChild) as TItem
} } else {
else {
list.add(item) as TItem list.add(item) as TItem
} }
} } else {
else {
var comma = KtPsiFactory(list).createComma() var comma = KtPsiFactory(list).createComma()
return if (anchor != null) { return if (anchor != null) {
comma = list.addAfter(comma, anchor) comma = list.addAfter(comma, anchor)
list.addAfter(item, comma) as TItem list.addAfter(item, comma) as TItem
} } else {
else {
comma = list.addBefore(comma, allItems.first()) comma = list.addBefore(comma, allItems.first())
list.addBefore(item, comma) as TItem list.addBefore(item, comma) as TItem
} }
@@ -53,19 +56,23 @@ object EditCommaSeparatedListHelper {
} }
@JvmOverloads @JvmOverloads
fun <TItem: KtElement> addItemBefore(list: KtElement, allItems: List<TItem>, item: TItem, anchor: TItem?, prefix: KtToken = KtTokens.LPAR): TItem { fun <TItem : KtElement> addItemBefore(
list: KtElement,
allItems: List<TItem>,
item: TItem,
anchor: TItem?,
prefix: KtToken = KtTokens.LPAR
): TItem {
val anchorAfter: TItem? val anchorAfter: TItem?
anchorAfter = if (allItems.isEmpty()) { anchorAfter = if (allItems.isEmpty()) {
assert(anchor == null) assert(anchor == null)
null null
} } else {
else {
if (anchor != null) { if (anchor != null) {
val index = allItems.indexOf(anchor) val index = allItems.indexOf(anchor)
assert(index >= 0) assert(index >= 0)
if (index > 0) allItems[index - 1] else null if (index > 0) allItems[index - 1] else null
} } else {
else {
allItems[allItems.size - 1] allItems[allItems.size - 1]
} }
} }
@@ -30,7 +30,8 @@ import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
abstract class KtClassOrObject : abstract class KtClassOrObject :
KtTypeParameterListOwnerStub<KotlinClassOrObjectStub<out KtClassOrObject>>, KtDeclarationContainer, KtNamedDeclaration, KtPureClassOrObject { KtTypeParameterListOwnerStub<KotlinClassOrObjectStub<out KtClassOrObject>>, KtDeclarationContainer, KtNamedDeclaration,
KtPureClassOrObject {
constructor(node: ASTNode) : super(node) constructor(node: ASTNode) : super(node)
constructor(stub: KotlinClassOrObjectStub<out KtClassOrObject>, nodeType: IStubElementType<*, *>) : super(stub, nodeType) constructor(stub: KotlinClassOrObjectStub<out KtClassOrObject>, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
@@ -59,8 +60,7 @@ abstract class KtClassOrObject :
if (specifierList.entries.size > 1) { if (specifierList.entries.size > 1) {
EditCommaSeparatedListHelper.removeItem<KtElement>(superTypeListEntry) EditCommaSeparatedListHelper.removeItem<KtElement>(superTypeListEntry)
} } else {
else {
deleteChildRange(findChildByType<PsiElement>(KtTokens.COLON) ?: specifierList, specifierList) deleteChildRange(findChildByType<PsiElement>(KtTokens.COLON) ?: specifierList, specifierList)
} }
} }
@@ -112,9 +112,11 @@ abstract class KtClassOrObject :
fun isAnnotation(): Boolean = hasModifier(KtTokens.ANNOTATION_KEYWORD) fun isAnnotation(): Boolean = hasModifier(KtTokens.ANNOTATION_KEYWORD)
fun getDeclarationKeyword(): PsiElement? = fun getDeclarationKeyword(): PsiElement? =
findChildByType(TokenSet.create( findChildByType(
TokenSet.create(
KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD, KtTokens.OBJECT_KEYWORD KtTokens.CLASS_KEYWORD, KtTokens.INTERFACE_KEYWORD, KtTokens.OBJECT_KEYWORD
)) )
)
override fun delete() { override fun delete() {
CheckUtil.checkWritable(this) CheckUtil.checkWritable(this)
@@ -122,8 +124,7 @@ abstract class KtClassOrObject :
val file = containingKtFile val file = containingKtFile
if (!isTopLevel() || file.declarations.size > 1) { if (!isTopLevel() || file.declarations.size > 1) {
super.delete() super.delete()
} } else {
else {
file.delete() file.delete()
} }
} }
@@ -37,7 +37,15 @@ abstract class KtCodeFragment(
imports: String?, // Should be separated by JetCodeFragment.IMPORT_SEPARATOR imports: String?, // Should be separated by JetCodeFragment.IMPORT_SEPARATOR
elementType: IElementType, elementType: IElementType,
private val context: PsiElement? private val context: PsiElement?
): KtFile((PsiManager.getInstance(_project) as PsiManagerEx).fileManager.createFileViewProvider(LightVirtualFile(name, KotlinFileType.INSTANCE, text), true), false), JavaCodeFragment { ) : KtFile(
(PsiManager.getInstance(_project) as PsiManagerEx).fileManager.createFileViewProvider(
LightVirtualFile(
name,
KotlinFileType.INSTANCE,
text
), true
), false
), JavaCodeFragment {
private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider
private var imports = LinkedHashSet<String>() private var imports = LinkedHashSet<String>()
@@ -93,7 +101,8 @@ abstract class KtCodeFragment(
clone.isPhysical = false clone.isPhysical = false
clone.originalFile = this clone.originalFile = this
clone.imports = imports clone.imports = imports
clone.viewProvider = SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false) clone.viewProvider =
SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false)
clone.viewProvider.forceCachedPsi(clone) clone.viewProvider.forceCachedPsi(clone)
return clone return clone
} }
@@ -58,15 +58,18 @@ class KtDotQualifiedExpression : KtExpressionImplStub<KotlinPlaceHolderStub<KtDo
private fun getChildExpressionsByStub(stub: KotlinPlaceHolderStub<KtDotQualifiedExpression>): Array<KtExpression>? { private fun getChildExpressionsByStub(stub: KotlinPlaceHolderStub<KtDotQualifiedExpression>): Array<KtExpression>? {
if (stub.getParentStubOfType(KtImportDirective::class.java) == null && if (stub.getParentStubOfType(KtImportDirective::class.java) == null &&
stub.getParentStubOfType(KtPackageDirective::class.java) == null) { stub.getParentStubOfType(KtPackageDirective::class.java) == null) {
LOG.error("KtDotQualifiedExpression should only have stubs inside import or package directives.\n" + LOG.error(
"Stubs were created for:\n$text\nFile text:\n${containingFile.text}") "KtDotQualifiedExpression should only have stubs inside import or package directives.\n" +
"Stubs were created for:\n$text\nFile text:\n${containingFile.text}"
)
return null return null
} } else {
else {
val expressions = stub.getChildrenByType(INSIDE_DIRECTIVE_EXPRESSIONS, KtExpression.ARRAY_FACTORY) val expressions = stub.getChildrenByType(INSIDE_DIRECTIVE_EXPRESSIONS, KtExpression.ARRAY_FACTORY)
if (expressions.size !in 1..2) { if (expressions.size !in 1..2) {
LOG.error("Invalid stub structure. DOT_QUALIFIED_EXPRESSION must have one or two children. Was: ${expressions.size}\n" + LOG.error(
"File text:\n${containingFile.text}") "Invalid stub structure. DOT_QUALIFIED_EXPRESSION must have one or two children. Was: ${expressions.size}\n" +
"File text:\n${containingFile.text}"
)
return null return null
} }
return expressions return expressions
@@ -85,8 +85,7 @@ open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) :
val packageDirective = packageDirective val packageDirective = packageDirective
if (packageDirective != null) { if (packageDirective != null) {
packageDirective.fqName = value packageDirective.fqName = value
} } else {
else {
val newPackageDirective = KtPsiFactory(this).createPackageDirectiveIfNeeded(value) ?: return val newPackageDirective = KtPsiFactory(this).createPackageDirectiveIfNeeded(value) ?: return
addAfter(newPackageDirective, null) addAfter(newPackageDirective, null)
} }
@@ -201,8 +200,7 @@ open class KtFile(viewProvider: FileViewProvider, val isCompiled: Boolean) :
if (visitor is KtVisitor<*, *>) { if (visitor is KtVisitor<*, *>) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
accept(visitor as KtVisitor<Any, Any?>, null) accept(visitor as KtVisitor<Any, Any?>, null)
} } else {
else {
visitor.visitFile(this) visitor.visitFile(this)
} }
} }
@@ -49,8 +49,7 @@ class KtObjectDeclaration : KtClassOrObject {
addAfter(psiFactory.createWhiteSpace(), getObjectKeyword()!!) addAfter(psiFactory.createWhiteSpace(), getObjectKeyword()!!)
result result
} } else {
else {
super.setName(name) super.setName(name)
} }
} }
@@ -36,8 +36,7 @@ fun setTypeReference(declaration: KtCallableDeclaration, addAfter: PsiElement?,
if (typeRef != null) { if (typeRef != null) {
return if (oldTypeRef != null) { return if (oldTypeRef != null) {
oldTypeRef.replace(typeRef) as KtTypeReference oldTypeRef.replace(typeRef) as KtTypeReference
} } else {
else {
val anchor = addAfter val anchor = addAfter
?: declaration.nameIdentifier?.siblings(forward = true)?.firstOrNull { it is PsiErrorElement } ?: declaration.nameIdentifier?.siblings(forward = true)?.firstOrNull { it is PsiErrorElement }
?: (declaration as? KtParameter)?.destructuringDeclaration ?: (declaration as? KtParameter)?.destructuringDeclaration
@@ -45,8 +44,7 @@ fun setTypeReference(declaration: KtCallableDeclaration, addAfter: PsiElement?,
declaration.addAfter(KtPsiFactory(declaration.project).createColon(), anchor) declaration.addAfter(KtPsiFactory(declaration.project).createColon(), anchor)
newTypeRef newTypeRef
} }
} } else {
else {
if (oldTypeRef != null) { if (oldTypeRef != null) {
val colon = declaration.colon!! val colon = declaration.colon!!
val removeFrom = colon.prevSibling as? PsiWhiteSpace ?: colon val removeFrom = colon.prevSibling as? PsiWhiteSpace ?: colon
@@ -67,8 +65,7 @@ private inline fun <T : KtElement> T.doSetReceiverTypeReference(
val newTypeRef = val newTypeRef =
if (oldTypeRef != null) { if (oldTypeRef != null) {
oldTypeRef.replace(typeRef) as KtTypeReference oldTypeRef.replace(typeRef) as KtTypeReference
} } else {
else {
val newTypeRef = addReceiverTypeReference(typeRef) val newTypeRef = addReceiverTypeReference(typeRef)
addAfter(KtPsiFactory(project).createDot(), newTypeRef.parentsWithSelf.first { it.parent == this }) addAfter(KtPsiFactory(project).createDot(), newTypeRef.parentsWithSelf.first { it.parent == this })
newTypeRef newTypeRef
@@ -79,8 +76,7 @@ private inline fun <T : KtElement> T.doSetReceiverTypeReference(
newTypeRef.add(argList.rightParenthesis!!) newTypeRef.add(argList.rightParenthesis!!)
} }
return newTypeRef return newTypeRef
} } else {
else {
if (oldTypeRef != null) { if (oldTypeRef != null) {
val dotSibling = oldTypeRef.parent as? KtFunctionTypeReceiver ?: oldTypeRef val dotSibling = oldTypeRef.parent as? KtFunctionTypeReceiver ?: oldTypeRef
val dot = dotSibling.siblings(forward = true).firstOrNull { it.node.elementType == KtTokens.DOT } val dot = dotSibling.siblings(forward = true).firstOrNull { it.node.elementType == KtTokens.DOT }
@@ -102,7 +98,9 @@ fun KtFunctionType.setReceiverTypeReference(typeRef: KtTypeReference?) =
typeRef, typeRef,
{ receiverTypeReference }, { receiverTypeReference },
{ {
(addBefore(KtPsiFactory(project).createFunctionTypeReceiver(it), (addBefore(
parameterList ?: firstChild) as KtFunctionTypeReceiver).typeReference KtPsiFactory(project).createFunctionTypeReceiver(it),
parameterList ?: firstChild
) as KtFunctionTypeReceiver).typeReference
} }
) )
@@ -20,7 +20,8 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
interface ValueArgument { interface ValueArgument {
@IfNotParsed fun getArgumentExpression(): KtExpression? @IfNotParsed
fun getArgumentExpression(): KtExpression?
fun getArgumentName(): ValueArgumentName? fun getArgumentName(): ValueArgumentName?
@@ -23,7 +23,11 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.psi.KtStringTemplateExpression
class KtStringTemplateExpressionManipulator : AbstractElementManipulator<KtStringTemplateExpression>() { class KtStringTemplateExpressionManipulator : AbstractElementManipulator<KtStringTemplateExpression>() {
override fun handleContentChange(element: KtStringTemplateExpression, range: TextRange, newContent: String): KtStringTemplateExpression? { override fun handleContentChange(
element: KtStringTemplateExpression,
range: TextRange,
newContent: String
): KtStringTemplateExpression? {
val node = element.node val node = element.node
val content = if (element.isSingleQuoted()) StringUtil.escapeStringCharacters(newContent) else newContent val content = if (element.isSingleQuoted()) StringUtil.escapeStringCharacters(newContent) else newContent
val oldText = node.text val oldText = node.text
@@ -22,8 +22,7 @@ data class PsiChildRange(val first: PsiElement?, val last: PsiElement?) : Sequen
init { init {
if (first == null) { if (first == null) {
assert(last == null) assert(last == null)
} } else {
else {
assert(first.parent == last!!.parent) assert(first.parent == last!!.parent)
} }
} }
@@ -34,8 +33,7 @@ data class PsiChildRange(val first: PsiElement?, val last: PsiElement?) : Sequen
override fun iterator(): Iterator<PsiElement> { override fun iterator(): Iterator<PsiElement> {
val sequence = if (first == null) { val sequence = if (first == null) {
emptySequence<PsiElement>() emptySequence<PsiElement>()
} } else {
else {
val afterLast = last!!.nextSibling val afterLast = last!!.nextSibling
first.siblings().takeWhile { it != afterLast } first.siblings().takeWhile { it != afterLast }
} }
@@ -23,7 +23,11 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
class StringTemplateExpressionManipulator : AbstractElementManipulator<KtStringTemplateExpression>() { class StringTemplateExpressionManipulator : AbstractElementManipulator<KtStringTemplateExpression>() {
override fun handleContentChange(element: KtStringTemplateExpression, range: TextRange, newContent: String): KtStringTemplateExpression? { override fun handleContentChange(
element: KtStringTemplateExpression,
range: TextRange,
newContent: String
): KtStringTemplateExpression? {
val node = element.node val node = element.node
val content = if (node.firstChildNode.textLength == 1) StringUtil.escapeStringCharacters(newContent) else newContent val content = if (node.firstChildNode.textLength == 1) StringUtil.escapeStringCharacters(newContent) else newContent
val oldText = node.text val oldText = node.text
@@ -71,7 +71,8 @@ open class StubIndexService protected constructor() {
} }
companion object { companion object {
@JvmStatic fun getInstance(): StubIndexService { @JvmStatic
fun getInstance(): StubIndexService {
return ServiceManager.getService(StubIndexService::class.java) ?: NO_INDEX return ServiceManager.getService(StubIndexService::class.java) ?: NO_INDEX
} }
@@ -22,8 +22,9 @@ import org.jetbrains.kotlin.psi.KtEnumEntrySuperclassReferenceExpression
import org.jetbrains.kotlin.psi.stubs.KotlinEnumEntrySuperclassReferenceExpressionStub import org.jetbrains.kotlin.psi.stubs.KotlinEnumEntrySuperclassReferenceExpressionStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
class KotlinEnumEntrySuperclassReferenceExpressionStubImpl(parent: StubElement<*>, private val referencedName: StringRef) class KotlinEnumEntrySuperclassReferenceExpressionStubImpl(parent: StubElement<*>, private val referencedName: StringRef) :
: KotlinStubBaseImpl<KtEnumEntrySuperclassReferenceExpression>(parent, KtStubElementTypes.ENUM_ENTRY_SUPERCLASS_REFERENCE_EXPRESSION), KotlinEnumEntrySuperclassReferenceExpressionStub { KotlinStubBaseImpl<KtEnumEntrySuperclassReferenceExpression>(parent, KtStubElementTypes.ENUM_ENTRY_SUPERCLASS_REFERENCE_EXPRESSION),
KotlinEnumEntrySuperclassReferenceExpressionStub {
override fun getReferencedName() = referencedName.string override fun getReferencedName() = referencedName.string
} }
@@ -26,9 +26,11 @@ object ModifierMaskUtils {
assert(MODIFIER_KEYWORDS_ARRAY.size <= 32) { "Current implementation depends on the ability to represent modifier list as bit mask" } assert(MODIFIER_KEYWORDS_ARRAY.size <= 32) { "Current implementation depends on the ability to represent modifier list as bit mask" }
} }
@JvmStatic fun computeMaskFromModifierList(modifierList: KtModifierList): Int = computeMask { modifierList.hasModifier(it) } @JvmStatic
fun computeMaskFromModifierList(modifierList: KtModifierList): Int = computeMask { modifierList.hasModifier(it) }
@JvmStatic fun computeMask(hasModifier: (KtModifierKeywordToken) -> Boolean): Int { @JvmStatic
fun computeMask(hasModifier: (KtModifierKeywordToken) -> Boolean): Int {
var mask = 0 var mask = 0
for ((index, modifierKeywordToken) in MODIFIER_KEYWORDS_ARRAY.withIndex()) { for ((index, modifierKeywordToken) in MODIFIER_KEYWORDS_ARRAY.withIndex()) {
if (hasModifier(modifierKeywordToken)) { if (hasModifier(modifierKeywordToken)) {
@@ -38,13 +40,15 @@ object ModifierMaskUtils {
return mask return mask
} }
@JvmStatic fun maskHasModifier(mask: Int, modifierToken: KtModifierKeywordToken): Boolean { @JvmStatic
fun maskHasModifier(mask: Int, modifierToken: KtModifierKeywordToken): Boolean {
val index = MODIFIER_KEYWORDS_ARRAY.indexOf(modifierToken) val index = MODIFIER_KEYWORDS_ARRAY.indexOf(modifierToken)
assert(index >= 0) { "All JetModifierKeywordTokens should be present in MODIFIER_KEYWORDS_ARRAY" } assert(index >= 0) { "All JetModifierKeywordTokens should be present in MODIFIER_KEYWORDS_ARRAY" }
return (mask and (1 shl index)) != 0 return (mask and (1 shl index)) != 0
} }
@JvmStatic fun maskToString(mask: Int): String { @JvmStatic
fun maskToString(mask: Int): String {
val sb = StringBuilder() val sb = StringBuilder()
sb.append("[") sb.append("[")
var first = true var first = true
@@ -174,12 +174,17 @@ class AnnotationChecker(
} }
if (useSiteTarget != null) { if (useSiteTarget != null) {
trace.report(Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on( trace.report(
entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName)) Errors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET.on(
} entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target", useSiteTarget.renderName
else { )
trace.report(Errors.WRONG_ANNOTATION_TARGET.on( )
entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target")) } else {
trace.report(
Errors.WRONG_ANNOTATION_TARGET.on(
entry, actualTargets.defaultTargets.firstOrNull()?.description ?: "unidentified target"
)
)
} }
} }
@@ -191,7 +196,8 @@ class AnnotationChecker(
return descriptor.annotationClass?.let(this::applicableTargetSet) ?: KotlinTarget.DEFAULT_TARGET_SET return descriptor.annotationClass?.let(this::applicableTargetSet) ?: KotlinTarget.DEFAULT_TARGET_SET
} }
@JvmStatic fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> { @JvmStatic
fun applicableTargetSet(descriptor: AnnotationDescriptor): Set<KotlinTarget> {
val classDescriptor = descriptor.annotationClass ?: return emptySet() val classDescriptor = descriptor.annotationClass ?: return emptySet()
return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET return applicableTargetSet(classDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
} }
@@ -211,8 +217,8 @@ class AnnotationChecker(
return getActualTargetList(annotated, descriptor, trace).defaultTargets return getActualTargetList(annotated, descriptor, trace).defaultTargets
} }
private fun DeclarationDescriptor?.hasBackingField(bindingTrace: BindingTrace) private fun DeclarationDescriptor?.hasBackingField(bindingTrace: BindingTrace) =
= (this as? PropertyDescriptor)?.let { bindingTrace.get(BindingContext.BACKING_FIELD_REQUIRED, it) } ?: false (this as? PropertyDescriptor)?.let { bindingTrace.get(BindingContext.BACKING_FIELD_REQUIRED, it) } ?: false
private fun getActualTargetList(annotated: KtElement, descriptor: DeclarationDescriptor?, trace: BindingTrace): TargetList { private fun getActualTargetList(annotated: KtElement, descriptor: DeclarationDescriptor?, trace: BindingTrace): TargetList {
return when (annotated) { return when (annotated) {
@@ -273,27 +279,30 @@ class AnnotationChecker(
if (backingField) extraTargets(FIELD) if (backingField) extraTargets(FIELD)
if (delegate) { if (delegate) {
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER, FIELD) onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER, FIELD)
} } else {
else {
onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER) onlyWithUseSiteTarget(VALUE_PARAMETER, PROPERTY_GETTER, PROPERTY_SETTER)
} }
} }
fun T_MEMBER_PROPERTY(backingField: Boolean, delegate: Boolean) = fun T_MEMBER_PROPERTY(backingField: Boolean, delegate: Boolean) =
targetList(when { targetList(
when {
backingField -> MEMBER_PROPERTY_WITH_BACKING_FIELD backingField -> MEMBER_PROPERTY_WITH_BACKING_FIELD
delegate -> MEMBER_PROPERTY_WITH_DELEGATE delegate -> MEMBER_PROPERTY_WITH_DELEGATE
else -> MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE else -> MEMBER_PROPERTY_WITHOUT_FIELD_OR_DELEGATE
}, MEMBER_PROPERTY, PROPERTY) { }, MEMBER_PROPERTY, PROPERTY
) {
propertyTargets(backingField, delegate) propertyTargets(backingField, delegate)
} }
fun T_TOP_LEVEL_PROPERTY(backingField: Boolean, delegate: Boolean) = fun T_TOP_LEVEL_PROPERTY(backingField: Boolean, delegate: Boolean) =
targetList(when { targetList(
when {
backingField -> TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD backingField -> TOP_LEVEL_PROPERTY_WITH_BACKING_FIELD
delegate -> TOP_LEVEL_PROPERTY_WITH_DELEGATE delegate -> TOP_LEVEL_PROPERTY_WITH_DELEGATE
else -> TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE else -> TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE
}, TOP_LEVEL_PROPERTY, PROPERTY) { }, TOP_LEVEL_PROPERTY, PROPERTY
) {
propertyTargets(backingField, delegate) propertyTargets(backingField, delegate)
} }
@@ -370,15 +379,20 @@ class AnnotationChecker(
private class TargetList( private class TargetList(
val defaultTargets: List<KotlinTarget>, val defaultTargets: List<KotlinTarget>,
val canBeSubstituted: List<KotlinTarget> = emptyList(), val canBeSubstituted: List<KotlinTarget> = emptyList(),
val onlyWithUseSiteTarget: List<KotlinTarget> = emptyList()) val onlyWithUseSiteTarget: List<KotlinTarget> = emptyList()
)
private object UseSiteTargetsList { private object UseSiteTargetsList {
val T_CONSTRUCTOR_PARAMETER = listOf(AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER, val T_CONSTRUCTOR_PARAMETER = listOf(
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER,
AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.FIELD) AnnotationUseSiteTarget.FIELD
)
val T_PROPERTY = listOf(AnnotationUseSiteTarget.PROPERTY, val T_PROPERTY = listOf(
AnnotationUseSiteTarget.FIELD) AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.FIELD
)
} }
} }
} }
@@ -46,26 +46,26 @@ object AnnotationUseSiteTargetChecker {
when (target) { when (target) {
AnnotationUseSiteTarget.FIELD -> checkIfHasBackingField(annotated, descriptor, annotation) AnnotationUseSiteTarget.FIELD -> checkIfHasBackingField(annotated, descriptor, annotation)
AnnotationUseSiteTarget.PROPERTY, AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.PROPERTY_GETTER -> {} AnnotationUseSiteTarget.PROPERTY_GETTER -> {
}
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> checkIfDelegatedProperty(annotated, annotation) AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> checkIfDelegatedProperty(annotated, annotation)
AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation) AnnotationUseSiteTarget.PROPERTY_SETTER -> checkIfMutableProperty(annotated, annotation)
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> { AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> {
if (annotated !is KtParameter) { if (annotated !is KtParameter) {
report(INAPPLICABLE_PARAM_TARGET.on(annotation)) report(INAPPLICABLE_PARAM_TARGET.on(annotation))
} } else {
else {
val containingDeclaration = bindingContext[BindingContext.VALUE_PARAMETER, annotated]?.containingDeclaration val containingDeclaration = bindingContext[BindingContext.VALUE_PARAMETER, annotated]?.containingDeclaration
if (containingDeclaration !is ConstructorDescriptor || !containingDeclaration.isPrimary) { if (containingDeclaration !is ConstructorDescriptor || !containingDeclaration.isPrimary) {
report(INAPPLICABLE_PARAM_TARGET.on(annotation)) report(INAPPLICABLE_PARAM_TARGET.on(annotation))
} } else if (!annotated.hasValOrVar()) {
else if (!annotated.hasValOrVar()) {
report(REDUNDANT_ANNOTATION_TARGET.on(annotation, target.renderName)) report(REDUNDANT_ANNOTATION_TARGET.on(annotation, target.renderName))
} }
} }
} }
AnnotationUseSiteTarget.SETTER_PARAMETER -> checkIfMutableProperty(annotated, annotation) AnnotationUseSiteTarget.SETTER_PARAMETER -> checkIfMutableProperty(annotated, annotation)
AnnotationUseSiteTarget.FILE -> reportDiagnosticOnce(INAPPLICABLE_FILE_TARGET.on(useSiteTarget)) AnnotationUseSiteTarget.FILE -> reportDiagnosticOnce(INAPPLICABLE_FILE_TARGET.on(useSiteTarget))
AnnotationUseSiteTarget.RECEIVER -> {} AnnotationUseSiteTarget.RECEIVER -> {
}
} }
} }
} }
@@ -76,7 +76,11 @@ object AnnotationUseSiteTargetChecker {
} }
} }
private fun BindingTrace.checkIfHasBackingField(annotated: KtAnnotated, descriptor: DeclarationDescriptor, annotation: KtAnnotationEntry) { private fun BindingTrace.checkIfHasBackingField(
annotated: KtAnnotated,
descriptor: DeclarationDescriptor,
annotation: KtAnnotationEntry
) {
if (annotated is KtProperty && annotated.hasDelegate() && if (annotated is KtProperty && annotated.hasDelegate() &&
descriptor is PropertyDescriptor && get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) != true) { descriptor is PropertyDescriptor && get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) != true) {
report(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD.on(annotation)) report(INAPPLICABLE_TARGET_PROPERTY_HAS_NO_BACKING_FIELD.on(annotation))
@@ -65,8 +65,7 @@ fun <C : ResolutionContext<C>> ResolutionContext<C>.recordDataFlowInfo(expressio
val typeInfo = trace.get(BindingContext.EXPRESSION_TYPE_INFO, expression) val typeInfo = trace.get(BindingContext.EXPRESSION_TYPE_INFO, expression)
if (typeInfo != null) { if (typeInfo != null) {
trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo.replaceDataFlowInfo(dataFlowInfo)) trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo.replaceDataFlowInfo(dataFlowInfo))
} } else if (dataFlowInfo != DataFlowInfo.EMPTY) {
else if (dataFlowInfo != DataFlowInfo.EMPTY) {
// Don't store anything in BindingTrace if it's simply an empty DataFlowInfo // Don't store anything in BindingTrace if it's simply an empty DataFlowInfo
trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, noTypeInfo(dataFlowInfo)) trace.record(BindingContext.EXPRESSION_TYPE_INFO, expression, noTypeInfo(dataFlowInfo))
} }
@@ -39,7 +39,11 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
class CollectionLiteralResolver(val module: ModuleDescriptor, val callResolver: CallResolver, val languageVersionSettings: LanguageVersionSettings) { class CollectionLiteralResolver(
val module: ModuleDescriptor,
val callResolver: CallResolver,
val languageVersionSettings: LanguageVersionSettings
) {
companion object { companion object {
val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf( val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf(
PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"), PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"),
@@ -76,8 +80,11 @@ class CollectionLiteralResolver(val module: ModuleDescriptor, val callResolver:
val callName = getArrayFunctionCallName(context.expectedType) val callName = getArrayFunctionCallName(context.expectedType)
val functionDescriptors = getFunctionDescriptorForCollectionLiteral(expression, callName) val functionDescriptors = getFunctionDescriptorForCollectionLiteral(expression, callName)
if (functionDescriptors.isEmpty()) { if (functionDescriptors.isEmpty()) {
context.trace.report(MISSING_STDLIB.on( context.trace.report(
expression, "Collection literal call '$callName()' is unresolved")) MISSING_STDLIB.on(
expression, "Collection literal call '$callName()' is unresolved"
)
)
return noTypeInfo(context) return noTypeInfo(context)
} }
@@ -86,7 +86,8 @@ class DelegatedPropertyResolver(
ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, variableDescriptor) ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, variableDescriptor)
else propertyHeaderScope else propertyHeaderScope
val byExpressionType = resolveDelegateExpression(delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo) val byExpressionType =
resolveDelegateExpression(delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo)
resolveProvideDelegateMethod(variableDescriptor, delegateExpression, byExpressionType, trace, initializerScope, outerDataFlowInfo) resolveProvideDelegateMethod(variableDescriptor, delegateExpression, byExpressionType, trace, initializerScope, outerDataFlowInfo)
val delegateType = getResolvedDelegateType(variableDescriptor, delegateExpression, byExpressionType, trace) val delegateType = getResolvedDelegateType(variableDescriptor, delegateExpression, byExpressionType, trace)
@@ -138,15 +139,19 @@ class DelegatedPropertyResolver(
initializerScope: LexicalScope, initializerScope: LexicalScope,
dataFlowInfo: DataFlowInfo dataFlowInfo: DataFlowInfo
) { ) {
val returnType = getGetValueMethodReturnType(variableDescriptor, delegateExpression, delegateType, trace, initializerScope, dataFlowInfo) val returnType =
getGetValueMethodReturnType(variableDescriptor, delegateExpression, delegateType, trace, initializerScope, dataFlowInfo)
val propertyType = variableDescriptor.type val propertyType = variableDescriptor.type
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */ /* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
if (propertyType !is DeferredType && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) { if (propertyType !is DeferredType && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, variableDescriptor.getter) val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, variableDescriptor.getter)
?: throw AssertionError("Call should exists for ${variableDescriptor.getter}") ?: throw AssertionError("Call should exists for ${variableDescriptor.getter}")
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH.on( trace.report(
delegateExpression, renderCall(call, trace.bindingContext), variableDescriptor.type, returnType)) DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH.on(
delegateExpression, renderCall(call, trace.bindingContext), variableDescriptor.type, returnType
)
)
} }
} }
@@ -158,8 +163,10 @@ class DelegatedPropertyResolver(
initializerScope: LexicalScope, initializerScope: LexicalScope,
dataFlowInfo: DataFlowInfo dataFlowInfo: DataFlowInfo
) { ) {
resolveGetSetValueMethod(variableDescriptor, delegateExpression, delegateType, trace, resolveGetSetValueMethod(
initializerScope, dataFlowInfo, false) variableDescriptor, delegateExpression, delegateType, trace,
initializerScope, dataFlowInfo, false
)
} }
private fun KtPsiFactory.createExpressionForProperty(): KtExpression { private fun KtPsiFactory.createExpressionForProperty(): KtExpression {
@@ -256,13 +263,16 @@ class DelegatedPropertyResolver(
val traceForProvideDelegate = TemporaryBindingTrace.create(trace, "trace to resolve provideDelegate method") val traceForProvideDelegate = TemporaryBindingTrace.create(trace, "trace to resolve provideDelegate method")
val provideDelegateResults = getProvideDelegateMethod(propertyDescriptor, byExpression, byExpressionType, val provideDelegateResults = getProvideDelegateMethod(
traceForProvideDelegate, initializerScope, dataFlowInfo) propertyDescriptor, byExpression, byExpressionType,
traceForProvideDelegate, initializerScope, dataFlowInfo
)
if (!provideDelegateResults.isSuccess) { if (!provideDelegateResults.isSuccess) {
val call = traceForProvideDelegate.bindingContext.get(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor) val call = traceForProvideDelegate.bindingContext.get(BindingContext.PROVIDE_DELEGATE_CALL, propertyDescriptor)
?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call") ?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call")
val shouldCommitTrace = reportDelegateOperatorResolutionError( val shouldCommitTrace = reportDelegateOperatorResolutionError(
traceForProvideDelegate, call, provideDelegateResults, byExpression, byExpressionType, operatorRequired = false) traceForProvideDelegate, call, provideDelegateResults, byExpression, byExpressionType, operatorRequired = false
)
if (shouldCommitTrace) { if (shouldCommitTrace) {
traceForProvideDelegate.commit() traceForProvideDelegate.commit()
@@ -314,9 +324,11 @@ class DelegatedPropertyResolver(
arguments.add(psiFactory.createExpressionForProperty()) arguments.add(psiFactory.createExpressionForProperty())
if (!isGet) { if (!isGet) {
val fakeArgument = createFakeExpressionOfType(delegateExpression.project, trace, val fakeArgument = createFakeExpressionOfType(
delegateExpression.project, trace,
"fakeArgument${arguments.size}", "fakeArgument${arguments.size}",
propertyDescriptor.type) as KtReferenceExpression propertyDescriptor.type
) as KtReferenceExpression
arguments.add(fakeArgument) arguments.add(fakeArgument)
val valueParameters = accessor.valueParameters val valueParameters = accessor.valueParameters
trace.record(REFERENCE_TARGET, fakeArgument, valueParameters[0]) trace.record(REFERENCE_TARGET, fakeArgument, valueParameters[0])
@@ -325,7 +337,8 @@ class DelegatedPropertyResolver(
val functionName = if (isGet) OperatorNameConventions.GET_VALUE else OperatorNameConventions.SET_VALUE val functionName = if (isGet) OperatorNameConventions.GET_VALUE else OperatorNameConventions.SET_VALUE
val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext) val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext)
val resolutionResult = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression) val resolutionResult =
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression)
trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.first) trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.first)
return resolutionResult.second return resolutionResult.second
@@ -397,14 +410,29 @@ class DelegatedPropertyResolver(
val traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property") val traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property")
val propertyExpectedType = if (property.typeReference != null) variableDescriptor.type else NO_EXPECTED_TYPE val propertyExpectedType = if (property.typeReference != null) variableDescriptor.type else NO_EXPECTED_TYPE
val completer = ConstraintSystemCompleterImpl(property, propertyExpectedType, variableDescriptor, delegateExpression, scopeForDelegate, trace, dataFlowInfo) val completer = ConstraintSystemCompleterImpl(
property,
propertyExpectedType,
variableDescriptor,
delegateExpression,
scopeForDelegate,
trace,
dataFlowInfo
)
delegateExpression.getCalleeExpressionIfAny()?.let { delegateExpression.getCalleeExpressionIfAny()?.let {
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer) traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, it, completer)
} }
val expectedTypeByNewInference = completer.resolveViaNewInference(delegateExpression, variableDescriptor, scopeForDelegate, trace, dataFlowInfo) val expectedTypeByNewInference =
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, expectedTypeByNewInference ?: NO_EXPECTED_TYPE, dataFlowInfo, traceToResolveDelegatedProperty) completer.resolveViaNewInference(delegateExpression, variableDescriptor, scopeForDelegate, trace, dataFlowInfo)
val delegateType = expressionTypingServices.safeGetType(
scopeForDelegate,
delegateExpression,
expectedTypeByNewInference ?: NO_EXPECTED_TYPE,
dataFlowInfo,
traceToResolveDelegatedProperty
)
traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true) traceToResolveDelegatedProperty.commit({ slice, _ -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
@@ -426,7 +454,8 @@ class DelegatedPropertyResolver(
val typeVariableSubstitutor = constraintSystem.typeVariableSubstitutors[resolvedCall.call.toHandle()] val typeVariableSubstitutor = constraintSystem.typeVariableSubstitutors[resolvedCall.call.toHandle()]
?: throw AssertionError("No substitutor in the system for call: " + resolvedCall.call) ?: throw AssertionError("No substitutor in the system for call: " + resolvedCall.call)
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods") val traceToResolveConventionMethods =
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
val delegateType = getDelegateType(returnType, constraintSystem, typeVariableSubstitutor, traceToResolveConventionMethods) val delegateType = getDelegateType(returnType, constraintSystem, typeVariableSubstitutor, traceToResolveConventionMethods)
@@ -485,8 +514,10 @@ class DelegatedPropertyResolver(
val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor
val provideDelegateReturnType = provideDelegateDescriptor.returnType val provideDelegateReturnType = provideDelegateDescriptor.returnType
if (provideDelegateDescriptor.isOperator) { if (provideDelegateDescriptor.isOperator) {
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, provideDelegateDescriptor, addConstraintForThisValue(
dispatchReceiverOnly = true) constraintSystem, typeVariableSubstitutor, provideDelegateDescriptor,
dispatchReceiverOnly = true
)
return provideDelegateReturnType return provideDelegateReturnType
?: throw AssertionError("No return type fore 'provideDelegate' of ${delegateExpression.text}") ?: throw AssertionError("No return type fore 'provideDelegate' of ${delegateExpression.text}")
} }
@@ -531,14 +562,19 @@ class DelegatedPropertyResolver(
): KotlinType? { ): KotlinType? {
if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return null if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return null
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods") val traceToResolveConventionMethods =
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
val delegateTypeInfo = expressionTypingServices.getTypeInfo(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo, val delegateTypeInfo = expressionTypingServices.getTypeInfo(
traceToResolveConventionMethods, false, delegateExpression, ContextDependency.DEPENDENT) scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE, dataFlowInfo,
traceToResolveConventionMethods, false, delegateExpression, ContextDependency.DEPENDENT
)
val contextForProvideDelegate = ExpressionTypingContext.newContext(traceToResolveConventionMethods, scopeForDelegate, delegateTypeInfo.dataFlowInfo, val contextForProvideDelegate = ExpressionTypingContext.newContext(
traceToResolveConventionMethods, scopeForDelegate, delegateTypeInfo.dataFlowInfo,
NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE, NO_EXPECTED_TYPE, ContextDependency.DEPENDENT, StatementFilter.NONE,
languageVersionSettings) languageVersionSettings
)
val delegateTypeConstructor = delegateTypeInfo.type?.constructor val delegateTypeConstructor = delegateTypeInfo.type?.constructor
@@ -556,8 +592,10 @@ class DelegatedPropertyResolver(
if (conventionMethodFound(provideDelegateResults)) { if (conventionMethodFound(provideDelegateResults)) {
val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor val provideDelegateDescriptor = provideDelegateResults.resultingDescriptor
if (provideDelegateDescriptor.isOperator) { if (provideDelegateDescriptor.isOperator) {
typeInfoForGetValueReceiver = KotlinTypeInfo(provideDelegateDescriptor.returnType, typeInfoForGetValueReceiver = KotlinTypeInfo(
provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo) provideDelegateDescriptor.returnType,
provideDelegateResults.resultingCall.dataFlowInfoForArguments.resultInfo
)
} }
} }
@@ -76,15 +76,18 @@ open class DelegatingBindingTrace(
} }
} }
constructor(parentContext: BindingContext, constructor(
parentContext: BindingContext,
debugName: String, debugName: String,
resolutionSubjectForMessage: Any?, resolutionSubjectForMessage: Any?,
filter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL, filter: BindingTraceFilter = BindingTraceFilter.ACCEPT_ALL,
allowSliceRewrite: Boolean = false allowSliceRewrite: Boolean = false
) : this(parentContext, ) : this(
parentContext,
AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage), AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage),
filter = filter, filter = filter,
allowSliceRewrite = allowSliceRewrite) allowSliceRewrite = allowSliceRewrite
)
override fun getBindingContext(): BindingContext = bindingContext override fun getBindingContext(): BindingContext = bindingContext
@@ -101,8 +104,7 @@ open class DelegatingBindingTrace(
if (slice is SetSlice<*>) { if (slice is SetSlice<*>) {
assert(value != null) assert(value != null)
if (value != SetSlice.DEFAULT) return value if (value != SetSlice.DEFAULT) return value
} } else if (value != null) {
else if (value != null) {
return value return value
} }
@@ -127,8 +129,7 @@ open class DelegatingBindingTrace(
var typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression) var typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression)
if (typeInfo == null) { if (typeInfo == null) {
typeInfo = createTypeInfo(type) typeInfo = createTypeInfo(type)
} } else {
else {
typeInfo = typeInfo.replaceType(type) typeInfo = typeInfo.replaceType(type)
} }
record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo) record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo)
@@ -139,7 +140,8 @@ open class DelegatingBindingTrace(
clear() clear()
} }
@JvmOverloads fun addOwnDataTo(trace: BindingTrace, filter: TraceEntryFilter? = null, commitDiagnostics: Boolean = true) { @JvmOverloads
fun addOwnDataTo(trace: BindingTrace, filter: TraceEntryFilter? = null, commitDiagnostics: Boolean = true) {
BindingContextUtils.addOwnDataTo(trace, filter, commitDiagnostics, map, mutableDiagnostics) BindingContextUtils.addOwnDataTo(trace, filter, commitDiagnostics, map, mutableDiagnostics)
} }
@@ -30,18 +30,14 @@ class ExceptionWrappingKtVisitorVoid(private val delegate: KtVisitorVoid) : KtVi
override fun visitDeclaration(dcl: KtDeclaration) { override fun visitDeclaration(dcl: KtDeclaration) {
try { try {
dcl.accept(delegate) dcl.accept(delegate)
} } catch (e: ProcessCanceledException) {
catch (e: ProcessCanceledException) {
throw e throw e
} } catch (e: KotlinFrontEndException) {
catch (e: KotlinFrontEndException) {
throw e throw e
} } catch (t: Throwable) {
catch (t: Throwable) {
val name = try { val name = try {
dcl.name dcl.name
} } catch (e: Throwable) {
catch (e: Throwable) {
"- error: ${e.message}" "- error: ${e.message}"
} }
throw KotlinFrontEndException("Failed to analyze declaration $name", t, dcl) throw KotlinFrontEndException("Failed to analyze declaration $name", t, dcl)
@@ -87,7 +87,8 @@ class FunctionDescriptorResolver(
if (function.name == null) trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function)) if (function.name == null) trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function))
return resolveFunctionDescriptor( return resolveFunctionDescriptor(
SimpleFunctionDescriptorImpl::create, containingDescriptor, scope, function, trace, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE) SimpleFunctionDescriptorImpl::create, containingDescriptor, scope, function, trace, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE
)
} }
@@ -99,7 +100,8 @@ class FunctionDescriptorResolver(
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
expectedFunctionType: KotlinType expectedFunctionType: KotlinType
): SimpleFunctionDescriptor = resolveFunctionDescriptor( ): SimpleFunctionDescriptor = resolveFunctionDescriptor(
::FunctionExpressionDescriptor, containingDescriptor, scope, function, trace, dataFlowInfo, expectedFunctionType) ::FunctionExpressionDescriptor, containingDescriptor, scope, function, trace, dataFlowInfo, expectedFunctionType
)
private fun resolveFunctionDescriptor( private fun resolveFunctionDescriptor(
functionConstructor: (DeclarationDescriptor, Annotations, Name, CallableMemberDescriptor.Kind, SourceElement) -> SimpleFunctionDescriptorImpl, functionConstructor: (DeclarationDescriptor, Annotations, Name, CallableMemberDescriptor.Kind, SourceElement) -> SimpleFunctionDescriptorImpl,
@@ -117,7 +119,15 @@ class FunctionDescriptorResolver(
CallableMemberDescriptor.Kind.DECLARATION, CallableMemberDescriptor.Kind.DECLARATION,
function.toSourceElement() function.toSourceElement()
) )
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, expectedFunctionType, dataFlowInfo) initializeFunctionDescriptorAndExplicitReturnType(
containingDescriptor,
scope,
function,
functionDescriptor,
trace,
expectedFunctionType,
dataFlowInfo
)
initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo) initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo)
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor) BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
return functionDescriptor return functionDescriptor
@@ -132,7 +142,8 @@ class FunctionDescriptorResolver(
) { ) {
if (functionDescriptor.returnType != null) return if (functionDescriptor.returnType != null) return
assert(function.typeReference == null) { assert(function.typeReference == null) {
"Return type must be initialized early for function: " + function.text + ", at: " + DiagnosticUtils.atLocation(function) } "Return type must be initialized early for function: " + function.text + ", at: " + DiagnosticUtils.atLocation(function)
}
val inferredReturnType = when { val inferredReturnType = when {
function.hasBlockBody() -> function.hasBlockBody() ->
@@ -154,32 +165,36 @@ class FunctionDescriptorResolver(
expectedFunctionType: KotlinType, expectedFunctionType: KotlinType,
dataFlowInfo: DataFlowInfo dataFlowInfo: DataFlowInfo
) { ) {
val headerScope = LexicalWritableScope(scope, functionDescriptor, true, val headerScope = LexicalWritableScope(
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER) scope, functionDescriptor, true,
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER
)
val typeParameterDescriptors = descriptorResolver. val typeParameterDescriptors =
resolveTypeParametersForDescriptor(functionDescriptor, headerScope, scope, function.typeParameters, trace) descriptorResolver.resolveTypeParametersForDescriptor(functionDescriptor, headerScope, scope, function.typeParameters, trace)
descriptorResolver.resolveGenericBounds(function, functionDescriptor, headerScope, typeParameterDescriptors, trace) descriptorResolver.resolveGenericBounds(function, functionDescriptor, headerScope, typeParameterDescriptors, trace)
val receiverTypeRef = function.receiverTypeReference val receiverTypeRef = function.receiverTypeReference
val receiverType = val receiverType =
if (receiverTypeRef != null) { if (receiverTypeRef != null) {
typeResolver.resolveType(headerScope, receiverTypeRef, trace, true) typeResolver.resolveType(headerScope, receiverTypeRef, trace, true)
} } else {
else {
if (function is KtFunctionLiteral) expectedFunctionType.getReceiverType() else null if (function is KtFunctionLiteral) expectedFunctionType.getReceiverType() else null
} }
val valueParameterDescriptors = createValueParameterDescriptors(function, functionDescriptor, headerScope, trace, expectedFunctionType) val valueParameterDescriptors =
createValueParameterDescriptors(function, functionDescriptor, headerScope, trace, expectedFunctionType)
headerScope.freeze() headerScope.freeze()
val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) } val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) }
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container)) val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container))
val modality = resolveMemberModalityFromModifiers(function, getDefaultModality(container, visibility, function.hasBody()), val modality = resolveMemberModalityFromModifiers(
trace.bindingContext, container) function, getDefaultModality(container, visibility, function.hasBody()),
trace.bindingContext, container
)
val contractProvider = getContractProvider(functionDescriptor, trace, scope, dataFlowInfo, function) val contractProvider = getContractProvider(functionDescriptor, trace, scope, dataFlowInfo, function)
functionDescriptor.initialize( functionDescriptor.initialize(
@@ -243,10 +258,12 @@ class FunctionDescriptorResolver(
if (expectedValueParameters.size == 1 && function is KtFunctionLiteral && function.getValueParameterList() == null) { if (expectedValueParameters.size == 1 && function is KtFunctionLiteral && function.getValueParameterList() == null) {
// it parameter for lambda // it parameter for lambda
val valueParameterDescriptor = expectedValueParameters.single() val valueParameterDescriptor = expectedValueParameters.single()
val it = ValueParameterDescriptorImpl(functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"), val it = ValueParameterDescriptorImpl(
functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
expectedParameterTypes!!.single(), valueParameterDescriptor.declaresDefaultValue(), expectedParameterTypes!!.single(), valueParameterDescriptor.declaresDefaultValue(),
valueParameterDescriptor.isCrossinline, valueParameterDescriptor.isNoinline, valueParameterDescriptor.isCrossinline, valueParameterDescriptor.isNoinline,
valueParameterDescriptor.varargElementType, SourceElement.NO_SOURCE) valueParameterDescriptor.varargElementType, SourceElement.NO_SOURCE
)
trace.record(BindingContext.AUTO_CREATED_IT, it) trace.record(BindingContext.AUTO_CREATED_IT, it)
return listOf(it) return listOf(it)
} }
@@ -279,8 +296,7 @@ class FunctionDescriptorResolver(
private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List<ValueParameterDescriptor>? = private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List<ValueParameterDescriptor>? =
if (functionTypeExpected()) { if (functionTypeExpected()) {
createValueParametersForInvokeInFunctionType(owner, this.getValueParameterTypesFromFunctionType()) createValueParametersForInvokeInFunctionType(owner, this.getValueParameterTypesFromFunctionType())
} } else null
else null
fun resolvePrimaryConstructorDescriptor( fun resolvePrimaryConstructorDescriptor(
scope: LexicalScope, scope: LexicalScope,
@@ -383,8 +399,7 @@ class FunctionDescriptorResolver(
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType)) trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
} }
} }
} } else {
else {
type = if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) { type = if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) {
val containsUninferredParameter = TypeUtils.contains(expectedType) { val containsUninferredParameter = TypeUtils.contains(expectedType) {
TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it) TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it)
@@ -394,8 +409,7 @@ class FunctionDescriptorResolver(
} }
expectedType ?: TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE expectedType ?: TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
} } else {
else {
trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter)) trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter))
ErrorUtils.createErrorType("Type annotation was missing for parameter ${valueParameter.nameAsSafeName}") ErrorUtils.createErrorType("Type annotation was missing for parameter ${valueParameter.nameAsSafeName}")
} }
@@ -411,8 +425,10 @@ class FunctionDescriptorResolver(
} }
} }
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor, val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(
valueParameter, i, type, trace) parameterScope, functionDescriptor,
valueParameter, i, type, trace
)
// Do not report NAME_SHADOWING for lambda destructured parameters as they may be not fully resolved at this time // Do not report NAME_SHADOWING for lambda destructured parameters as they may be not fully resolved at this time
ExpressionTypingUtils.checkVariableShadowing(parameterScope, trace, valueParameterDescriptor) ExpressionTypingUtils.checkVariableShadowing(parameterScope, trace, valueParameterDescriptor)
@@ -43,11 +43,11 @@ data class ImportPath @JvmOverloads constructor(val fqName: FqName, val isAllUnd
} }
companion object { companion object {
@JvmStatic fun fromString(pathStr: String): ImportPath { @JvmStatic
fun fromString(pathStr: String): ImportPath {
return if (pathStr.endsWith(".*")) { return if (pathStr.endsWith(".*")) {
ImportPath(FqName(pathStr.substring(0, pathStr.length - 2)), isAllUnder = true) ImportPath(FqName(pathStr.substring(0, pathStr.length - 2)), isAllUnder = true)
} } else {
else {
ImportPath(FqName(pathStr), isAllUnder = false) ImportPath(FqName(pathStr), isAllUnder = false)
} }
@@ -47,9 +47,13 @@ object LateinitModifierApplicabilityChecker {
if (type.isMarkedNullable) { if (type.isMarkedNullable) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of nullable types")) trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of nullable types"))
} } else if (TypeUtils.isNullableType(type)) {
else if (TypeUtils.isNullableType(type)) { trace.report(
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables of a type with nullable upper bound")) Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
modifier,
"is not allowed on $variables of a type with nullable upper bound"
)
)
} }
if (KotlinBuiltIns.isPrimitiveType(type)) { if (KotlinBuiltIns.isPrimitiveType(type)) {
@@ -59,8 +63,7 @@ object LateinitModifierApplicabilityChecker {
if (ktDeclaration is KtProperty) { if (ktDeclaration is KtProperty) {
if (ktDeclaration.hasDelegateExpression()) { if (ktDeclaration.hasDelegateExpression()) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on delegated properties")) trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on delegated properties"))
} } else if (ktDeclaration.hasInitializer()) {
else if (ktDeclaration.hasInitializer()) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables with initializer")) trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on $variables with initializer"))
} }
} }
@@ -81,9 +84,13 @@ object LateinitModifierApplicabilityChecker {
if (!hasDelegateExpressionOrInitializer) { if (!hasDelegateExpressionOrInitializer) {
if (hasAccessorImplementation) { if (hasAccessorImplementation) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties with a custom getter or setter")) trace.report(
} Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
else if (!isAbstract && !hasBackingField) { modifier,
"is not allowed on properties with a custom getter or setter"
)
)
} else if (!isAbstract && !hasBackingField) {
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field")) trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field"))
} }
} }
@@ -148,6 +148,5 @@ class LazyExplicitImportScope(
} }
private fun <D : CallableMemberDescriptor> Collection<D>.choseOnlyVisibleOrAll() = private fun <D : CallableMemberDescriptor> Collection<D>.choseOnlyVisibleOrAll() =
filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }. filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }.takeIf { it.isNotEmpty() } ?: this
takeIf { it.isNotEmpty() } ?: this
} }
@@ -78,16 +78,23 @@ class LocalVariableResolver(
val delegateExpression = property.delegateExpression val delegateExpression = property.delegateExpression
if (delegateExpression != null) { if (delegateExpression != null) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.LocalDelegatedProperties)) { if (!languageVersionSettings.supportsFeature(LanguageFeature.LocalDelegatedProperties)) {
context.trace.report(UNSUPPORTED_FEATURE.on(property.delegate!!, LanguageFeature.LocalDelegatedProperties to languageVersionSettings)) context.trace.report(
UNSUPPORTED_FEATURE.on(
property.delegate!!,
LanguageFeature.LocalDelegatedProperties to languageVersionSettings
)
)
} }
if (propertyDescriptor is VariableDescriptorWithAccessors) { if (propertyDescriptor is VariableDescriptorWithAccessors) {
delegatedPropertyResolver.resolvePropertyDelegate(typingContext.dataFlowInfo, delegatedPropertyResolver.resolvePropertyDelegate(
typingContext.dataFlowInfo,
property, property,
propertyDescriptor, propertyDescriptor,
delegateExpression, delegateExpression,
typingContext.scope, typingContext.scope,
typingContext.trace) typingContext.trace
)
propertyDescriptor.getter?.updateAccessorFlagsFromResolvedCallForDelegatedProperty(typingContext.trace) propertyDescriptor.getter?.updateAccessorFlagsFromResolvedCallForDelegatedProperty(typingContext.trace)
propertyDescriptor.setter?.updateAccessorFlagsFromResolvedCallForDelegatedProperty(typingContext.trace) propertyDescriptor.setter?.updateAccessorFlagsFromResolvedCallForDelegatedProperty(typingContext.trace)
} }
@@ -111,15 +118,19 @@ class LocalVariableResolver(
if (property.typeReference == null) { if (property.typeReference == null) {
val variableDataFlowValue = DataFlowValueFactory.createDataFlowValueForProperty( val variableDataFlowValue = DataFlowValueFactory.createDataFlowValueForProperty(
property, propertyDescriptor, context.trace.bindingContext, property, propertyDescriptor, context.trace.bindingContext,
DescriptorUtils.getContainingModuleOrNull(scope.ownerDescriptor)) DescriptorUtils.getContainingModuleOrNull(scope.ownerDescriptor)
)
// We cannot say here anything new about initializerDataFlowValue // We cannot say here anything new about initializerDataFlowValue
// except it has the same value as variableDataFlowValue // except it has the same value as variableDataFlowValue
typeInfo = typeInfo.replaceDataFlowInfo(dataFlowInfo.assign(variableDataFlowValue, initializerDataFlowValue, typeInfo = typeInfo.replaceDataFlowInfo(
languageVersionSettings)) dataFlowInfo.assign(
variableDataFlowValue, initializerDataFlowValue,
languageVersionSettings
)
)
} }
} }
} } else {
else {
typeInfo = noTypeInfo(context) typeInfo = noTypeInfo(context)
} }
@@ -171,8 +182,7 @@ class LocalVariableResolver(
initializeWithDefaultGetterSetter(propertyDescriptor) initializeWithDefaultGetterSetter(propertyDescriptor)
trace.record(BindingContext.VARIABLE, variable, propertyDescriptor) trace.record(BindingContext.VARIABLE, variable, propertyDescriptor)
result = propertyDescriptor result = propertyDescriptor
} } else {
else {
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace) val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
// For a local variable the type must not be deferred // For a local variable the type must not be deferred
type = variableTypeAndInitializerResolver.resolveType(variableDescriptor, scope, variable, dataFlowInfo, trace, local = true) type = variableTypeAndInitializerResolver.resolveType(variableDescriptor, scope, variable, dataFlowInfo, trace, local = true)
@@ -64,7 +64,12 @@ object OperatorModifierChecker {
diagnosticHolder.report(Errors.INAPPLICABLE_OPERATOR_MODIFIER.on(modifier, errorDescription)) diagnosticHolder.report(Errors.INAPPLICABLE_OPERATOR_MODIFIER.on(modifier, errorDescription))
} }
private fun checkSupportsFeature(feature: LanguageFeature, languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, modifier: PsiElement) { private fun checkSupportsFeature(
feature: LanguageFeature,
languageVersionSettings: LanguageVersionSettings,
diagnosticHolder: DiagnosticSink,
modifier: PsiElement
) {
if (!languageVersionSettings.supportsFeature(feature)) { if (!languageVersionSettings.supportsFeature(feature)) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature to languageVersionSettings)) diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature to languageVersionSettings))
} }
@@ -61,8 +61,10 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
val aSignature = FlatSignature.createFromCallableDescriptor(a) val aSignature = FlatSignature.createFromCallableDescriptor(a)
val bSignature = FlatSignature.createFromCallableDescriptor(b) val bSignature = FlatSignature.createFromCallableDescriptor(b)
val aIsNotLessSpecificThanB = ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks, specificityComparator) val aIsNotLessSpecificThanB = ConstraintSystemBuilderImpl.forSpecificity()
val bIsNotLessSpecificThanA = ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks, specificityComparator) .isSignatureNotLessSpecific(aSignature, bSignature, OverloadabilitySpecificityCallbacks, specificityComparator)
val bIsNotLessSpecificThanA = ConstraintSystemBuilderImpl.forSpecificity()
.isSignatureNotLessSpecific(bSignature, aSignature, OverloadabilitySpecificityCallbacks, specificityComparator)
return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA) return !(aIsNotLessSpecificThanB && bIsNotLessSpecificThanA)
} }
@@ -54,11 +54,9 @@ class OverloadResolver(
val containingDeclaration = klass.containingDeclaration val containingDeclaration = klass.containingDeclaration
if (containingDeclaration is ScriptDescriptor) { if (containingDeclaration is ScriptDescriptor) {
// TODO: check overload conflicts of functions with constructors in scripts // TODO: check overload conflicts of functions with constructors in scripts
} } else if (containingDeclaration is ClassDescriptor) {
else if (containingDeclaration is ClassDescriptor) {
constructorsByOuterClass.putValues(containingDeclaration, klass.constructors) constructorsByOuterClass.putValues(containingDeclaration, klass.constructors)
} } else if (!(containingDeclaration is FunctionDescriptor ||
else if (!(containingDeclaration is FunctionDescriptor ||
containingDeclaration is PropertyDescriptor || containingDeclaration is PropertyDescriptor ||
containingDeclaration is PackageFragmentDescriptor)) { containingDeclaration is PackageFragmentDescriptor)) {
throw IllegalStateException("Illegal class container: " + containingDeclaration) throw IllegalStateException("Illegal class container: " + containingDeclaration)
@@ -93,8 +91,7 @@ class OverloadResolver(
packageMembersByName, packageMembersByName,
(c.functions.values as Collection<DeclarationDescriptor>) + c.declaredClasses.values + c.typeAliases.values, (c.functions.values as Collection<DeclarationDescriptor>) + c.declaredClasses.values + c.typeAliases.values,
overloadFilter overloadFilter
) { ) { scope, name ->
scope, name ->
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS) val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS) val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
when (classifier) { when (classifier) {
@@ -110,8 +107,7 @@ class OverloadResolver(
} }
} }
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) { collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) { scope, name ->
scope, name ->
val variables = scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS) val variables = scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS) val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
variables + listOfNotNull(classifier) variables + listOfNotNull(classifier)
@@ -149,8 +145,7 @@ class OverloadResolver(
throw AssertionError("$descriptor is not a top-level package member") throw AssertionError("$descriptor is not a top-level package member")
} }
val containingModule = DescriptorUtils.getContainingModuleOrNull(descriptor) ?: val containingModule = DescriptorUtils.getContainingModuleOrNull(descriptor) ?: return when (descriptor) {
return when (descriptor) {
is CallableMemberDescriptor -> listOf(descriptor) is CallableMemberDescriptor -> listOf(descriptor)
is ClassDescriptor -> descriptor.constructors is ClassDescriptor -> descriptor.constructors
else -> throw AssertionError("Unexpected descriptor kind: $descriptor") else -> throw AssertionError("Unexpected descriptor kind: $descriptor")
@@ -47,8 +47,10 @@ class QualifiedExpressionResolver {
) { ) {
val packageNames = packageDirective.packageNames val packageNames = packageDirective.packageNames
for ((index, nameExpression) in packageNames.withIndex()) { for ((index, nameExpression) in packageNames.withIndex()) {
storeResult(trace, nameExpression, module.getPackage(packageDirective.getFqName(nameExpression)), storeResult(
shouldBeVisibleFrom = null, position = QualifierPosition.PACKAGE_HEADER, isQualifier = index != packageNames.lastIndex) trace, nameExpression, module.getPackage(packageDirective.getFqName(nameExpression)),
shouldBeVisibleFrom = null, position = QualifierPosition.PACKAGE_HEADER, isQualifier = index != packageNames.lastIndex
)
} }
} }
@@ -158,8 +160,7 @@ class QualifiedExpressionResolver {
val referenceExpression = userType.referenceExpression val referenceExpression = userType.referenceExpression
if (referenceExpression != null) { if (referenceExpression != null) {
result.add(QualifierPart(referenceExpression.getReferencedNameAsName(), referenceExpression, userType.typeArgumentList)) result.add(QualifierPart(referenceExpression.getReferencedNameAsName(), referenceExpression, userType.typeArgumentList))
} } else {
else {
hasError = true hasError = true
} }
userType = userType.qualifier userType = userType.qualifier
@@ -181,23 +182,32 @@ class QualifiedExpressionResolver {
when { when {
importDirective.suppressDiagnosticsInDebugMode() -> null importDirective.suppressDiagnosticsInDebugMode() -> null
packageFragmentForVisibilityCheck is DeclarationDescriptorWithSource && packageFragmentForVisibilityCheck.source == SourceElement.NO_SOURCE -> { packageFragmentForVisibilityCheck is DeclarationDescriptorWithSource && packageFragmentForVisibilityCheck.source == SourceElement.NO_SOURCE -> {
PackageFragmentWithCustomSource(packageFragmentForVisibilityCheck, KotlinSourceElement(importDirective.containingKtFile)) PackageFragmentWithCustomSource(
packageFragmentForVisibilityCheck,
KotlinSourceElement(importDirective.containingKtFile)
)
} }
else -> packageFragmentForVisibilityCheck else -> packageFragmentForVisibilityCheck
} }
if (importDirective.isAllUnder) { if (importDirective.isAllUnder) {
val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForCheck, val packageOrClassDescriptor = resolveToPackageOrClass(
scopeForFirstPart = null, position = QualifierPosition.IMPORT) ?: return null path, moduleDescriptor, trace, packageFragmentForCheck,
scopeForFirstPart = null, position = QualifierPosition.IMPORT
) ?: return null
if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) { if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) {
trace.report(Errors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star trace.report(
Errors.CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON.on(
lastPart.expression,
packageOrClassDescriptor
)
) // todo report on star
return null return null
} }
return AllUnderImportScope(packageOrClassDescriptor, excludedImportNames) return AllUnderImportScope(packageOrClassDescriptor, excludedImportNames)
} } else {
else {
return processSingleImport(moduleDescriptor, trace, importDirective, path, lastPart, packageFragmentForCheck) return processSingleImport(moduleDescriptor, trace, importDirective, path, lastPart, packageFragmentForCheck)
} }
} }
@@ -213,7 +223,14 @@ class QualifiedExpressionResolver {
val aliasName = KtPsiUtil.getAliasName(importDirective) val aliasName = KtPsiUtil.getAliasName(importDirective)
if (aliasName == null) { if (aliasName == null) {
// import kotlin. // import kotlin.
resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, position = QualifierPosition.IMPORT) resolveToPackageOrClass(
path,
moduleDescriptor,
trace,
packageFragmentForVisibilityCheck,
scopeForFirstPart = null,
position = QualifierPosition.IMPORT
)
return null return null
} }
@@ -222,15 +239,26 @@ class QualifiedExpressionResolver {
packageFragmentForVisibilityCheck, scopeForFirstPart = null, position = QualifierPosition.IMPORT packageFragmentForVisibilityCheck, scopeForFirstPart = null, position = QualifierPosition.IMPORT
) ?: return null ) ?: return null
val packageOrClassDescriptor = (resolvedDescriptor as? TypeAliasDescriptor)?.let { it.classDescriptor ?: return null } ?: resolvedDescriptor val packageOrClassDescriptor =
(resolvedDescriptor as? TypeAliasDescriptor)?.let { it.classDescriptor ?: return null } ?: resolvedDescriptor
return LazyExplicitImportScope(packageOrClassDescriptor, packageFragmentForVisibilityCheck, lastPart.name, aliasName) { return LazyExplicitImportScope(
candidates -> packageOrClassDescriptor,
packageFragmentForVisibilityCheck,
lastPart.name,
aliasName
) { candidates ->
if (candidates.isNotEmpty()) { if (candidates.isNotEmpty()) {
storeResult(trace, lastPart.expression, candidates, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT, isQualifier = false) storeResult(
} trace,
else { lastPart.expression,
candidates,
packageFragmentForVisibilityCheck,
position = QualifierPosition.IMPORT,
isQualifier = false
)
} else {
tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart) tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart)
} }
} }
@@ -264,7 +292,14 @@ class QualifiedExpressionResolver {
else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor") else -> throw IllegalStateException("Should be class or package: $packageOrClassDescriptor")
} }
storeResult(trace, lastPart.expression, descriptors, shouldBeVisibleFrom = null, position = QualifierPosition.IMPORT, isQualifier = false) storeResult(
trace,
lastPart.expression,
descriptors,
shouldBeVisibleFrom = null,
position = QualifierPosition.IMPORT,
isQualifier = false
)
} }
private fun KtExpression.asQualifierPartList(doubleColonLHS: Boolean = false): List<QualifierPart> { private fun KtExpression.asQualifierPartList(doubleColonLHS: Boolean = false): List<QualifierPart> {
@@ -377,12 +412,10 @@ class QualifiedExpressionResolver {
val packageView = val packageView =
if (qualifierPart.typeArguments == null) { if (qualifierPart.typeArguments == null) {
moduleDescriptor.getPackage(currentDescriptor.fqName.child(qualifierPart.name)) moduleDescriptor.getPackage(currentDescriptor.fqName.child(qualifierPart.name))
} } else null
else null
if (packageView != null && !packageView.isEmpty()) { if (packageView != null && !packageView.isEmpty()) {
packageView packageView
} } else {
else {
currentDescriptor.memberScope.getContributedClassifier(qualifierPart.name, qualifierPart.location) currentDescriptor.memberScope.getContributedClassifier(qualifierPart.name, qualifierPart.location)
} }
} }
@@ -419,12 +452,12 @@ class QualifiedExpressionResolver {
val qualifierDescriptor = when (receiver) { val qualifierDescriptor = when (receiver) {
is PackageQualifier -> { is PackageQualifier -> {
val childPackageFQN = receiver.descriptor.fqName.child(name) val childPackageFQN = receiver.descriptor.fqName.child(name)
receiver.descriptor.module.getPackage(childPackageFQN).takeUnless { it.isEmpty() } ?: receiver.descriptor.module.getPackage(childPackageFQN).takeUnless { it.isEmpty() }
receiver.descriptor.memberScope.getContributedClassifier(name, location) ?: receiver.descriptor.memberScope.getContributedClassifier(name, location)
} }
is ClassQualifier -> receiver.staticScope.getContributedClassifier(name, location) is ClassQualifier -> receiver.staticScope.getContributedClassifier(name, location)
null -> context.scope.findClassifier(name, location) ?: null -> context.scope.findClassifier(name, location)
context.scope.ownerDescriptor.module.getPackage(FqName.ROOT.child(name)).takeUnless { it.isEmpty() } ?: context.scope.ownerDescriptor.module.getPackage(FqName.ROOT.child(name)).takeUnless { it.isEmpty() }
is ReceiverValue -> receiver.type.memberScope.memberScopeAsImportingScope().findClassifier(name, location) is ReceiverValue -> receiver.type.memberScope.memberScopeAsImportingScope().findClassifier(name, location)
else -> null else -> null
} }
@@ -436,16 +469,20 @@ class QualifiedExpressionResolver {
return null return null
} }
data class QualifiedExpressionResolveResult(val classOrPackage: DeclarationDescriptor?, data class QualifiedExpressionResolveResult(
val memberName: Name?) { val classOrPackage: DeclarationDescriptor?,
val memberName: Name?
) {
companion object { companion object {
val UNRESOLVED = QualifiedExpressionResolveResult(null, null) val UNRESOLVED = QualifiedExpressionResolveResult(null, null)
} }
} }
fun resolveClassOrPackageInQualifiedExpression(expression: KtQualifiedExpression, fun resolveClassOrPackageInQualifiedExpression(
expression: KtQualifiedExpression,
scope: LexicalScope, scope: LexicalScope,
context: BindingContext): QualifiedExpressionResolveResult { context: BindingContext
): QualifiedExpressionResolveResult {
val qualifiedExpressions = unrollToLeftMostQualifiedExpression(expression) val qualifiedExpressions = unrollToLeftMostQualifiedExpression(expression)
val path = mapToQualifierParts(qualifiedExpressions, 0) val path = mapToQualifierParts(qualifiedExpressions, 0)
val trace = DelegatingBindingTrace(context, "Temp trace for resolving qualified expression") val trace = DelegatingBindingTrace(context, "Temp trace for resolving qualified expression")
@@ -493,8 +530,10 @@ class QualifiedExpressionResolver {
.map(::CallExpressionElement) .map(::CallExpressionElement)
} }
private fun mapToQualifierParts(qualifiedExpressions: List<KtQualifiedExpression>, private fun mapToQualifierParts(
skipLast: Int): List<QualifierPart> { qualifiedExpressions: List<KtQualifiedExpression>,
skipLast: Int
): List<QualifierPart> {
if (qualifiedExpressions.isEmpty()) return emptyList() if (qualifiedExpressions.isEmpty()) return emptyList()
val first = qualifiedExpressions.first() val first = qualifiedExpressions.first()
@@ -553,8 +592,10 @@ class QualifiedExpressionResolver {
path.foldRight(packageView) { (_, expression), currentView -> path.foldRight(packageView) { (_, expression), currentView ->
storeResult(trace, expression, currentView, shouldBeVisibleFrom = null, position = position) storeResult(trace, expression, currentView, shouldBeVisibleFrom = null, position = position)
currentView.containingDeclaration currentView.containingDeclaration
?: error("Containing Declaration must be not null for package with fqName: ${currentView.fqName}, " + ?: error(
"path: ${path.joinToString()}, packageView fqName: ${packageView.fqName}") "Containing Declaration must be not null for package with fqName: ${currentView.fqName}, " +
"path: ${path.joinToString()}, packageView fqName: ${packageView.fqName}"
)
} }
} }
@@ -580,8 +621,7 @@ class QualifiedExpressionResolver {
storeResult(trace, referenceExpression, visibleDescriptors.single(), null, position, isQualifier) storeResult(trace, referenceExpression, visibleDescriptors.single(), null, position, isQualifier)
} }
} }
} } else {
else {
storeResult(trace, referenceExpression, descriptors.singleOrNull(), shouldBeVisibleFrom, position, isQualifier) storeResult(trace, referenceExpression, descriptors.singleOrNull(), shouldBeVisibleFrom, position, isQualifier)
} }
} }
@@ -607,8 +647,7 @@ class QualifiedExpressionResolver {
val fromToCheck = val fromToCheck =
if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) { if (shouldBeVisibleFrom is PackageFragmentDescriptor && shouldBeVisibleFrom.source == SourceElement.NO_SOURCE && referenceExpression.containingFile !is DummyHolder) {
PackageFragmentWithCustomSource(shouldBeVisibleFrom, KotlinSourceElement(referenceExpression.containingKtFile)) PackageFragmentWithCustomSource(shouldBeVisibleFrom, KotlinSourceElement(referenceExpression.containingKtFile))
} } else {
else {
shouldBeVisibleFrom shouldBeVisibleFrom
} }
if (!isVisible(descriptor, fromToCheck, position)) { if (!isVisible(descriptor, fromToCheck, position)) {
@@ -619,7 +658,11 @@ class QualifiedExpressionResolver {
return if (isQualifier) storeQualifier(trace, referenceExpression, descriptor) else null return if (isQualifier) storeQualifier(trace, referenceExpression, descriptor) else null
} }
private fun storeQualifier(trace: BindingTrace, referenceExpression: KtSimpleNameExpression, descriptor: DeclarationDescriptor): Qualifier? { private fun storeQualifier(
trace: BindingTrace,
referenceExpression: KtSimpleNameExpression,
descriptor: DeclarationDescriptor
): Qualifier? {
val qualifier = val qualifier =
when (descriptor) { when (descriptor) {
is PackageViewDescriptor -> PackageQualifier(referenceExpression, descriptor) is PackageViewDescriptor -> PackageQualifier(referenceExpression, descriptor)
@@ -661,6 +704,7 @@ internal enum class QualifierPosition {
This purpose of this class is to pass information about source file for current package fragment in order for check visibilities between modules This purpose of this class is to pass information about source file for current package fragment in order for check visibilities between modules
(see ModuleVisibilityHelperImpl.isInFriendModule). (see ModuleVisibilityHelperImpl.isInFriendModule).
*/ */
private class PackageFragmentWithCustomSource(private val original: PackageFragmentDescriptor, private val source: SourceElement) : PackageFragmentDescriptor by original { private class PackageFragmentWithCustomSource(private val original: PackageFragmentDescriptor, private val source: SourceElement) :
PackageFragmentDescriptor by original {
override fun getSource(): SourceElement = source override fun getSource(): SourceElement = source
} }
@@ -51,7 +51,9 @@ class ShadowedExtensionChecker(val typeSpecificityComparator: TypeSpecificityCom
private fun checkShadowedExtensionFunction(declaration: KtDeclaration, extensionFunction: FunctionDescriptor, trace: DiagnosticSink) { private fun checkShadowedExtensionFunction(declaration: KtDeclaration, extensionFunction: FunctionDescriptor, trace: DiagnosticSink) {
val memberScope = extensionFunction.extensionReceiverParameter?.type?.memberScope ?: return val memberScope = extensionFunction.extensionReceiverParameter?.type?.memberScope ?: return
for (memberFunction in memberScope.getContributedFunctions(extensionFunction.name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)) { val contributedFunctions =
memberScope.getContributedFunctions(extensionFunction.name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
for (memberFunction in contributedFunctions) {
if (memberFunction.isPublic() && isExtensionFunctionShadowedByMemberFunction(extensionFunction, memberFunction)) { if (memberFunction.isPublic() && isExtensionFunctionShadowedByMemberFunction(extensionFunction, memberFunction)) {
trace.report(Errors.EXTENSION_SHADOWED_BY_MEMBER.on(declaration, memberFunction)) trace.report(Errors.EXTENSION_SHADOWED_BY_MEMBER.on(declaration, memberFunction))
return return
@@ -68,12 +70,20 @@ class ShadowedExtensionChecker(val typeSpecificityComparator: TypeSpecificityCom
} }
} }
for (memberProperty in memberScope.getContributedVariables(extensionFunction.name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)) { val contributedVariables =
memberScope.getContributedVariables(extensionFunction.name, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
for (memberProperty in contributedVariables) {
if (!memberProperty.isPublic()) continue if (!memberProperty.isPublic()) continue
val invokeOperator = getInvokeOperatorShadowingExtensionFunction(extensionFunction, memberProperty) val invokeOperator = getInvokeOperatorShadowingExtensionFunction(extensionFunction, memberProperty)
if (invokeOperator != null) { if (invokeOperator != null) {
trace.report(Errors.EXTENSION_FUNCTION_SHADOWED_BY_MEMBER_PROPERTY_WITH_INVOKE.on(declaration, memberProperty, invokeOperator)) trace.report(
Errors.EXTENSION_FUNCTION_SHADOWED_BY_MEMBER_PROPERTY_WITH_INVOKE.on(
declaration,
memberProperty,
invokeOperator
)
)
return return
} }
} }
@@ -99,11 +109,17 @@ class ShadowedExtensionChecker(val typeSpecificityComparator: TypeSpecificityCom
return isSignatureNotLessSpecific(extensionSignature, memberSignature) return isSignatureNotLessSpecific(extensionSignature, memberSignature)
} }
private fun getInvokeOperatorShadowingExtensionFunction(extension: FunctionDescriptor, member: PropertyDescriptor): FunctionDescriptor? = private fun getInvokeOperatorShadowingExtensionFunction(
extension: FunctionDescriptor,
member: PropertyDescriptor
): FunctionDescriptor? =
member.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS) member.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.WHEN_CHECK_DECLARATION_CONFLICTS)
.firstOrNull { it.isPublic() && it.isOperator && isExtensionFunctionShadowedByMemberFunction(extension, it) } .firstOrNull { it.isPublic() && it.isOperator && isExtensionFunctionShadowedByMemberFunction(extension, it) }
private fun isSignatureNotLessSpecific(extensionSignature: FlatSignature<FunctionDescriptor>, memberSignature: FlatSignature<FunctionDescriptor>): Boolean = private fun isSignatureNotLessSpecific(
extensionSignature: FlatSignature<FunctionDescriptor>,
memberSignature: FlatSignature<FunctionDescriptor>
): Boolean =
ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific( ConstraintSystemBuilderImpl.forSpecificity().isSignatureNotLessSpecific(
extensionSignature, extensionSignature,
memberSignature, memberSignature,
@@ -25,7 +25,8 @@ open class StatementFilter {
get() = null get() = null
companion object { companion object {
@JvmField val NONE = object : StatementFilter() { @JvmField
val NONE = object : StatementFilter() {
override fun toString() = "NONE" override fun toString() = "NONE"
} }
} }
@@ -40,8 +40,8 @@ abstract class TargetPlatform(val platformName: String) {
abstract val multiTargetPlatform: MultiTargetPlatform abstract val multiTargetPlatform: MultiTargetPlatform
object Common : TargetPlatform("Default") { object Common : TargetPlatform("Default") {
private val defaultImports = LockBasedStorageManager().createMemoizedFunction<Boolean, List<ImportPath>> { private val defaultImports =
includeKotlinComparisons -> LockBasedStorageManager().createMemoizedFunction<Boolean, List<ImportPath>> { includeKotlinComparisons ->
ArrayList<ImportPath>().apply { ArrayList<ImportPath>().apply {
listOf( listOf(
"kotlin.*", "kotlin.*",
@@ -125,7 +125,8 @@ abstract class PlatformConfigurator(
private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers private val declarationCheckers: List<DeclarationChecker> = DEFAULT_DECLARATION_CHECKERS + additionalDeclarationCheckers
private val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers private val callCheckers: List<CallChecker> = DEFAULT_CALL_CHECKERS + additionalCallCheckers
private val typeCheckers: List<AdditionalTypeChecker> = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers private val typeCheckers: List<AdditionalTypeChecker> = DEFAULT_TYPE_CHECKERS + additionalTypeCheckers
private val classifierUsageCheckers: List<ClassifierUsageChecker> = DEFAULT_CLASSIFIER_USAGE_CHECKERS + additionalClassifierUsageCheckers private val classifierUsageCheckers: List<ClassifierUsageChecker> =
DEFAULT_CLASSIFIER_USAGE_CHECKERS + additionalClassifierUsageCheckers
abstract fun configureModuleComponents(container: StorageComponentContainer) abstract fun configureModuleComponents(container: StorageComponentContainer)
@@ -145,5 +146,5 @@ abstract class PlatformConfigurator(
} }
} }
fun createContainer(id: String, platform: TargetPlatform, init: StorageComponentContainer.() -> Unit) fun createContainer(id: String, platform: TargetPlatform, init: StorageComponentContainer.() -> Unit) =
= composeContainer(id, platform.platformConfigurator.platformSpecificContainer, init) composeContainer(id, platform.platformConfigurator.platformSpecificContainer, init)
@@ -31,12 +31,16 @@ class TypeAliasExpander(
) { ) {
fun expand(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) = fun expand(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) =
expandRecursively(typeAliasExpansion, annotations, expandRecursively(
isNullable = false, recursionDepth = 0, withAbbreviatedType = true) typeAliasExpansion, annotations,
isNullable = false, recursionDepth = 0, withAbbreviatedType = true
)
fun expandWithoutAbbreviation(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) = fun expandWithoutAbbreviation(typeAliasExpansion: TypeAliasExpansion, annotations: Annotations) =
expandRecursively(typeAliasExpansion, annotations, expandRecursively(
isNullable = false, recursionDepth = 0, withAbbreviatedType = false) typeAliasExpansion, annotations,
isNullable = false, recursionDepth = 0, withAbbreviatedType = false
)
private fun expandRecursively( private fun expandRecursively(
typeAliasExpansion: TypeAliasExpansion, typeAliasExpansion: TypeAliasExpansion,
@@ -56,7 +60,8 @@ class TypeAliasExpander(
} }
checkRepeatedAnnotations(expandedType.annotations, annotations) checkRepeatedAnnotations(expandedType.annotations, annotations)
val expandedTypeWithExtraAnnotations = expandedType.combineAnnotations(annotations).let { TypeUtils.makeNullableIfNeeded(it, isNullable) } val expandedTypeWithExtraAnnotations =
expandedType.combineAnnotations(annotations).let { TypeUtils.makeNullableIfNeeded(it, isNullable) }
return if (withAbbreviatedType) return if (withAbbreviatedType)
expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(annotations, isNullable)) expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(annotations, isNullable))
@@ -85,8 +90,12 @@ class TypeAliasExpander(
if (underlyingProjection.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!) if (underlyingProjection.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!)
val underlyingType = underlyingProjection.type val underlyingType = underlyingProjection.type
val argument = typeAliasExpansion.getReplacement(underlyingType.constructor) ?: val argument = typeAliasExpansion.getReplacement(underlyingType.constructor)
return expandNonArgumentTypeProjection(underlyingProjection, typeAliasExpansion, recursionDepth) ?: return expandNonArgumentTypeProjection(
underlyingProjection,
typeAliasExpansion,
recursionDepth
)
if (argument.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!) if (argument.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!)
@@ -186,7 +195,10 @@ class TypeAliasExpander(
is TypeAliasDescriptor -> { is TypeAliasDescriptor -> {
if (typeAliasExpansion.isRecursion(typeDescriptor)) { if (typeAliasExpansion.isRecursion(typeDescriptor)) {
reportStrategy.recursiveTypeAlias(typeDescriptor) reportStrategy.recursiveTypeAlias(typeDescriptor)
return TypeProjectionImpl(Variance.INVARIANT, ErrorUtils.createErrorType("Recursive type alias: ${typeDescriptor.name}")) return TypeProjectionImpl(
Variance.INVARIANT,
ErrorUtils.createErrorType("Recursive type alias: ${typeDescriptor.name}")
)
} }
val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument -> val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument ->
@@ -195,23 +207,29 @@ class TypeAliasExpander(
val nestedExpansion = TypeAliasExpansion.create(typeAliasExpansion, typeDescriptor, expandedArguments) val nestedExpansion = TypeAliasExpansion.create(typeAliasExpansion, typeDescriptor, expandedArguments)
val nestedExpandedType = expandRecursively(nestedExpansion, type.annotations, val nestedExpandedType = expandRecursively(
nestedExpansion, type.annotations,
isNullable = type.isMarkedNullable, isNullable = type.isMarkedNullable,
recursionDepth = recursionDepth + 1, recursionDepth = recursionDepth + 1,
withAbbreviatedType = false) withAbbreviatedType = false
)
// 'dynamic' type can't be abbreviated - will be reported separately // 'dynamic' type can't be abbreviated - will be reported separately
val typeWithAbbreviation = if (nestedExpandedType.isDynamic()) nestedExpandedType else nestedExpandedType.withAbbreviation(type) val typeWithAbbreviation =
if (nestedExpandedType.isDynamic()) nestedExpandedType else nestedExpandedType.withAbbreviation(type)
TypeProjectionImpl(originalProjection.projectionKind, typeWithAbbreviation) TypeProjectionImpl(originalProjection.projectionKind, typeWithAbbreviation)
} }
else -> { else -> {
val substitutedArguments = type.arguments.mapIndexed { i, originalArgument -> val substitutedArguments = type.arguments.mapIndexed { i, originalArgument ->
val projection = expandTypeProjection( val projection = expandTypeProjection(
originalArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth + 1) originalArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth + 1
)
if (projection.isStarProjection) projection if (projection.isStarProjection) projection
else TypeProjectionImpl(projection.projectionKind, else TypeProjectionImpl(
TypeUtils.makeNullableIfNeeded(projection.type, originalArgument.type.isMarkedNullable)) projection.projectionKind,
TypeUtils.makeNullableIfNeeded(projection.type, originalArgument.type.isMarkedNullable)
)
} }
val substitutedType = type.replace(newArguments = substitutedArguments) val substitutedType = type.replace(newArguments = substitutedArguments)
@@ -231,7 +249,13 @@ class TypeAliasExpander(
val unsubstitutedArgument = unsubstitutedType.arguments[i] val unsubstitutedArgument = unsubstitutedType.arguments[i]
val typeParameter = unsubstitutedType.constructor.parameters[i] val typeParameter = unsubstitutedType.constructor.parameters[i]
if (shouldCheckBounds) { if (shouldCheckBounds) {
DescriptorResolver.checkBoundsInTypeAlias(reportStrategy, unsubstitutedArgument.type, substitutedArgument.type, typeParameter, typeSubstitutor) DescriptorResolver.checkBoundsInTypeAlias(
reportStrategy,
unsubstitutedArgument.type,
substitutedArgument.type,
typeParameter,
typeSubstitutor
)
} }
} }
} }
@@ -25,14 +25,33 @@ interface TypeAliasExpansionReportStrategy {
fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int)
fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType) fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType)
fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor)
fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) fun boundsViolationInSubstitution(
bound: KotlinType,
unsubstitutedArgument: KotlinType,
argument: KotlinType,
typeParameter: TypeParameterDescriptor
)
fun repeatedAnnotation(annotation: AnnotationDescriptor) fun repeatedAnnotation(annotation: AnnotationDescriptor)
object DO_NOTHING : TypeAliasExpansionReportStrategy { object DO_NOTHING : TypeAliasExpansionReportStrategy {
override fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) {} override fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) {}
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType) {} override fun conflictingProjection(
typeAlias: TypeAliasDescriptor,
typeParameter: TypeParameterDescriptor?,
substitutedArgument: KotlinType
) {
}
override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {} override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {}
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) {} override fun boundsViolationInSubstitution(
bound: KotlinType,
unsubstitutedArgument: KotlinType,
argument: KotlinType,
typeParameter: TypeParameterDescriptor
) {
}
override fun repeatedAnnotation(annotation: AnnotationDescriptor) {} override fun repeatedAnnotation(annotation: AnnotationDescriptor) {}
} }
} }
@@ -75,12 +75,17 @@ class TypeResolver(
fun resolveType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType { fun resolveType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType {
// bare types are not allowed // bare types are not allowed
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode(), false), typeReference) return resolveType(
TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode(), false),
typeReference
)
} }
fun resolveAbbreviatedType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace): SimpleType { fun resolveAbbreviatedType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace): SimpleType {
val resolvedType = resolveType(TypeResolutionContext(scope, trace, true, false, typeReference.suppressDiagnosticsInDebugMode(), true), val resolvedType = resolveType(
typeReference).unwrap() TypeResolutionContext(scope, trace, true, false, typeReference.suppressDiagnosticsInDebugMode(), true),
typeReference
).unwrap()
return when (resolvedType) { return when (resolvedType) {
is DynamicType -> { is DynamicType -> {
trace.report(Errors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS.on(typeReference, resolvedType)) trace.report(Errors.TYPEALIAS_SHOULD_EXPAND_TO_CLASS.on(typeReference, resolvedType))
@@ -168,8 +173,7 @@ class TypeResolver(
if (type.isFlexible()) { if (type.isFlexible()) {
forceResolveTypeContents(type.asFlexibleType().lowerBound) forceResolveTypeContents(type.asFlexibleType().lowerBound)
forceResolveTypeContents(type.asFlexibleType().upperBound) forceResolveTypeContents(type.asFlexibleType().upperBound)
} } else {
else {
type.constructor // force read type constructor type.constructor // force read type constructor
for (projection in type.arguments) { for (projection in type.arguments) {
if (!projection.isStarProjection) { if (!projection.isStarProjection) {
@@ -179,15 +183,19 @@ class TypeResolver(
} }
} }
private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, outerModifierList: KtModifierList?, typeElement: KtTypeElement?): PossiblyBareType { private fun resolveTypeElement(
c: TypeResolutionContext,
annotations: Annotations,
outerModifierList: KtModifierList?,
typeElement: KtTypeElement?
): PossiblyBareType {
var result: PossiblyBareType? = null var result: PossiblyBareType? = null
val hasSuspendModifier = outerModifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) ?: false val hasSuspendModifier = outerModifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) ?: false
val suspendModifier = outerModifierList?.getModifier(KtTokens.SUSPEND_KEYWORD) val suspendModifier = outerModifierList?.getModifier(KtTokens.SUSPEND_KEYWORD)
if (hasSuspendModifier && !typeElement.canHaveFunctionTypeModifiers()) { if (hasSuspendModifier && !typeElement.canHaveFunctionTypeModifiers()) {
c.trace.report(Errors.WRONG_MODIFIER_TARGET.on(suspendModifier!!, KtTokens.SUSPEND_KEYWORD, "non-functional type")) c.trace.report(Errors.WRONG_MODIFIER_TARGET.on(suspendModifier!!, KtTokens.SUSPEND_KEYWORD, "non-functional type"))
} } else if (hasSuspendModifier) {
else if (hasSuspendModifier) {
checkCoroutinesFeature(languageVersionSettings, c.trace, suspendModifier!!) checkCoroutinesFeature(languageVersionSettings, c.trace, suspendModifier!!)
} }
@@ -239,13 +247,15 @@ class TypeResolver(
val returnType = if (returnTypeRef != null) resolveType(c.noBareTypes(), returnTypeRef) val returnType = if (returnTypeRef != null) resolveType(c.noBareTypes(), returnTypeRef)
else moduleDescriptor.builtIns.unitType else moduleDescriptor.builtIns.unitType
result = type(createFunctionType( result = type(
createFunctionType(
moduleDescriptor.builtIns, annotations, receiverType, moduleDescriptor.builtIns, annotations, receiverType,
parameterDescriptors.map { it.type }, parameterDescriptors.map { it.type },
parameterDescriptors.map { it.name }, parameterDescriptors.map { it.name },
returnType, returnType,
suspendFunction = hasSuspendModifier suspendFunction = hasSuspendModifier
)) )
)
} }
private fun checkParametersOfFunctionType(parameterDescriptors: List<VariableDescriptor>) { private fun checkParametersOfFunctionType(parameterDescriptors: List<VariableDescriptor>) {
@@ -332,7 +342,8 @@ class TypeResolver(
if (modifierList != null) { if (modifierList != null) {
KtTokens.MODIFIER_KEYWORDS_ARRAY KtTokens.MODIFIER_KEYWORDS_ARRAY
.mapNotNull { modifierList.getModifier(it) } .mapNotNull { modifierList.getModifier(it) }
.forEach { c.trace.report(Errors.UNSUPPORTED.on(it, "modifier on parameter in function type")) .forEach {
c.trace.report(Errors.UNSUPPORTED.on(it, "modifier on parameter in function type"))
} }
} }
@@ -369,11 +380,13 @@ class TypeResolver(
return if (scopeForTypeParameter is ErrorUtils.ErrorScope) return if (scopeForTypeParameter is ErrorUtils.ErrorScope)
ErrorUtils.createErrorType("?") ErrorUtils.createErrorType("?")
else else
KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(annotations, KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
annotations,
typeParameter.typeConstructor, typeParameter.typeConstructor,
listOf(), listOf(),
false, false,
scopeForTypeParameter) scopeForTypeParameter
)
} }
private fun getScopeForTypeParameter(c: TypeResolutionContext, typeParameterDescriptor: TypeParameterDescriptor): MemberScope { private fun getScopeForTypeParameter(c: TypeResolutionContext, typeParameterDescriptor: TypeParameterDescriptor): MemberScope {
@@ -543,8 +556,7 @@ class TypeResolver(
return if (c.abbreviated) { return if (c.abbreviated) {
val abbreviatedType = KotlinTypeFactory.simpleType(annotations, descriptor.typeConstructor, arguments, false) val abbreviatedType = KotlinTypeFactory.simpleType(annotations, descriptor.typeConstructor, arguments, false)
type(abbreviatedType) type(abbreviatedType)
} } else {
else {
val typeAliasExpansion = TypeAliasExpansion.create(null, descriptor, arguments) val typeAliasExpansion = TypeAliasExpansion.create(null, descriptor, arguments)
val expandedType = TypeAliasExpander(reportStrategy, c.checkBounds).expand(typeAliasExpansion, annotations) val expandedType = TypeAliasExpander(reportStrategy, c.checkBounds).expand(typeAliasExpansion, annotations)
type(expandedType) type(expandedType)
@@ -606,12 +618,15 @@ class TypeResolver(
} }
} }
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, substitutedArgument: KotlinType) { override fun conflictingProjection(
typeAlias: TypeAliasDescriptor,
typeParameter: TypeParameterDescriptor?,
substitutedArgument: KotlinType
) {
val argumentElement = typeParameter?.let { mappedArguments[it] } val argumentElement = typeParameter?.let { mappedArguments[it] }
if (argumentElement != null) { if (argumentElement != null) {
trace.report(CONFLICTING_PROJECTION.on(argumentElement, typeParameter)) trace.report(CONFLICTING_PROJECTION.on(argumentElement, typeParameter))
} } else if (type != null) {
else if (type != null) {
trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(type, typeAliasDescriptor.underlyingType)) trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(type, typeAliasDescriptor.underlyingType))
} }
} }
@@ -622,14 +637,18 @@ class TypeResolver(
} }
} }
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) { override fun boundsViolationInSubstitution(
bound: KotlinType,
unsubstitutedArgument: KotlinType,
argument: KotlinType,
typeParameter: TypeParameterDescriptor
) {
val descriptorForUnsubstitutedArgument = unsubstitutedArgument.constructor.declarationDescriptor val descriptorForUnsubstitutedArgument = unsubstitutedArgument.constructor.declarationDescriptor
val argumentElement = mappedArguments[descriptorForUnsubstitutedArgument] val argumentElement = mappedArguments[descriptorForUnsubstitutedArgument]
val argumentTypeReferenceElement = argumentElement?.typeReference val argumentTypeReferenceElement = argumentElement?.typeReference
if (argumentTypeReferenceElement != null) { if (argumentTypeReferenceElement != null) {
trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReferenceElement, bound, argument)) trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReferenceElement, bound, argument))
} } else if (type != null) {
else if (type != null) {
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(type, bound, argument, typeParameter)) trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(type, bound, argument, typeParameter))
} }
} }
@@ -645,10 +664,12 @@ class TypeResolver(
arguments: List<KtTypeProjection>, arguments: List<KtTypeProjection>,
typeConstructor: TypeConstructor typeConstructor: TypeConstructor
): PossiblyBareType = ): PossiblyBareType =
type(ErrorUtils.createErrorTypeWithArguments( type(
ErrorUtils.createErrorTypeWithArguments(
typeConstructor.declarationDescriptor?.name?.asString() ?: typeConstructor.toString(), typeConstructor.declarationDescriptor?.name?.asString() ?: typeConstructor.toString(),
resolveTypeProjectionsWithErrorConstructor(c, arguments) resolveTypeProjectionsWithErrorConstructor(c, arguments)
)) )
)
// Returns true in case when at least one argument for this class could be specified // Returns true in case when at least one argument for this class could be specified
// It could be always equal to 'typeConstructor.parameters.isNotEmpty()' unless local classes could captured type parameters // It could be always equal to 'typeConstructor.parameters.isNotEmpty()' unless local classes could captured type parameters
@@ -716,7 +737,8 @@ class TypeResolver(
val nonClassQualifierParts = val nonClassQualifierParts =
reversedQualifierParts.subList( reversedQualifierParts.subList(
Math.min(classifierChainLastIndex + 1, reversedQualifierParts.size), Math.min(classifierChainLastIndex + 1, reversedQualifierParts.size),
reversedQualifierParts.size) reversedQualifierParts.size
)
for ((_, _, typeArguments) in nonClassQualifierParts) { for ((_, _, typeArguments) in nonClassQualifierParts) {
if (typeArguments != null) { if (typeArguments != null) {
@@ -741,17 +763,16 @@ class TypeResolver(
if (restArguments == null && typeArgumentsCanBeSpecifiedCount > result.size) { if (restArguments == null && typeArgumentsCanBeSpecifiedCount > result.size) {
c.trace.report( c.trace.report(
OUTER_CLASS_ARGUMENTS_REQUIRED.on(qualifierParts.first().expression, nextParameterOwner)) OUTER_CLASS_ARGUMENTS_REQUIRED.on(qualifierParts.first().expression, nextParameterOwner)
)
return null return null
} } else if (restArguments == null) {
else if (restArguments == null) {
assert(typeArgumentsCanBeSpecifiedCount == result.size) { assert(typeArgumentsCanBeSpecifiedCount == result.size) {
"Number of type arguments that can be specified ($typeArgumentsCanBeSpecifiedCount) " + "Number of type arguments that can be specified ($typeArgumentsCanBeSpecifiedCount) " +
"should be equal to actual arguments number ${result.size}, (classifier: $classifierDescriptor)" "should be equal to actual arguments number ${result.size}, (classifier: $classifierDescriptor)"
} }
return Pair(result, null) return Pair(result, null)
} } else {
else {
assert(restParameters.size == restArguments.size) { assert(restParameters.size == restArguments.size) {
"Number of type of restParameters should be equal to ${restArguments.size}, " + "Number of type of restParameters should be equal to ${restArguments.size}, " +
"but ${restArguments.size} were found for $classifierDescriptor/$nextParameterOwner" "but ${restArguments.size} were found for $classifierDescriptor/$nextParameterOwner"
@@ -805,12 +826,10 @@ class TypeResolver(
if (parameters.size > i) { if (parameters.size > i) {
val parameterDescriptor = parameters[i] val parameterDescriptor = parameters[i]
TypeUtils.makeStarProjection(parameterDescriptor) TypeUtils.makeStarProjection(parameterDescriptor)
} } else {
else {
TypeProjectionImpl(OUT_VARIANCE, ErrorUtils.createErrorType("*")) TypeProjectionImpl(OUT_VARIANCE, ErrorUtils.createErrorType("*"))
} }
} } else {
else {
val type = resolveType(c.noBareTypes(), argumentElement.typeReference!!) val type = resolveType(c.noBareTypes(), argumentElement.typeReference!!)
val kind = resolveProjectionKind(projectionKind) val kind = resolveProjectionKind(projectionKind)
if (constructor.parameters.size > i) { if (constructor.parameters.size > i) {
@@ -818,8 +837,7 @@ class TypeResolver(
if (kind != INVARIANT && parameterDescriptor.variance != INVARIANT) { if (kind != INVARIANT && parameterDescriptor.variance != INVARIANT) {
if (kind == parameterDescriptor.variance) { if (kind == parameterDescriptor.variance) {
c.trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.declarationDescriptor!!)) c.trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.declarationDescriptor!!))
} } else {
else {
c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.declarationDescriptor!!)) c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.declarationDescriptor!!))
} }
} }
@@ -87,9 +87,12 @@ class VariableTypeAndInitializerResolver(
wrappedTypeFactory.createRecursionIntolerantDeferredType( wrappedTypeFactory.createRecursionIntolerantDeferredType(
trace trace
) { ) {
PreliminaryDeclarationVisitor.createForDeclaration(variable, trace, PreliminaryDeclarationVisitor.createForDeclaration(
expressionTypingServices.languageVersionSettings) variable, trace,
val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local) expressionTypingServices.languageVersionSettings
)
val initializerType =
resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local)
transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace) transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace)
} }
@@ -112,7 +115,10 @@ class VariableTypeAndInitializerResolver(
variableDescriptor.setCompileTimeInitializer( variableDescriptor.setCompileTimeInitializer(
storageManager.createRecursionTolerantNullableLazyValue( storageManager.createRecursionTolerantNullableLazyValue(
computeInitializer@{ computeInitializer@{
if (!DescriptorUtils.shouldRecordInitializerForProperty(variableDescriptor, variableType)) return@computeInitializer null if (!DescriptorUtils.shouldRecordInitializerForProperty(
variableDescriptor,
variableType
)) return@computeInitializer null
val initializer = variable.initializer val initializer = variable.initializer
val initializerType = expressionTypingServices.safeGetType(scope, initializer!!, variableType, dataFlowInfo, trace) val initializerType = expressionTypingServices.safeGetType(scope, initializer!!, variableType, dataFlowInfo, trace)
@@ -140,7 +146,8 @@ class VariableTypeAndInitializerResolver(
) = wrappedTypeFactory.createRecursionIntolerantDeferredType(trace) { ) = wrappedTypeFactory.createRecursionIntolerantDeferredType(trace) {
val delegateExpression = property.delegateExpression!! val delegateExpression = property.delegateExpression!!
val type = delegatedPropertyResolver.resolveDelegateExpression( val type = delegatedPropertyResolver.resolveDelegateExpression(
delegateExpression, property, variableDescriptor, scopeForInitializer, trace, dataFlowInfo) delegateExpression, property, variableDescriptor, scopeForInitializer, trace, dataFlowInfo
)
val getterReturnType = delegatedPropertyResolver.getGetValueMethodReturnType( val getterReturnType = delegatedPropertyResolver.getGetValueMethodReturnType(
variableDescriptor, delegateExpression, type, trace, scopeForInitializer, dataFlowInfo variableDescriptor, delegateExpression, type, trace, scopeForInitializer, dataFlowInfo
@@ -137,8 +137,8 @@ class VarianceCheckerCore(
return noError return noError
} }
private fun KtTypeReference.checkTypePosition(trace: BindingContext, position: Variance) private fun KtTypeReference.checkTypePosition(trace: BindingContext, position: Variance) =
= createTypeBinding(trace)?.checkTypePosition(position) createTypeBinding(trace)?.checkTypePosition(position)
private fun TypeBinding<PsiElement>.checkTypePosition(position: Variance) = checkTypePosition(type, position) private fun TypeBinding<PsiElement>.checkTypePosition(position: Variance) = checkTypePosition(type, position)
@@ -147,7 +147,8 @@ class VarianceCheckerCore(
position, position,
{ typeParameterDescriptor, typeBinding, errorPosition -> { typeParameterDescriptor, typeBinding, errorPosition ->
val varianceConflictDiagnosticData = VarianceConflictDiagnosticData(containingType, typeParameterDescriptor, errorPosition) val varianceConflictDiagnosticData = VarianceConflictDiagnosticData(containingType, typeParameterDescriptor, errorPosition)
val diagnostic = if (typeBinding.isInAbbreviation) Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE else Errors.TYPE_VARIANCE_CONFLICT val diagnostic =
if (typeBinding.isInAbbreviation) Errors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE else Errors.TYPE_VARIANCE_CONFLICT
diagnosticSink.report(diagnostic.on(typeBinding.psiElement, varianceConflictDiagnosticData)) diagnosticSink.report(diagnostic.on(typeBinding.psiElement, varianceConflictDiagnosticData))
}, },
customVariance = { it.varianceWithManual() } customVariance = { it.varianceWithManual() }
@@ -30,9 +30,13 @@ import java.util.*
object CallDiagnosticToDiagnostic { object CallDiagnosticToDiagnostic {
private val diagnosticMap: MutableMap<Class<out KotlinCallDiagnostic>, KotlinCallDiagnostic.(PsiElement) -> ParametrizedDiagnostic<*>> = HashMap() private val diagnosticMap: MutableMap<Class<out KotlinCallDiagnostic>, KotlinCallDiagnostic.(PsiElement) -> ParametrizedDiagnostic<*>> =
HashMap()
private fun <E: PsiElement, C: KotlinCallDiagnostic> checkPut(klass: Class<C>, factory: C.(PsiElement) -> ParametrizedDiagnostic<E>?) { private fun <E : PsiElement, C : KotlinCallDiagnostic> checkPut(
klass: Class<C>,
factory: C.(PsiElement) -> ParametrizedDiagnostic<E>?
) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
diagnosticMap.put(klass, factory as KotlinCallDiagnostic.(PsiElement) -> ParametrizedDiagnostic<*>) diagnosticMap.put(klass, factory as KotlinCallDiagnostic.(PsiElement) -> ParametrizedDiagnostic<*>)
} }
@@ -43,14 +47,19 @@ object CallDiagnosticToDiagnostic {
} }
} }
private inline fun <reified E: PsiElement, A, C: KotlinCallDiagnostic> put(factory1: DiagnosticFactory1<E, A>, klass: Class<C>, crossinline getA: C.() -> A) { private inline fun <reified E : PsiElement, A, C : KotlinCallDiagnostic> put(
factory1: DiagnosticFactory1<E, A>,
klass: Class<C>,
crossinline getA: C.() -> A
) {
checkPut<E, C>(klass) { checkPut<E, C>(klass) {
(it as? E)?.let { factory1.on(it, getA()) } (it as? E)?.let { factory1.on(it, getA()) }
} }
} }
private inline fun <reified E : PsiElement, A, B, C : KotlinCallDiagnostic> put( private inline fun <reified E : PsiElement, A, B, C : KotlinCallDiagnostic> put(
factory2: DiagnosticFactory2<E, A, B>, klass: Class<C>, crossinline getA: C.() -> A, crossinline getB: C.() -> B) { factory2: DiagnosticFactory2<E, A, B>, klass: Class<C>, crossinline getA: C.() -> A, crossinline getB: C.() -> B
) {
checkPut<E, C>(klass) { checkPut<E, C>(klass) {
(it as? E)?.let { factory2.on(it, getA(), getB()) } (it as? E)?.let { factory2.on(it, getA(), getB()) }
} }
@@ -58,7 +67,12 @@ object CallDiagnosticToDiagnostic {
init { init {
// put(Errors.UNSAFE_CALL, UnsafeCallDiagnostic::class.java, UnsafeCallDiagnostic::receiverType) // put(Errors.UNSAFE_CALL, UnsafeCallDiagnostic::class.java, UnsafeCallDiagnostic::receiverType)
put(Errors.TYPE_MISMATCH, TypeMismatchDiagnostic::class.java, TypeMismatchDiagnostic::expectedType, TypeMismatchDiagnostic::actualType) put(
Errors.TYPE_MISMATCH,
TypeMismatchDiagnostic::class.java,
TypeMismatchDiagnostic::expectedType,
TypeMismatchDiagnostic::actualType
)
} }
@@ -36,6 +36,7 @@ interface AdditionalTypeChecker {
receiverArgument: ReceiverValue, receiverArgument: ReceiverValue,
safeAccess: Boolean, safeAccess: Boolean,
c: CallResolutionContext<*> c: CallResolutionContext<*>
) { } ) {
}
} }
@@ -51,8 +51,7 @@ class AssigningNamedArgumentToVarargChecker : CallChecker {
if (isParameterOfAnnotation(parameterDescriptor)) { if (isParameterOfAnnotation(parameterDescriptor)) {
checkAssignmentOfSingleElementInAnnotation(argument, argumentExpression, context) checkAssignmentOfSingleElementInAnnotation(argument, argumentExpression, context)
} } else {
else {
checkAssignmentOfSingleElementInFunction(argument, argumentExpression, context, parameterDescriptor) checkAssignmentOfSingleElementInFunction(argument, argumentExpression, context, parameterDescriptor)
} }
} }
@@ -66,8 +65,7 @@ class AssigningNamedArgumentToVarargChecker : CallChecker {
if (argument.hasSpread()) { if (argument.hasSpread()) {
context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression)) context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression))
} }
} } else {
else {
context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression)) context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_ANNOTATION.on(argumentExpression))
} }
} }
@@ -79,7 +77,12 @@ class AssigningNamedArgumentToVarargChecker : CallChecker {
parameterDescriptor: ValueParameterDescriptor parameterDescriptor: ValueParameterDescriptor
) { ) {
if (!argument.hasSpread()) { if (!argument.hasSpread()) {
context.trace.report(Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION.on(argumentExpression, parameterDescriptor.type)) context.trace.report(
Errors.ASSIGNING_SINGLE_ELEMENT_TO_VARARG_IN_NAMED_FORM_FUNCTION.on(
argumentExpression,
parameterDescriptor.type
)
)
} }
} }
@@ -39,8 +39,7 @@ object ConstructorHeaderCallChecker : CallChecker {
val labelReferenceClass = val labelReferenceClass =
if (callElement is KtInstanceExpressionWithLabel) { if (callElement is KtInstanceExpressionWithLabel) {
context.trace.get(BindingContext.REFERENCE_TARGET, callElement.instanceReference) as? ClassDescriptor context.trace.get(BindingContext.REFERENCE_TARGET, callElement.instanceReference) as? ClassDescriptor
} } else null
else null
if (dispatchReceiverClass == null && extensionReceiverClass == null && labelReferenceClass == null) return if (dispatchReceiverClass == null && extensionReceiverClass == null && labelReferenceClass == null) return
@@ -74,7 +74,8 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
if (inlinableParameters.contains(targetDescriptor)) { if (inlinableParameters.contains(targetDescriptor)) {
when { when {
!checkNotInDefaultParameter(context, targetDescriptor, expression) -> { /*error*/ } !checkNotInDefaultParameter(context, targetDescriptor, expression) -> { /*error*/
}
!isInsideCall(expression) -> context.trace.report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor)) !isInsideCall(expression) -> context.trace.report(USAGE_IS_NOT_INLINABLE.on(expression, expression, descriptor))
} }
} }
@@ -95,7 +96,13 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
!supportDefaultValueInline || expression.getParentOfType<KtParameter>(true)?.let { !supportDefaultValueInline || expression.getParentOfType<KtParameter>(true)?.let {
val allow = it !in inlinableKtParameters val allow = it !in inlinableKtParameters
if (!allow) { if (!allow) {
context.trace.report(NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE.on(expression, expression, descriptor)) context.trace.report(
NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE.on(
expression,
expression,
descriptor
)
)
} }
allow allow
} ?: true } ?: true
@@ -136,13 +143,13 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
if (argumentCallee != null && inlinableParameters.contains(argumentCallee)) { if (argumentCallee != null && inlinableParameters.contains(argumentCallee)) {
when { when {
!checkNotInDefaultParameter(context, argumentCallee, argumentExpression) -> { /*error*/ } !checkNotInDefaultParameter(context, argumentCallee, argumentExpression) -> { /*error*/
}
InlineUtil.isInline(targetDescriptor) && InlineUtil.isInlineParameter(targetParameterDescriptor) -> InlineUtil.isInline(targetDescriptor) && InlineUtil.isInlineParameter(targetParameterDescriptor) ->
if (allowsNonLocalReturns(argumentCallee) && !allowsNonLocalReturns(targetParameterDescriptor)) { if (allowsNonLocalReturns(argumentCallee) && !allowsNonLocalReturns(targetParameterDescriptor)) {
context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression)) context.trace.report(NON_LOCAL_RETURN_NOT_ALLOWED.on(argumentExpression, argumentExpression))
} } else {
else {
checkNonLocalReturn(context, argumentCallee, argumentExpression) checkNonLocalReturn(context, argumentCallee, argumentExpression)
} }
@@ -209,8 +216,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
val inlinableCall = isInvokeOrInlineExtension(callDescriptor) val inlinableCall = isInvokeOrInlineExtension(callDescriptor)
if (!inlinableCall) { if (!inlinableCall) {
context.trace.report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor)) context.trace.report(USAGE_IS_NOT_INLINABLE.on(receiverExpression, receiverExpression, descriptor))
} } else {
else {
checkNonLocalReturn(context, lambdaDescriptor, receiverExpression) checkNonLocalReturn(context, lambdaDescriptor, receiverExpression)
} }
} }
@@ -254,8 +260,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
!isCalledFunPublicOrPublishedApi && !isCalledFunPublicOrPublishedApi &&
calledDescriptor.visibility !== Visibilities.LOCAL) { calledDescriptor.visibility !== Visibilities.LOCAL) {
context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor)) context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, calledDescriptor, descriptor))
} } else {
else {
checkPrivateClassMemberAccess(calledDescriptor, expression, context) checkPrivateClassMemberAccess(calledDescriptor, expression, context)
} }
@@ -46,8 +46,7 @@ object LateinitIntrinsicApplicabilityChecker : CallChecker {
val expression = (resolvedCall.extensionReceiver as? ExpressionReceiver)?.expression?.let(KtPsiUtil::safeDeparenthesize) val expression = (resolvedCall.extensionReceiver as? ExpressionReceiver)?.expression?.let(KtPsiUtil::safeDeparenthesize)
if (expression !is KtCallableReferenceExpression) { if (expression !is KtCallableReferenceExpression) {
context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL.on(reportOn)) context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL.on(reportOn))
} } else {
else {
val propertyReferenceResolvedCall = expression.callableReference.getResolvedCall(context.trace.bindingContext) ?: return val propertyReferenceResolvedCall = expression.callableReference.getResolvedCall(context.trace.bindingContext) ?: return
val referencedProperty = propertyReferenceResolvedCall.resultingDescriptor val referencedProperty = propertyReferenceResolvedCall.resultingDescriptor
if (referencedProperty !is PropertyDescriptor) { if (referencedProperty !is PropertyDescriptor) {
@@ -56,11 +55,9 @@ object LateinitIntrinsicApplicabilityChecker : CallChecker {
if (!referencedProperty.isLateInit) { if (!referencedProperty.isLateInit) {
context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT.on(reportOn)) context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT.on(reportOn))
} } else if (!isBackingFieldAccessible(referencedProperty, context)) {
else if (!isBackingFieldAccessible(referencedProperty, context)) {
context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY.on(reportOn, referencedProperty)) context.trace.report(LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY.on(reportOn, referencedProperty))
} } else if ((context.scope.ownerDescriptor as? FunctionDescriptor)?.isInline == true) {
else if ((context.scope.ownerDescriptor as? FunctionDescriptor)?.isInline == true) {
context.trace.report(LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION.on(reportOn)) context.trace.report(LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION.on(reportOn))
} }
} }
@@ -46,14 +46,17 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
bounds.add(bound) bounds.add(bound)
} }
private fun filterBounds(bounds: Collection<Bound>, kind: BoundKind, errorValues: MutableCollection<KotlinType>? = null): Set<KotlinType> { private fun filterBounds(
bounds: Collection<Bound>,
kind: BoundKind,
errorValues: MutableCollection<KotlinType>? = null
): Set<KotlinType> {
val result = LinkedHashSet<KotlinType>() val result = LinkedHashSet<KotlinType>()
for (bound in bounds) { for (bound in bounds) {
if (bound.kind == kind) { if (bound.kind == kind) {
if (!ErrorUtils.containsErrorType(bound.constrainingType)) { if (!ErrorUtils.containsErrorType(bound.constrainingType)) {
result.add(bound.constrainingType) result.add(bound.constrainingType)
} } else {
else {
errorValues?.add(bound.constrainingType) errorValues?.add(bound.constrainingType)
} }
} }
@@ -116,7 +119,8 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
values.addIfNotNull(superTypeOfNumberLowerBounds) values.addIfNotNull(superTypeOfNumberLowerBounds)
if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) { if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) {
val superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(listOf(superTypeOfLowerBounds, superTypeOfNumberLowerBounds)) val superTypeOfAllLowerBounds =
CommonSupertypes.commonSupertypeForNonDenotableTypes(listOf(superTypeOfLowerBounds, superTypeOfNumberLowerBounds))
if (tryPossibleAnswer(bounds, superTypeOfAllLowerBounds)) { if (tryPossibleAnswer(bounds, superTypeOfAllLowerBounds)) {
return setOf(superTypeOfAllLowerBounds!!) return setOf(superTypeOfAllLowerBounds!!)
} }
@@ -141,7 +145,8 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
if (!typeVariable.hasOnlyInputTypesAnnotation()) return true if (!typeVariable.hasOnlyInputTypesAnnotation()) return true
// Only type mentioned in bounds might be the result // Only type mentioned in bounds might be the result
val typesInBoundsSet = bounds.filter { it.isProper && it.constrainingType.constructor.isDenotable }.map { it.constrainingType }.toSet() val typesInBoundsSet =
bounds.filter { it.isProper && it.constrainingType.constructor.isDenotable }.map { it.constrainingType }.toSet()
// Flexible types are equal to inflexible // Flexible types are equal to inflexible
if (typesInBoundsSet.any { KotlinTypeChecker.DEFAULT.equalTypes(it, possibleAnswer) }) return true if (typesInBoundsSet.any { KotlinTypeChecker.DEFAULT.equalTypes(it, possibleAnswer) }) return true
@@ -181,8 +186,7 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
private fun commonSupertypeForNumberTypes(numberLowerBounds: Collection<KotlinType>): KotlinType? { private fun commonSupertypeForNumberTypes(numberLowerBounds: Collection<KotlinType>): KotlinType? {
if (numberLowerBounds.isEmpty()) return null if (numberLowerBounds.isEmpty()) return null
val intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds) val intersectionOfSupertypes = getIntersectionOfSupertypes(numberLowerBounds)
return TypeUtils.getDefaultPrimitiveNumberType(intersectionOfSupertypes) ?: return TypeUtils.getDefaultPrimitiveNumberType(intersectionOfSupertypes) ?: CommonSupertypes.commonSupertype(numberLowerBounds)
CommonSupertypes.commonSupertype(numberLowerBounds)
} }
private fun getIntersectionOfSupertypes(types: Collection<KotlinType>): Set<KotlinType> { private fun getIntersectionOfSupertypes(types: Collection<KotlinType>): Set<KotlinType> {
@@ -191,8 +195,7 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
val supertypes = type.constructor.supertypes val supertypes = type.constructor.supertypes
if (upperBounds.isEmpty()) { if (upperBounds.isEmpty()) {
upperBounds.addAll(supertypes) upperBounds.addAll(supertypes)
} } else {
else {
upperBounds.retainAll(supertypes) upperBounds.retainAll(supertypes)
} }
} }
@@ -99,8 +99,8 @@ fun ResolvedCall<*>.makeNullableTypeIfSafeReceiver(type: KotlinType?, context: C
fun ResolvedCall<*>.hasBothReceivers() = dispatchReceiver != null && extensionReceiver != null fun ResolvedCall<*>.hasBothReceivers() = dispatchReceiver != null && extensionReceiver != null
fun ResolvedCall<*>.getDispatchReceiverWithSmartCast(): ReceiverValue? fun ResolvedCall<*>.getDispatchReceiverWithSmartCast(): ReceiverValue? =
= getReceiverValueWithSmartCast(dispatchReceiver, smartCastDispatchReceiverType) getReceiverValueWithSmartCast(dispatchReceiver, smartCastDispatchReceiverType)
fun KtCallElement.getArgumentByParameterIndex(index: Int, context: BindingContext): List<ValueArgument> { fun KtCallElement.getArgumentByParameterIndex(index: Int, context: BindingContext): List<ValueArgument> {
val resolvedCall = getResolvedCall(context) ?: return emptyList() val resolvedCall = getResolvedCall(context) ?: return emptyList()
@@ -38,8 +38,7 @@ fun <RC : ResolvedCall<*>> RC.createFlatSignature(): FlatSignature<RC> {
for ((valueParameter, resolvedValueArgument) in valueArguments.entries) { for ((valueParameter, resolvedValueArgument) in valueArguments.entries) {
if (resolvedValueArgument is DefaultValueArgument) { if (resolvedValueArgument is DefaultValueArgument) {
numDefaults++ numDefaults++
} } else {
else {
val originalValueParameter = originalValueParameters[valueParameter.index] val originalValueParameter = originalValueParameters[valueParameter.index]
val parameterType = originalValueParameter.argumentValueType val parameterType = originalValueParameter.argumentValueType
for (valueArgument in resolvedValueArgument.arguments) { for (valueArgument in resolvedValueArgument.arguments) {
@@ -68,7 +68,6 @@ class ManyCandidates<D : CallableDescriptor>(
} }
class AllCandidates<D : CallableDescriptor>(private val allCandidates: Collection<ResolvedCall<D>>) : NameNotFoundResolutionResult<D>() { class AllCandidates<D : CallableDescriptor>(private val allCandidates: Collection<ResolvedCall<D>>) : NameNotFoundResolutionResult<D>() {
override fun getAllCandidates() = allCandidates override fun getAllCandidates() = allCandidates
} }
@@ -92,9 +92,11 @@ object DataFlowValueFactory {
// //
// But there are some problem with types built on type parameters, e.g. // But there are some problem with types built on type parameters, e.g.
// fun <T : Any?> foo(x: T) = x!!.hashCode() // there no way in type system to denote that `x!!` is not nullable // fun <T : Any?> foo(x: T) = x!!.hashCode() // there no way in type system to denote that `x!!` is not nullable
return DataFlowValue(ExpressionIdentifierInfo(expression), return DataFlowValue(
ExpressionIdentifierInfo(expression),
type, type,
Nullability.NOT_NULL) Nullability.NOT_NULL
)
} }
if (isComplexExpression(expression)) { if (isComplexExpression(expression)) {
@@ -121,10 +123,12 @@ object DataFlowValueFactory {
containingDeclarationOrModule: DeclarationDescriptor containingDeclarationOrModule: DeclarationDescriptor
) = when (receiverValue) { ) = when (receiverValue) {
is TransientReceiver, is ImplicitReceiver -> createDataFlowValueForStableReceiver(receiverValue) is TransientReceiver, is ImplicitReceiver -> createDataFlowValueForStableReceiver(receiverValue)
is ExpressionReceiver -> createDataFlowValue(receiverValue.expression, is ExpressionReceiver -> createDataFlowValue(
receiverValue.expression,
receiverValue.getType(), receiverValue.getType(),
bindingContext, bindingContext,
containingDeclarationOrModule) containingDeclarationOrModule
)
else -> throw UnsupportedOperationException("Unsupported receiver value: " + receiverValue::class.java.name) else -> throw UnsupportedOperationException("Unsupported receiver value: " + receiverValue::class.java.name)
} }
@@ -134,11 +138,14 @@ object DataFlowValueFactory {
variableDescriptor: VariableDescriptor, variableDescriptor: VariableDescriptor,
bindingContext: BindingContext, bindingContext: BindingContext,
usageContainingModule: ModuleDescriptor? usageContainingModule: ModuleDescriptor?
) = DataFlowValue(IdentifierInfo.Variable(variableDescriptor, ) = DataFlowValue(
variableKind(variableDescriptor, usageContainingModule, IdentifierInfo.Variable(
bindingContext, property), variableDescriptor,
bindingContext[BOUND_INITIALIZER_VALUE, variableDescriptor]), variableKind(variableDescriptor, usageContainingModule, bindingContext, property),
variableDescriptor.type) bindingContext[BOUND_INITIALIZER_VALUE, variableDescriptor]
),
variableDescriptor.type
)
private fun createDataFlowValueForComplexExpression( private fun createDataFlowValueForComplexExpression(
expression: KtExpression, expression: KtExpression,
@@ -166,8 +173,7 @@ object DataFlowValueFactory {
private fun postfix(argumentInfo: IdentifierInfo, op: KtToken) = private fun postfix(argumentInfo: IdentifierInfo, op: KtToken) =
if (argumentInfo == IdentifierInfo.NO) { if (argumentInfo == IdentifierInfo.NO) {
IdentifierInfo.NO IdentifierInfo.NO
} } else {
else {
PostfixIdentifierInfo(argumentInfo, op) PostfixIdentifierInfo(argumentInfo, op)
} }
@@ -189,8 +195,10 @@ object DataFlowValueFactory {
val receiverInfo = getIdForStableIdentifier(receiverExpression, bindingContext, containingDeclarationOrModule) val receiverInfo = getIdForStableIdentifier(receiverExpression, bindingContext, containingDeclarationOrModule)
val selectorInfo = getIdForStableIdentifier(selectorExpression, bindingContext, containingDeclarationOrModule) val selectorInfo = getIdForStableIdentifier(selectorExpression, bindingContext, containingDeclarationOrModule)
IdentifierInfo.qualified(receiverInfo, bindingContext.getType(receiverExpression), IdentifierInfo.qualified(
selectorInfo, expression.operationSign === KtTokens.SAFE_ACCESS) receiverInfo, bindingContext.getType(receiverExpression),
selectorInfo, expression.operationSign === KtTokens.SAFE_ACCESS
)
} }
is KtBinaryExpressionWithTypeRHS -> { is KtBinaryExpressionWithTypeRHS -> {
val subjectExpression = expression.left val subjectExpression = expression.left
@@ -198,11 +206,12 @@ object DataFlowValueFactory {
val operationToken = expression.operationReference.getReferencedNameElementType() val operationToken = expression.operationReference.getReferencedNameElementType()
if (operationToken == KtTokens.IS_KEYWORD || operationToken == KtTokens.AS_KEYWORD) { if (operationToken == KtTokens.IS_KEYWORD || operationToken == KtTokens.AS_KEYWORD) {
IdentifierInfo.NO IdentifierInfo.NO
} } else {
else { IdentifierInfo.SafeCast(
IdentifierInfo.SafeCast(getIdForStableIdentifier(subjectExpression, bindingContext, containingDeclarationOrModule), getIdForStableIdentifier(subjectExpression, bindingContext, containingDeclarationOrModule),
bindingContext.getType(subjectExpression), bindingContext.getType(subjectExpression),
bindingContext[BindingContext.TYPE, targetTypeReference]) bindingContext[BindingContext.TYPE, targetTypeReference]
)
} }
} }
is KtSimpleNameExpression -> is KtSimpleNameExpression ->
@@ -214,10 +223,11 @@ object DataFlowValueFactory {
is KtPostfixExpression -> { is KtPostfixExpression -> {
val operationType = expression.operationReference.getReferencedNameElementType() val operationType = expression.operationReference.getReferencedNameElementType()
if (operationType === KtTokens.PLUSPLUS || operationType === KtTokens.MINUSMINUS) { if (operationType === KtTokens.PLUSPLUS || operationType === KtTokens.MINUSMINUS) {
postfix(getIdForStableIdentifier(expression.baseExpression, bindingContext, containingDeclarationOrModule), postfix(
operationType) getIdForStableIdentifier(expression.baseExpression, bindingContext, containingDeclarationOrModule),
} operationType
else { )
} else {
IdentifierInfo.NO IdentifierInfo.NO
} }
} }
@@ -240,24 +250,25 @@ object DataFlowValueFactory {
// for now it fails for resolving 'invoke' convention, return it after 'invoke' algorithm changes // for now it fails for resolving 'invoke' convention, return it after 'invoke' algorithm changes
// assert resolvedCall != null : "Cannot create right identifier info if the resolved call is not known yet for // assert resolvedCall != null : "Cannot create right identifier info if the resolved call is not known yet for
val usageModuleDescriptor = DescriptorUtils.getContainingModuleOrNull(containingDeclarationOrModule) val usageModuleDescriptor = DescriptorUtils.getContainingModuleOrNull(containingDeclarationOrModule)
val selectorInfo = IdentifierInfo.Variable(declarationDescriptor, val selectorInfo = IdentifierInfo.Variable(
variableKind(declarationDescriptor, usageModuleDescriptor, declarationDescriptor,
bindingContext, simpleNameExpression), variableKind(declarationDescriptor, usageModuleDescriptor, bindingContext, simpleNameExpression),
bindingContext[BOUND_INITIALIZER_VALUE, declarationDescriptor]) bindingContext[BOUND_INITIALIZER_VALUE, declarationDescriptor]
)
val implicitReceiver = resolvedCall?.dispatchReceiver val implicitReceiver = resolvedCall?.dispatchReceiver
if (implicitReceiver == null) { if (implicitReceiver == null) {
selectorInfo selectorInfo
} } else {
else {
val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression) val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression)
if (receiverInfo == null) { if (receiverInfo == null) {
selectorInfo selectorInfo
} } else {
else { IdentifierInfo.qualified(
IdentifierInfo.qualified(receiverInfo, implicitReceiver.type, receiverInfo, implicitReceiver.type,
selectorInfo, resolvedCall.call.isSafeCall()) selectorInfo, resolvedCall.call.isSafeCall()
)
} }
} }
} }
@@ -329,7 +340,8 @@ object DataFlowValueFactory {
// writer which is the same with declaration site does not count // writer which is the same with declaration site does not count
writers.mapNotNull { it.declaration }.forEach { writerDeclaration -> writers.mapNotNull { it.declaration }.forEach { writerDeclaration ->
val writerDescriptor = ControlFlowInformationProvider.getDeclarationDescriptorIncludingConstructors( val writerDescriptor = ControlFlowInformationProvider.getDeclarationDescriptorIncludingConstructors(
bindingContext, writerDeclaration) bindingContext, writerDeclaration
)
// Access is after some writerDeclaration // Access is after some writerDeclaration
if (variableContainingDeclaration != writerDescriptor && !accessElement.before(writerDeclaration)) { if (variableContainingDeclaration != writerDescriptor && !accessElement.before(writerDeclaration)) {
return false return false
@@ -383,8 +395,7 @@ object DataFlowValueFactory {
hasNoWritersInClosures(variableContainingDeclaration, writers, bindingContext) && hasNoWritersInClosures(variableContainingDeclaration, writers, bindingContext) &&
isAccessedInsideClosureAfterAllWriters(writers, accessElement)) { isAccessedInsideClosureAfterAllWriters(writers, accessElement)) {
STABLE_VARIABLE STABLE_VARIABLE
} } else {
else {
CAPTURED_VARIABLE CAPTURED_VARIABLE
} }
} }
@@ -44,7 +44,8 @@ class SmartCastManager {
languageVersionSettings: LanguageVersionSettings languageVersionSettings: LanguageVersionSettings
): List<KotlinType> { ): List<KotlinType> {
val variants = getSmartCastVariantsExcludingReceiver( val variants = getSmartCastVariantsExcludingReceiver(
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings) bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings
)
val result = ArrayList<KotlinType>(variants.size + 1) val result = ArrayList<KotlinType>(variants.size + 1)
result.add(receiverToCast.type) result.add(receiverToCast.type)
result.addAll(variants) result.addAll(variants)
@@ -58,11 +59,13 @@ class SmartCastManager {
context: ResolutionContext<*>, context: ResolutionContext<*>,
receiverToCast: ReceiverValue receiverToCast: ReceiverValue
): Collection<KotlinType> { ): Collection<KotlinType> {
return getSmartCastVariantsExcludingReceiver(context.trace.bindingContext, return getSmartCastVariantsExcludingReceiver(
context.trace.bindingContext,
context.scope.ownerDescriptor, context.scope.ownerDescriptor,
context.dataFlowInfo, context.dataFlowInfo,
receiverToCast, receiverToCast,
context.languageVersionSettings) context.languageVersionSettings
)
} }
/** /**
@@ -141,8 +144,7 @@ class SmartCastManager {
//Why the expression type is rewritten for receivers and is not rewritten for arguments? Is it necessary? //Why the expression type is rewritten for receivers and is not rewritten for arguments? Is it necessary?
trace.recordType(expression, type) trace.recordType(expression, type)
} }
} } else {
else {
trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.text, dataFlowValue.kind.description)) trace.report(SMARTCAST_IMPOSSIBLE.on(expression, type, expression.text, dataFlowValue.kind.description))
} }
} }
@@ -169,11 +171,12 @@ class SmartCastManager {
): SmartCastResult? { ): SmartCastResult? {
val calleeExpression = call?.calleeExpression val calleeExpression = call?.calleeExpression
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) { for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) {
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType) && (additionalPredicate == null || additionalPredicate(possibleType))) { if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType) &&
(additionalPredicate == null || additionalPredicate(possibleType))
) {
if (expression != null) { if (expression != null) {
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType) recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType)
} } else if (calleeExpression != null && dataFlowValue.isStable) {
else if (calleeExpression != null && dataFlowValue.isStable) {
val receiver = (dataFlowValue.identifierInfo as? IdentifierInfo.Receiver)?.value val receiver = (dataFlowValue.identifierInfo as? IdentifierInfo.Receiver)?.value
if (receiver is ImplicitReceiver) { if (receiver is ImplicitReceiver) {
val oldSmartCasts = c.trace[IMPLICIT_RECEIVER_SMARTCAST, calleeExpression] val oldSmartCasts = c.trace[IMPLICIT_RECEIVER_SMARTCAST, calleeExpression]
@@ -181,8 +184,10 @@ class SmartCastManager {
if (oldSmartCasts != null) { if (oldSmartCasts != null) {
val oldType = oldSmartCasts.receiverTypes[receiver] val oldType = oldSmartCasts.receiverTypes[receiver]
if (oldType != null && oldType != possibleType) { if (oldType != null && oldType != possibleType) {
throw AssertionError("Rewriting key $receiver for implicit smart cast on ${calleeExpression.text}: " + throw AssertionError(
"was $oldType, now $possibleType") "Rewriting key $receiver for implicit smart cast on ${calleeExpression.text}: " +
"was $oldType, now $possibleType"
)
} }
} }
c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression, c.trace.record(IMPLICIT_RECEIVER_SMARTCAST, calleeExpression,
@@ -211,7 +216,9 @@ class SmartCastManager {
val immanentlyNotNull = !dataFlowValue.immanentNullability.canBeNull() val immanentlyNotNull = !dataFlowValue.immanentNullability.canBeNull()
val nullableExpectedType = TypeUtils.makeNullable(expectedType) val nullableExpectedType = TypeUtils.makeNullable(expectedType)
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(dataFlowValue.type, nullableExpectedType) && (additionalPredicate == null || additionalPredicate(dataFlowValue.type))) { if (ArgumentTypeResolver.isSubtypeOfForArgumentType(dataFlowValue.type, nullableExpectedType) &&
(additionalPredicate == null || additionalPredicate(dataFlowValue.type))
) {
if (!immanentlyNotNull && expression != null) { if (!immanentlyNotNull && expression != null) {
recordCastOrError(expression, dataFlowValue.type, c.trace, dataFlowValue, call, recordExpressionType) recordCastOrError(expression, dataFlowValue.type, c.trace, dataFlowValue, call, recordExpressionType)
} }
@@ -83,9 +83,7 @@ class TracingStrategyForImplicitConstructorDelegationCall(
} }
private fun reportError(trace: BindingTrace) { private fun reportError(trace: BindingTrace) {
if (!trace.bindingContext.diagnostics.forElement(delegationCall). if (!trace.bindingContext.diagnostics.forElement(delegationCall).any { it.factory == Errors.EXPLICIT_DELEGATION_CALL_REQUIRED }) {
any { it.factory == Errors.EXPLICIT_DELEGATION_CALL_REQUIRED }
) {
trace.report(Errors.EXPLICIT_DELEGATION_CALL_REQUIRED.on(delegationCall)) trace.report(Errors.EXPLICIT_DELEGATION_CALL_REQUIRED.on(delegationCall))
} }
} }
@@ -118,7 +116,12 @@ class TracingStrategyForImplicitConstructorDelegationCall(
unexpectedError("missingReceiver") unexpectedError("missingReceiver")
} }
override fun wrongReceiverType(trace: BindingTrace, receiverParameter: ReceiverParameterDescriptor, receiverArgument: ReceiverValue, c: ResolutionContext<*>) { override fun wrongReceiverType(
trace: BindingTrace,
receiverParameter: ReceiverParameterDescriptor,
receiverArgument: ReceiverValue,
c: ResolutionContext<*>
) {
unexpectedError("wrongReceiverType") unexpectedError("wrongReceiverType")
} }
@@ -102,9 +102,11 @@ class KotlinToResolvedCallTransformer(
} }
CallResolutionResult.Type.ERROR, CallResolutionResult.Type.COMPLETED -> { CallResolutionResult.Type.ERROR, CallResolutionResult.Type.COMPLETED -> {
val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor() val resultSubstitutor = baseResolvedCall.constraintSystem.buildResultingSubstitutor()
val ktPrimitiveCompleter = ResolvedAtomCompleter(resultSubstitutor, context.trace, context, this, val ktPrimitiveCompleter = ResolvedAtomCompleter(
resultSubstitutor, context.trace, context, this,
expressionTypingServices, argumentTypeResolver, doubleColonExpressionResolver, expressionTypingServices, argumentTypeResolver, doubleColonExpressionResolver,
languageFeatureSettings, deprecationResolver) languageFeatureSettings, deprecationResolver
)
for (subKtPrimitive in candidate.subResolvedAtoms) { for (subKtPrimitive in candidate.subResolvedAtoms) {
ktPrimitiveCompleter.completeAll(subKtPrimitive) ktPrimitiveCompleter.completeAll(subKtPrimitive)
@@ -143,8 +145,7 @@ class KotlinToResolvedCallTransformer(
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics), createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics),
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics) createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
) as ResolvedCall<D> ) as ResolvedCall<D>
} } else {
else {
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics) createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
} }
} }
@@ -156,8 +157,8 @@ class KotlinToResolvedCallTransformer(
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>
): NewResolvedCallImpl<D> { ): NewResolvedCallImpl<D> {
if (trace != null) { if (trace != null) {
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext)?. val storedResolvedCall =
safeAs<NewResolvedCallImpl<D>>() completedSimpleAtom.atom.psiKotlinCall.psiCall.getResolvedCall(trace.bindingContext)?.safeAs<NewResolvedCallImpl<D>>()
if (storedResolvedCall != null) { if (storedResolvedCall != null) {
storedResolvedCall.setResultingSubstitutor(resultSubstitutor) storedResolvedCall.setResultingSubstitutor(resultSubstitutor)
storedResolvedCall.updateDiagnostics(diagnostics) storedResolvedCall.updateDiagnostics(diagnostics)
@@ -197,7 +198,8 @@ class KotlinToResolvedCallTransformer(
val (expectedType, callPosition) = when (argumentMapping) { val (expectedType, callPosition) = when (argumentMapping) {
is ArgumentMatch -> Pair( is ArgumentMatch -> Pair(
getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context), getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context),
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument)) CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument)
)
else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown) else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown)
} }
val newContext = val newContext =
@@ -350,7 +352,8 @@ class KotlinToResolvedCallTransformer(
) { ) {
val trackingTrace = TrackingBindingTrace(trace) val trackingTrace = TrackingBindingTrace(trace)
val newContext = context.replaceBindingTrace(trackingTrace) val newContext = context.replaceBindingTrace(trackingTrace)
val diagnosticReporter = DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall) val diagnosticReporter =
DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall)
val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder() val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder()
additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics) additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics)
@@ -362,7 +365,8 @@ class KotlinToResolvedCallTransformer(
val dontRecordToTraceAsIs = diagnostic is ResolutionDiagnostic && diagnostic !is VisibilityError val dontRecordToTraceAsIs = diagnostic is ResolutionDiagnostic && diagnostic !is VisibilityError
val shouldReportMissingDiagnostic = !trackingTrace.reported && !dontRecordToTraceAsIs val shouldReportMissingDiagnostic = !trackingTrace.reported && !dontRecordToTraceAsIs
if (shouldReportMissingDiagnostic && REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC) { if (shouldReportMissingDiagnostic && REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC) {
val factory = if (diagnostic.candidateApplicability.isSuccess) Errors.NEW_INFERENCE_DIAGNOSTIC else Errors.NEW_INFERENCE_ERROR val factory =
if (diagnostic.candidateApplicability.isSuccess) Errors.NEW_INFERENCE_DIAGNOSTIC else Errors.NEW_INFERENCE_ERROR
trace.report(factory.on(diagnosticReporter.psiKotlinCall.psiCall.callElement, "Missing diagnostic: $diagnostic")) trace.report(factory.on(diagnosticReporter.psiKotlinCall.psiCall.callElement, "Missing diagnostic: $diagnostic"))
} }
} }
@@ -554,7 +558,8 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
// this code is very suspicious. Now it is very useful for BE, because they cannot do nothing with captured types, // this code is very suspicious. Now it is very useful for BE, because they cannot do nothing with captured types,
// but it seems like temporary solution. // but it seems like temporary solution.
candidateDescriptor.substitute(resolvedCallAtom.substitutor).substituteAndApproximateCapturedTypes( candidateDescriptor.substitute(resolvedCallAtom.substitutor).substituteAndApproximateCapturedTypes(
substitutor ?: FreshVariableNewTypeSubstitutor.Empty) substitutor ?: FreshVariableNewTypeSubstitutor.Empty
)
else -> else ->
candidateDescriptor candidateDescriptor
} }
@@ -51,14 +51,16 @@ abstract class PSIKotlinCallArgument : KotlinCallArgument {
abstract class SimplePSIKotlinCallArgument : PSIKotlinCallArgument(), SimpleKotlinCallArgument abstract class SimplePSIKotlinCallArgument : PSIKotlinCallArgument(), SimpleKotlinCallArgument
val KotlinCallArgument.psiCallArgument: PSIKotlinCallArgument get() { val KotlinCallArgument.psiCallArgument: PSIKotlinCallArgument
get() {
assert(this is PSIKotlinCallArgument) { assert(this is PSIKotlinCallArgument) {
"Incorrect KotlinCallArgument: $this. Java class: ${javaClass.canonicalName}" "Incorrect KotlinCallArgument: $this. Java class: ${javaClass.canonicalName}"
} }
return this as PSIKotlinCallArgument return this as PSIKotlinCallArgument
} }
val KotlinCallArgument.psiExpression: KtExpression? get() { val KotlinCallArgument.psiExpression: KtExpression?
get() {
return when (this) { return when (this) {
is ReceiverExpressionKotlinCallArgument -> receiver.receiverValue.safeAs<ExpressionReceiver>()?.expression is ReceiverExpressionKotlinCallArgument -> receiver.receiverValue.safeAs<ExpressionReceiver>()?.expression
is QualifierReceiverKotlinCallArgument -> receiver.safeAs<Qualifier>()?.expression is QualifierReceiverKotlinCallArgument -> receiver.safeAs<Qualifier>()?.expression
@@ -204,10 +206,12 @@ internal fun createSimplePSICallArgument(
contextForArgument: BasicCallResolutionContext, contextForArgument: BasicCallResolutionContext,
valueArgument: ValueArgument, valueArgument: ValueArgument,
typeInfoForArgument: KotlinTypeInfo typeInfoForArgument: KotlinTypeInfo
) = createSimplePSICallArgument(contextForArgument.trace.bindingContext, contextForArgument.statementFilter, ) = createSimplePSICallArgument(
contextForArgument.trace.bindingContext, contextForArgument.statementFilter,
contextForArgument.scope.ownerDescriptor, valueArgument, contextForArgument.scope.ownerDescriptor, valueArgument,
contextForArgument.dataFlowInfo, typeInfoForArgument, contextForArgument.dataFlowInfo, typeInfoForArgument,
contextForArgument.languageVersionSettings) contextForArgument.languageVersionSettings
)
internal fun createSimplePSICallArgument( internal fun createSimplePSICallArgument(
bindingContext: BindingContext, bindingContext: BindingContext,
@@ -224,9 +228,7 @@ internal fun createSimplePSICallArgument(
bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it) bindingContext.get(BindingContext.ONLY_RESOLVED_CALL, it)
} }
// todo hack for if expression: sometimes we not write properly type information for branches // todo hack for if expression: sometimes we not write properly type information for branches
val baseType = typeInfoForArgument.type?.unwrap() ?: val baseType = typeInfoForArgument.type?.unwrap() ?: onlyResolvedCall?.resultCallAtom?.freshReturnType ?: return null
onlyResolvedCall?.resultCallAtom?.freshReturnType ?:
return null
// we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches. // we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches.
val receiverToCast = transformToReceiverWithSmartCastInfo( val receiverToCast = transformToReceiverWithSmartCastInfo(
@@ -240,8 +242,13 @@ internal fun createSimplePSICallArgument(
return if (onlyResolvedCall == null) { return if (onlyResolvedCall == null) {
ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast) ExpressionKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast)
} } else {
else { SubKotlinCallArgumentImpl(
SubKotlinCallArgumentImpl(valueArgument, dataFlowInfoBeforeThisArgument, typeInfoForArgument.dataFlowInfo, receiverToCast, onlyResolvedCall) valueArgument,
dataFlowInfoBeforeThisArgument,
typeInfoForArgument.dataFlowInfo,
receiverToCast,
onlyResolvedCall
)
} }
} }
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
val KotlinCall.psiKotlinCall: PSIKotlinCall get() { val KotlinCall.psiKotlinCall: PSIKotlinCall
get() {
assert(this is PSIKotlinCall) { assert(this is PSIKotlinCall) {
"Incorrect ASTCAll: $this. Java class: ${javaClass.canonicalName}" "Incorrect ASTCAll: $this. Java class: ${javaClass.canonicalName}"
} }
@@ -103,8 +104,10 @@ class PSIKotlinCallForInvoke(
psiCall = CallTransformer.CallForImplicitInvoke( psiCall = CallTransformer.CallForImplicitInvoke(
explicitExtensionReceiver?.receiverValue, explicitExtensionReceiver?.receiverValue,
variableReceiver.receiverValue as ExpressionReceiver, baseCall.psiCall, true) variableReceiver.receiverValue as ExpressionReceiver, baseCall.psiCall, true
tracingStrategy = TracingStrategyForInvoke(calleeExpression, psiCall, variableReceiver.receiverValue!!.type) // check for type parameters )
tracingStrategy =
TracingStrategyForInvoke(calleeExpression, psiCall, variableReceiver.receiverValue!!.type) // check for type parameters
} }
} }
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DeprecationResolver import org.jetbrains.kotlin.resolve.DeprecationResolver
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
interface ClassifierUsageChecker { interface ClassifierUsageChecker {
fun check( fun check(
@@ -92,7 +91,10 @@ interface ClassifierUsageChecker {
return targets.filterIsInstance<ClassifierDescriptor>().singleOrNull() return targets.filterIsInstance<ClassifierDescriptor>().singleOrNull()
} }
private fun getReferenceToCompanionViaClassifier(expression: KtReferenceExpression, target: ClassifierDescriptor): ClassifierDescriptor? { private fun getReferenceToCompanionViaClassifier(
expression: KtReferenceExpression,
target: ClassifierDescriptor
): ClassifierDescriptor? {
if (!DescriptorUtils.isCompanionObject(target)) return null if (!DescriptorUtils.isCompanionObject(target)) return null
return trace.get(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, expression) return trace.get(BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, expression)
} }
@@ -44,9 +44,11 @@ abstract class KotlinVersionStringAnnotationValueChecker(
val annotation = descriptor.annotations.findAnnotation(annotationFqName) ?: return val annotation = descriptor.annotations.findAnnotation(annotationFqName) ?: return
val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return val version = annotation.allValueArguments.values.singleOrNull()?.value as? String ?: return
if (!version.matches(VERSION_REGEX)) { if (!version.matches(VERSION_REGEX)) {
diagnosticHolder.report(Errors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE.on( diagnosticHolder.report(
Errors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE.on(
annotation.source.getPsi() ?: declaration, annotationFqName annotation.source.getPsi() ?: declaration, annotationFqName
)) )
)
return return
} }
@@ -59,7 +61,8 @@ abstract class KotlinVersionStringAnnotationValueChecker(
version: String, version: String,
diagnosticHolder: DiagnosticSink, diagnosticHolder: DiagnosticSink,
languageVersionSettings: LanguageVersionSettings languageVersionSettings: LanguageVersionSettings
) {} ) {
}
companion object { companion object {
val VERSION_REGEX: Regex = "(0|[1-9][0-9]*)".let { number -> Regex("$number\\.$number(\\.$number)?") } val VERSION_REGEX: Regex = "(0|[1-9][0-9]*)".let { number -> Regex("$number\\.$number(\\.$number)?") }
@@ -77,7 +80,12 @@ object SinceKotlinAnnotationValueChecker : KotlinVersionStringAnnotationValueChe
val apiVersion = ApiVersion.parse(version) val apiVersion = ApiVersion.parse(version)
val specified = languageVersionSettings.apiVersion val specified = languageVersionSettings.apiVersion
if (apiVersion != null && apiVersion > specified) { if (apiVersion != null && apiVersion > specified) {
diagnosticHolder.report(Errors.NEWER_VERSION_IN_SINCE_KOTLIN.on(annotation.source.getPsi() ?: declaration, specified.versionString)) diagnosticHolder.report(
Errors.NEWER_VERSION_IN_SINCE_KOTLIN.on(
annotation.source.getPsi() ?: declaration,
specified.versionString
)
)
} }
} }
} }
@@ -41,9 +41,13 @@ object UnderscoreChecker : DeclarationChecker {
val isValidSingleUnderscore = allowSingleUnderscore && identifier.text == "_" val isValidSingleUnderscore = allowSingleUnderscore && identifier.text == "_"
if (!isValidSingleUnderscore && identifier.text.all { it == '_' }) { if (!isValidSingleUnderscore && identifier.text.all { it == '_' }) {
diagnosticHolder.report(Errors.UNDERSCORE_IS_RESERVED.on(identifier)) diagnosticHolder.report(Errors.UNDERSCORE_IS_RESERVED.on(identifier))
} } else if (isValidSingleUnderscore && !languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) {
else if (isValidSingleUnderscore && !languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) { diagnosticHolder.report(
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName to languageVersionSettings)) Errors.UNSUPPORTED_FEATURE.on(
identifier,
LanguageFeature.SingleUnderscoreForParameterName to languageVersionSettings
)
)
} }
} }
@@ -226,7 +226,8 @@ abstract class KotlinSuppressCache {
private class StringSuppressRequest( private class StringSuppressRequest(
override val element: PsiElement, override val element: PsiElement,
override val severity: Severity, override val severity: Severity,
override val suppressKey: String) : SuppressRequest override val suppressKey: String
) : SuppressRequest
private class DiagnosticSuppressRequest(val diagnostic: Diagnostic) : SuppressRequest { private class DiagnosticSuppressRequest(val diagnostic: Diagnostic) : SuppressRequest {
override val element: PsiElement get() = diagnostic.psiElement override val element: PsiElement get() = diagnostic.psiElement
@@ -241,8 +242,7 @@ class BindingContextSuppressCache(val context: BindingContext) : KotlinSuppressC
return if (descriptor != null) { return if (descriptor != null) {
descriptor.annotations.toList() descriptor.annotations.toList()
} } else {
else {
annotated.annotationEntries.mapNotNull { context.get(BindingContext.ANNOTATION, it) } annotated.annotationEntries.mapNotNull { context.get(BindingContext.ANNOTATION, it) }
} }
} }
@@ -60,5 +60,6 @@ class MutableDiagnosticsWithSuppression @JvmOverloads constructor(
modificationTracker.incModificationCount() modificationTracker.incModificationCount()
} }
@TestOnly fun getReadonlyView(): DiagnosticsWithSuppression = readonlyView() @TestOnly
fun getReadonlyView(): DiagnosticsWithSuppression = readonlyView()
} }
@@ -33,7 +33,8 @@ import java.util.*
interface SyntheticResolveExtension { interface SyntheticResolveExtension {
companion object : ProjectExtensionDescriptor<SyntheticResolveExtension>( companion object : ProjectExtensionDescriptor<SyntheticResolveExtension>(
"org.jetbrains.kotlin.syntheticResolveExtension", SyntheticResolveExtension::class.java) { "org.jetbrains.kotlin.syntheticResolveExtension", SyntheticResolveExtension::class.java
) {
fun getInstance(project: Project): SyntheticResolveExtension { fun getInstance(project: Project): SyntheticResolveExtension {
val instances = getInstances(project) val instances = getInstances(project)
if (instances.size == 1) return instances.single() if (instances.size == 1) return instances.single()
@@ -45,9 +46,11 @@ interface SyntheticResolveExtension {
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> = override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
instances.flatMap { it.getSyntheticFunctionNames(thisDescriptor) } instances.flatMap { it.getSyntheticFunctionNames(thisDescriptor) }
override fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, name: Name, override fun generateSyntheticClasses(
thisDescriptor: ClassDescriptor, name: Name,
ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider, ctx: LazyClassContext, declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor>) = result: MutableSet<ClassDescriptor>
) =
instances.forEach { it.generateSyntheticClasses(thisDescriptor, name, ctx, declarationProvider, result) } instances.forEach { it.generateSyntheticClasses(thisDescriptor, name, ctx, declarationProvider, result) }
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? = override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
@@ -57,14 +60,18 @@ interface SyntheticResolveExtension {
instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) } instances.forEach { it.addSyntheticSupertypes(thisDescriptor, supertypes) }
// todo revert // todo revert
override fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, name: Name, override fun generateSyntheticMethods(
thisDescriptor: ClassDescriptor, name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>, fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) = result: MutableCollection<SimpleFunctionDescriptor>
) =
instances.forEach { it.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result) } instances.forEach { it.generateSyntheticMethods(thisDescriptor, name, fromSupertypes, result) }
override fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, name: Name, override fun generateSyntheticProperties(
thisDescriptor: ClassDescriptor, name: Name,
fromSupertypes: ArrayList<PropertyDescriptor>, fromSupertypes: ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) = result: MutableSet<PropertyDescriptor>
) =
instances.forEach { it.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result) } instances.forEach { it.generateSyntheticProperties(thisDescriptor, name, fromSupertypes, result) }
} }
} }
@@ -78,22 +85,28 @@ interface SyntheticResolveExtension {
fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {} fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList<KotlinType>) {}
fun generateSyntheticClasses(thisDescriptor: ClassDescriptor, fun generateSyntheticClasses(
thisDescriptor: ClassDescriptor,
name: Name, name: Name,
ctx: LazyClassContext, ctx: LazyClassContext,
declarationProvider: ClassMemberDeclarationProvider, declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor>) { result: MutableSet<ClassDescriptor>
) {
} }
fun generateSyntheticMethods(thisDescriptor: ClassDescriptor, fun generateSyntheticMethods(
thisDescriptor: ClassDescriptor,
name: Name, name: Name,
fromSupertypes: List<SimpleFunctionDescriptor>, fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>) { result: MutableCollection<SimpleFunctionDescriptor>
) {
} }
fun generateSyntheticProperties(thisDescriptor: ClassDescriptor, fun generateSyntheticProperties(
thisDescriptor: ClassDescriptor,
name: Name, name: Name,
fromSupertypes: ArrayList<PropertyDescriptor>, fromSupertypes: ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>) { result: MutableSet<PropertyDescriptor>
) {
} }
} }
@@ -15,6 +15,7 @@
*/ */
@file:JvmName("FindLoopsInSupertypes") @file:JvmName("FindLoopsInSupertypes")
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
@@ -19,8 +19,10 @@ class BasicAbsentDescriptorHandler : AbsentDescriptorHandler {
} }
class NoDescriptorForDeclarationException @JvmOverloads constructor(declaration: KtDeclaration, additionalDetails: String? = null) : class NoDescriptorForDeclarationException @JvmOverloads constructor(declaration: KtDeclaration, additionalDetails: String? = null) :
KotlinExceptionWithAttachments("Descriptor wasn't found for declaration $declaration" KotlinExceptionWithAttachments(
+ (additionalDetails?.let { "\n---------------------------------------------------\n$it" } ?: "")) { "Descriptor wasn't found for declaration $declaration"
+ (additionalDetails?.let { "\n---------------------------------------------------\n$it" } ?: "")
) {
init { init {
withAttachment("declaration.kt", declaration.getElementTextWithContext()) withAttachment("declaration.kt", declaration.getElementTextWithContext())
} }
@@ -60,20 +60,33 @@ class FileScopeFactory(
return FilesScopesBuilder(file, existingImports, packageFragment, packageView).result return FilesScopesBuilder(file, existingImports, packageFragment, packageView).result
} }
private fun createDefaultImportResolvers(extraImports: Collection<KtImportDirective>, aliasImportNames: Collection<FqName>): Pair<LazyImportResolver, LazyImportResolver> { private fun createDefaultImportResolvers(
extraImports: Collection<KtImportDirective>,
aliasImportNames: Collection<FqName>
): Pair<LazyImportResolver, LazyImportResolver> {
val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false) val tempTrace = TemporaryBindingTrace.create(bindingTrace, "Transient trace for default imports lazy resolve", false)
val allImplicitImports = defaultImports concat extraImports val allImplicitImports = defaultImports concat extraImports
val defaultImportsFiltered = if (aliasImportNames.isEmpty()) { // optimization val defaultImportsFiltered = if (aliasImportNames.isEmpty()) { // optimization
allImplicitImports allImplicitImports
} } else {
else {
allImplicitImports.filter { it.isAllUnder || it.importedFqName !in aliasImportNames } allImplicitImports.filter { it.isAllUnder || it.importedFqName !in aliasImportNames }
} }
val defaultExplicitImportResolver = createImportResolver(ExplicitImportsIndexed(defaultImportsFiltered), tempTrace, packageFragment = null, aliasImportNames = aliasImportNames) val defaultExplicitImportResolver = createImportResolver(
ExplicitImportsIndexed(defaultImportsFiltered),
tempTrace,
packageFragment = null,
aliasImportNames = aliasImportNames
)
val defaultAllUnderImportResolver = val defaultAllUnderImportResolver =
createImportResolver(AllUnderImportsIndexed(defaultImportsFiltered), tempTrace, packageFragment = null, aliasImportNames = aliasImportNames, excludedImports = defaultImportProvider.excludedImports) createImportResolver(
AllUnderImportsIndexed(defaultImportsFiltered),
tempTrace,
packageFragment = null,
aliasImportNames = aliasImportNames,
excludedImports = defaultImportProvider.excludedImports
)
return defaultExplicitImportResolver to defaultAllUnderImportResolver return defaultExplicitImportResolver to defaultAllUnderImportResolver
} }
@@ -105,7 +118,12 @@ class FileScopeFactory(
val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null } val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null }
val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace, aliasImportNames, packageFragment) val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace, aliasImportNames, packageFragment)
val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace, aliasImportNames, packageFragment) // TODO: should we count excludedImports here also? val allUnderImportResolver = createImportResolver(
AllUnderImportsIndexed(imports),
bindingTrace,
aliasImportNames,
packageFragment
) // TODO: should we count excludedImports here also?
val lazyImportingScope = object : ImportingScope by ImportingScope.Empty { val lazyImportingScope = object : ImportingScope by ImportingScope.Empty {
// avoid constructing the scope before we query it // avoid constructing the scope before we query it
@@ -114,7 +132,8 @@ class FileScopeFactory(
} }
} }
val lexicalScope = LexicalScope.Base(lazyImportingScope, topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file)) val lexicalScope =
LexicalScope.Base(lazyImportingScope, topLevelDescriptorProvider.getPackageFragmentOrDiagnoseFailure(file.packageFqName, file))
val importResolver = object : ImportResolver { val importResolver = object : ImportResolver {
override fun forceResolveAllImports() { override fun forceResolveAllImports() {
@@ -125,8 +144,7 @@ class FileScopeFactory(
override fun forceResolveImport(importDirective: KtImportDirective) { override fun forceResolveImport(importDirective: KtImportDirective) {
if (importDirective.isAllUnder) { if (importDirective.isAllUnder) {
allUnderImportResolver.forceResolveImport(importDirective) allUnderImportResolver.forceResolveImport(importDirective)
} } else {
else {
explicitImportResolver.forceResolveImport(importDirective) explicitImportResolver.forceResolveImport(importDirective)
} }
} }
@@ -155,22 +173,32 @@ class FileScopeFactory(
var scope: ImportingScope var scope: ImportingScope
val debugName = "LazyFileScope for file " + file.name val debugName = "LazyFileScope for file " + file.name
scope = LazyImportScope(existingImports, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES, scope = LazyImportScope(
"Default all under imports in $debugName (invisible classes only)") existingImports, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
"Default all under imports in $debugName (invisible classes only)"
)
scope = LazyImportScope(scope, allUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES, scope = LazyImportScope(
"All under imports in $debugName (invisible classes only)") scope, allUnderImportResolver, LazyImportScope.FilteringKind.INVISIBLE_CLASSES,
"All under imports in $debugName (invisible classes only)"
)
scope = currentPackageScope(packageView, aliasImportNames, dummyContainerDescriptor, FilteringKind.INVISIBLE_CLASSES, scope) scope = currentPackageScope(packageView, aliasImportNames, dummyContainerDescriptor, FilteringKind.INVISIBLE_CLASSES, scope)
scope = LazyImportScope(scope, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES, scope = LazyImportScope(
"Default all under imports in $debugName (visible classes)") scope, defaultAllUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
"Default all under imports in $debugName (visible classes)"
)
scope = LazyImportScope(scope, allUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES, scope = LazyImportScope(
"All under imports in $debugName (visible classes)") scope, allUnderImportResolver, LazyImportScope.FilteringKind.VISIBLE_CLASSES,
"All under imports in $debugName (visible classes)"
)
scope = LazyImportScope(scope, defaultExplicitImportResolver, LazyImportScope.FilteringKind.ALL, scope = LazyImportScope(
"Default explicit imports in $debugName") scope, defaultExplicitImportResolver, LazyImportScope.FilteringKind.ALL,
"Default explicit imports in $debugName"
)
scope = SubpackagesImportingScope(scope, moduleDescriptor, FqName.ROOT) scope = SubpackagesImportingScope(scope, moduleDescriptor, FqName.ROOT)
@@ -247,7 +275,8 @@ class FileScopeFactory(
} }
// we use this dummy implementation of DeclarationDescriptor to check accessibility of symbols from the current package // we use this dummy implementation of DeclarationDescriptor to check accessibility of symbols from the current package
private class DummyContainerDescriptor(file: KtFile, private val packageFragment: PackageFragmentDescriptor) : DeclarationDescriptorNonRoot { private class DummyContainerDescriptor(file: KtFile, private val packageFragment: PackageFragmentDescriptor) :
DeclarationDescriptorNonRoot {
private val sourceElement = KotlinSourceElement(file) private val sourceElement = KotlinSourceElement(file)
override fun getContainingDeclaration() = packageFragment override fun getContainingDeclaration() = packageFragment
@@ -85,16 +85,14 @@ class LazyImportResolver(
private val packageFragment: PackageFragmentDescriptor?, private val packageFragment: PackageFragmentDescriptor?,
val deprecationResolver: DeprecationResolver val deprecationResolver: DeprecationResolver
) : ImportResolver { ) : ImportResolver {
private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues { private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues { directive: KtImportDirective ->
directive: KtImportDirective ->
qualifiedExpressionResolver.processImportReference( qualifiedExpressionResolver.processImportReference(
directive, moduleDescriptor, traceForImportResolve, excludedImportNames, packageFragment directive, moduleDescriptor, traceForImportResolve, excludedImportNames, packageFragment
) )
} }
private val forceResolveImportDirective = storageManager.createMemoizedFunction { private val forceResolveImportDirective = storageManager.createMemoizedFunction { directive: KtImportDirective ->
directive: KtImportDirective ->
val scope = importedScopesProvider(directive) val scope = importedScopesProvider(directive)
if (scope is LazyExplicitImportScope) { if (scope is LazyExplicitImportScope) {
val allDescriptors = scope.storeReferencesToDescriptors() val allDescriptors = scope.storeReferencesToDescriptors()
@@ -267,7 +265,13 @@ class LazyImportScope(
val importPath = directive.importPath ?: continue val importPath = directive.importPath ?: continue
val importedName = importPath.importedName val importedName = importPath.importedName
if (importedName == null || nameFilter(importedName)) { if (importedName == null || nameFilter(importedName)) {
descriptors.addAll(importResolver.getImportScope(directive).getContributedDescriptors(kindFilter, nameFilter, changeNamesForAliased)) descriptors.addAll(
importResolver.getImportScope(directive).getContributedDescriptors(
kindFilter,
nameFilter,
changeNamesForAliased
)
)
} }
} }
descriptors descriptors
@@ -90,21 +90,18 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
internal fun toInfoString() = toString() + ": " + index().toString() internal fun toInfoString() = toString() + ": " + index().toString()
override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<KtDeclaration> override fun getDeclarations(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<KtDeclaration> =
= index().allDeclarations index().allDeclarations
override fun getFunctionDeclarations(name: Name): List<KtNamedFunction> override fun getFunctionDeclarations(name: Name): List<KtNamedFunction> = index().functions[safeNameForLazyResolve(name)].toList()
= index().functions[safeNameForLazyResolve(name)].toList()
override fun getPropertyDeclarations(name: Name): List<KtProperty> override fun getPropertyDeclarations(name: Name): List<KtProperty> = index().properties[safeNameForLazyResolve(name)].toList()
= index().properties[safeNameForLazyResolve(name)].toList()
override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> override fun getDestructuringDeclarationsEntries(name: Name): Collection<KtDestructuringDeclarationEntry> =
= index().destructuringDeclarationsEntries[safeNameForLazyResolve(name)].toList() index().destructuringDeclarationsEntries[safeNameForLazyResolve(name)].toList()
override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo> override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo> =
= index().classesAndObjects[safeNameForLazyResolve(name)] index().classesAndObjects[safeNameForLazyResolve(name)]
override fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias> override fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias> = index().typeAliases[safeNameForLazyResolve(name)]
= index().typeAliases[safeNameForLazyResolve(name)]
} }
@@ -25,8 +25,8 @@ class FileBasedPackageMemberDeclarationProvider(
storageManager: StorageManager, storageManager: StorageManager,
private val fqName: FqName, private val fqName: FqName,
private val factory: FileBasedDeclarationProviderFactory, private val factory: FileBasedDeclarationProviderFactory,
private val packageFiles: Collection<KtFile>) private val packageFiles: Collection<KtFile>
: AbstractPsiBasedDeclarationProvider(storageManager), PackageMemberDeclarationProvider { ) : AbstractPsiBasedDeclarationProvider(storageManager), PackageMemberDeclarationProvider {
private val allDeclaredSubPackages = storageManager.createLazyValue<Collection<FqName>> { private val allDeclaredSubPackages = storageManager.createLazyValue<Collection<FqName>> {
factory.getAllDeclaredSubPackagesOf(fqName) factory.getAllDeclaredSubPackagesOf(fqName)
@@ -56,20 +56,27 @@ class ClassResolutionScopesSupport(
createInheritanceScope(parent = inheritanceScopeWithoutMe(), ownerDescriptor = classDescriptor, classDescriptor = classDescriptor) createInheritanceScope(parent = inheritanceScopeWithoutMe(), ownerDescriptor = classDescriptor, classDescriptor = classDescriptor)
} }
val scopeForCompanionObjectHeaderResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) { val scopeForCompanionObjectHeaderResolution: () -> LexicalScope =
storageManager.createLazyValue(onRecursion = createErrorLexicalScope) {
createInheritanceScope(inheritanceScopeWithoutMe(), classDescriptor, classDescriptor, withCompanionObject = false) createInheritanceScope(inheritanceScopeWithoutMe(), classDescriptor, classDescriptor, withCompanionObject = false)
} }
val scopeForMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) { val scopeForMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) {
val scopeWithGenerics = scopeWithGenerics(inheritanceScopeWithMe()) val scopeWithGenerics = scopeWithGenerics(inheritanceScopeWithMe())
LexicalScopeImpl(scopeWithGenerics, classDescriptor, true, classDescriptor.thisAsReceiverParameter, LexicalScopeKind.CLASS_MEMBER_SCOPE) LexicalScopeImpl(
scopeWithGenerics,
classDescriptor,
true,
classDescriptor.thisAsReceiverParameter,
LexicalScopeKind.CLASS_MEMBER_SCOPE
)
} }
val scopeForStaticMemberDeclarationResolution: () -> LexicalScope = storageManager.createLazyValue(onRecursion = createErrorLexicalScope) { val scopeForStaticMemberDeclarationResolution: () -> LexicalScope =
storageManager.createLazyValue(onRecursion = createErrorLexicalScope) {
if (classDescriptor.kind.isSingleton) { if (classDescriptor.kind.isSingleton) {
scopeForMemberDeclarationResolution() scopeForMemberDeclarationResolution()
} } else {
else {
inheritanceScopeWithMe() inheritanceScopeWithMe()
} }
} }
@@ -97,19 +104,25 @@ class ClassResolutionScopesSupport(
parentForNewScope = classDescriptor.companionObjectDescriptor?.let { parentForNewScope = classDescriptor.companionObjectDescriptor?.let {
it.getAllSuperclassesWithoutAny().asReversed().fold(parent) { scope, currentClass -> it.getAllSuperclassesWithoutAny().asReversed().fold(parent) { scope, currentClass ->
createInheritanceScope(parent = scope, ownerDescriptor = ownerDescriptor, classDescriptor = currentClass, withCompanionObject = false) createInheritanceScope(
parent = scope,
ownerDescriptor = ownerDescriptor,
classDescriptor = currentClass,
withCompanionObject = false
)
} }
} ?: parent } ?: parent
} } else {
else {
implicitReceiver = null implicitReceiver = null
parentForNewScope = parent parentForNewScope = parent
} }
return LexicalChainedScope(parentForNewScope, ownerDescriptor, false, return LexicalChainedScope(
parentForNewScope, ownerDescriptor, false,
implicitReceiver, implicitReceiver,
LexicalScopeKind.CLASS_INHERITANCE, LexicalScopeKind.CLASS_INHERITANCE,
memberScopes = staticScopes, isStaticScope = true) memberScopes = staticScopes, isStaticScope = true
)
} }
private fun <T : Any> StorageManager.createLazyValue(onRecursion: ((Boolean) -> T), compute: () -> T) = private fun <T : Any> StorageManager.createLazyValue(onRecursion: ((Boolean) -> T), compute: () -> T) =
@@ -80,5 +80,6 @@ class LazyScriptDescriptor(
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!! override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
override fun computeSupertypes() = listOf(ScriptHelper.getInstance().getKotlinType(this, scriptDefinition.template)).ifEmpty { listOf(builtIns.anyType) } override fun computeSupertypes() =
listOf(ScriptHelper.getInstance().getKotlinType(this, scriptDefinition.template)).ifEmpty { listOf(builtIns.anyType) }
} }
@@ -87,12 +87,18 @@ class LazyTypeAliasDescriptor(
declaredTypeParameters: List<TypeParameterDescriptor>, declaredTypeParameters: List<TypeParameterDescriptor>,
underlyingType: SimpleType, underlyingType: SimpleType,
expandedType: SimpleType expandedType: SimpleType
) = initialize(declaredTypeParameters, storageManager.createLazyValue { underlyingType }, storageManager.createLazyValue { expandedType }) ) = initialize(
declaredTypeParameters,
storageManager.createLazyValue { underlyingType },
storageManager.createLazyValue { expandedType }
)
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor { override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor {
if (substitutor.isEmpty) return this if (substitutor.isEmpty) return this
val substituted = LazyTypeAliasDescriptor(storageManager, trace, val substituted = LazyTypeAliasDescriptor(
containingDeclaration, annotations, name, source, visibility) storageManager, trace,
containingDeclaration, annotations, name, source, visibility
)
substituted.initialize(declaredTypeParameters, substituted.initialize(declaredTypeParameters,
storageManager.createLazyValue { storageManager.createLazyValue {
substitutor.substitute(underlyingType, Variance.INVARIANT)!!.asSimpleType() substitutor.substitute(underlyingType, Variance.INVARIANT)!!.asSimpleType()
@@ -108,7 +114,8 @@ class LazyTypeAliasDescriptor(
lazyTypeConstructorParameters() lazyTypeConstructorParameters()
companion object { companion object {
@JvmStatic fun create( @JvmStatic
fun create(
storageManager: StorageManager, storageManager: StorageManager,
trace: BindingTrace, trace: BindingTrace,
containingDeclaration: DeclarationDescriptor, containingDeclaration: DeclarationDescriptor,
@@ -117,7 +124,9 @@ class LazyTypeAliasDescriptor(
sourceElement: SourceElement, sourceElement: SourceElement,
visibility: Visibility visibility: Visibility
): LazyTypeAliasDescriptor = ): LazyTypeAliasDescriptor =
LazyTypeAliasDescriptor(storageManager, trace, LazyTypeAliasDescriptor(
containingDeclaration, annotations, name, sourceElement, visibility) storageManager, trace,
containingDeclaration, annotations, name, sourceElement, visibility
)
} }
} }
@@ -62,7 +62,12 @@ class ReplState {
abstract val parentLine: SuccessfulLine? abstract val parentLine: SuccessfulLine?
class SubmittedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo() class SubmittedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo()
class SuccessfulLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?, val lineDescriptor: LazyScriptDescriptor) : LineInfo() class SuccessfulLine(
override val linePsi: KtFile,
override val parentLine: SuccessfulLine?,
val lineDescriptor: LazyScriptDescriptor
) : LineInfo()
class FailedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo() class FailedLine(override val linePsi: KtFile, override val parentLine: SuccessfulLine?) : LineInfo()
} }
@@ -57,8 +57,7 @@ interface ExpressionReceiver : ReceiverValue {
var referenceExpression: KtReferenceExpression? = null var referenceExpression: KtReferenceExpression? = null
if (expression is KtThisExpression) { if (expression is KtThisExpression) {
referenceExpression = expression.instanceReference referenceExpression = expression.instanceReference
} } else if (expression is KtConstructorDelegationReferenceExpression) { // todo check this
else if (expression is KtConstructorDelegationReferenceExpression) { // todo check this
referenceExpression = expression referenceExpression = expression
} }
@@ -67,12 +66,11 @@ interface ExpressionReceiver : ReceiverValue {
if (descriptor is ClassDescriptor) { if (descriptor is ClassDescriptor) {
return ThisExpressionClassReceiver(descriptor.original, expression, type) return ThisExpressionClassReceiver(descriptor.original, expression, type)
} }
} } else if (expression is KtSuperExpression) {
else if (expression is KtSuperExpression) {
// if there is no THIS_TYPE_FOR_SUPER_EXPRESSION in binding context, we fall through into more restrictive option // if there is no THIS_TYPE_FOR_SUPER_EXPRESSION in binding context, we fall through into more restrictive option
// i.e. just return common ExpressionReceiverImpl // i.e. just return common ExpressionReceiverImpl
bindingContext[BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression]?.let { bindingContext[BindingContext.THIS_TYPE_FOR_SUPER_EXPRESSION, expression]?.let { thisType ->
thisType -> return SuperExpressionReceiver(thisType, expression, type) return SuperExpressionReceiver(thisType, expression, type)
} }
} }
@@ -70,7 +70,8 @@ class ClassQualifier(
ClassValueReceiver(this, it) ClassValueReceiver(this, it)
} }
override val staticScope: MemberScope get() { override val staticScope: MemberScope
get() {
val scopes = ArrayList<MemberScope>(2) val scopes = ArrayList<MemberScope>(2)
scopes.add(descriptor.staticScope) scopes.add(descriptor.staticScope)
@@ -98,8 +99,10 @@ class TypeAliasQualifier(
override val staticScope: MemberScope override val staticScope: MemberScope
get() = when { get() = when {
DescriptorUtils.isEnumClass(classDescriptor) -> DescriptorUtils.isEnumClass(classDescriptor) ->
ChainedMemberScope("Static scope for typealias ${descriptor.name}", ChainedMemberScope(
listOf(classDescriptor.staticScope, EnumEntriesScope())) "Static scope for typealias ${descriptor.name}",
listOf(classDescriptor.staticScope, EnumEntriesScope())
)
else -> else ->
classDescriptor.staticScope classDescriptor.staticScope
} }
@@ -28,7 +28,8 @@ import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class LockBasedLazyResolveStorageManager(private val storageManager: StorageManager): StorageManager by storageManager, LazyResolveStorageManager { class LockBasedLazyResolveStorageManager(private val storageManager: StorageManager) : StorageManager by storageManager,
LazyResolveStorageManager {
override fun <K, V : Any> createSoftlyRetainedMemoizedFunction(compute: Function1<K, V>) = override fun <K, V : Any> createSoftlyRetainedMemoizedFunction(compute: Function1<K, V>) =
storageManager.createMemoizedFunction<K, V>(compute, ContainerUtil.createConcurrentSoftValueMap<K, Any>()) storageManager.createMemoizedFunction<K, V>(compute, ContainerUtil.createConcurrentSoftValueMap<K, Any>())
@@ -171,8 +171,7 @@ object CastDiagnosticsUtil {
TypeProjectionImpl(supertype), TypeProjectionImpl(supertypeWithVariables), variableConstructors::contains TypeProjectionImpl(supertype), TypeProjectionImpl(supertypeWithVariables), variableConstructors::contains
) )
Maps.newHashMap(solution.substitution) Maps.newHashMap(solution.substitution)
} } else {
else {
// If there's no corresponding supertype, no variables are determined // If there's no corresponding supertype, no variables are determined
// This may be OK, e.g. in case 'Any as List<*>' // This may be OK, e.g. in case 'Any as List<*>'
Maps.newHashMapWithExpectedSize<TypeConstructor, TypeProjection>(variables.size) Maps.newHashMapWithExpectedSize<TypeConstructor, TypeProjection>(variables.size)
@@ -186,7 +185,8 @@ object CastDiagnosticsUtil {
if (value == null) { if (value == null) {
substitution.put( substitution.put(
variable.typeConstructor, variable.typeConstructor,
TypeUtils.makeStarProjection(variable)) TypeUtils.makeStarProjection(variable)
)
allArgumentsInferred = false allArgumentsInferred = false
} }
} }

Some files were not shown because too many files have changed in this diff Show More