Reformat 'frontend' module according to new codestyle
This commit is contained in:
@@ -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]
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -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
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -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) {
|
||||||
|
|||||||
+12
-2
@@ -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))
|
||||||
|
|||||||
+8
-3
@@ -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
|
||||||
|
|||||||
+6
-3
@@ -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)
|
||||||
|
|||||||
+4
-2
@@ -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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -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))
|
||||||
|
|||||||
+1
-2
@@ -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(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -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?
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -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 }
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-7
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-8
@@ -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)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-8
@@ -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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-3
@@ -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!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-5
@@ -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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -36,6 +36,7 @@ interface AdditionalTypeChecker {
|
|||||||
receiverArgument: ReceiverValue,
|
receiverArgument: ReceiverValue,
|
||||||
safeAccess: Boolean,
|
safeAccess: Boolean,
|
||||||
c: CallResolutionContext<*>
|
c: CallResolutionContext<*>
|
||||||
) { }
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-5
@@ -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
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -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()
|
||||||
|
|||||||
+1
-2
@@ -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) {
|
||||||
|
|||||||
-1
@@ -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
|
||||||
}
|
}
|
||||||
+45
-34
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-11
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-10
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-10
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-4
@@ -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
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -60,5 +60,6 @@ class MutableDiagnosticsWithSuppression @JvmOverloads constructor(
|
|||||||
modificationTracker.incModificationCount()
|
modificationTracker.incModificationCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly fun getReadonlyView(): DiagnosticsWithSuppression = readonlyView()
|
@TestOnly
|
||||||
|
fun getReadonlyView(): DiagnosticsWithSuppression = readonlyView()
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-13
@@ -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
|
||||||
|
|||||||
+9
-12
@@ -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)]
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -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)
|
||||||
|
|||||||
+23
-10
@@ -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) =
|
||||||
|
|||||||
+2
-1
@@ -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) }
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-6
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -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
Reference in New Issue
Block a user