FIR: implement diagnostics for qualifier as stand-alone expression case

This commit is contained in:
Mikhail Glukhikh
2021-04-30 12:25:52 +03:00
parent 84ccf7bbb1
commit 80a449862e
38 changed files with 190 additions and 58 deletions
@@ -4,7 +4,7 @@ class Factory {
}
companion object {
val f = Function
val f = <!NO_COMPANION_OBJECT!>Function<!>
val x = Function.Default
}
}
@@ -2,5 +2,5 @@ class Outer {
inner class Inner
}
val x = Outer.Inner
val x = Outer.<!NO_COMPANION_OBJECT!>Inner<!>
val klass = Outer.Inner::class
@@ -23,7 +23,8 @@ object D {
val D.E get() = ""
val def = D.E.F // object
val de = D.E // extension
// See KT-46409
val de = D.<!NO_COMPANION_OBJECT!>E<!> // Should be: extension & no error, in fact: qualifier
enum class G {
H;
@@ -38,6 +38,7 @@ fun main(args: Array<String>) {
alias<FirEqualityOperatorCall>("EqualityOperatorCallChecker")
alias<FirAnonymousFunction>("AnonymousFunctionAsExpressionChecker")
alias<FirStringConcatenationCall>("StringConcatenationCallChecker")
alias<FirResolvedQualifier>("ResolvedQualifierChecker")
}
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
@@ -669,6 +669,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val TYPE_PARAMETER_ON_LHS_OF_DOT by error<KtSimpleNameExpression> {
parameter<FirTypeParameterSymbol>("typeParameter")
}
val NO_COMPANION_OBJECT by error<KtSimpleNameExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirRegularClassSymbol>("klass")
}
val EXPRESSION_EXPECTED_PACKAGE_FOUND by error<KtSimpleNameExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
}
val FUNCTION_CONTRACTS by object : DiagnosticGroup("Function contracts") {
@@ -45,6 +45,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _anonymousFunctionAsExpressionCheckers
override val stringConcatenationCallCheckers: Set<FirStringConcatenationCallChecker>
get() = _stringConcatenationCallCheckers
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker>
get() = _resolvedQualifierCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
@@ -62,6 +64,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
private val _equalityOperatorCallCheckers: MutableSet<FirEqualityOperatorCallChecker> = mutableSetOf()
private val _anonymousFunctionAsExpressionCheckers: MutableSet<FirAnonymousFunctionAsExpressionChecker> = mutableSetOf()
private val _stringConcatenationCallCheckers: MutableSet<FirStringConcatenationCallChecker> = mutableSetOf()
private val _resolvedQualifierCheckers: MutableSet<FirResolvedQualifierChecker> = mutableSetOf()
@CheckersComponentInternal
fun register(checkers: ExpressionCheckers) {
@@ -81,5 +84,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
_equalityOperatorCallCheckers += checkers.equalityOperatorCallCheckers
_anonymousFunctionAsExpressionCheckers += checkers.anonymousFunctionAsExpressionCheckers
_stringConcatenationCallCheckers += checkers.stringConcatenationCallCheckers
_resolvedQualifierCheckers += checkers.resolvedQualifierCheckers
}
}
@@ -33,6 +33,7 @@ abstract class ExpressionCheckers {
open val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker> = emptySet()
open val anonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker> = emptySet()
open val stringConcatenationCallCheckers: Set<FirStringConcatenationCallChecker> = emptySet()
open val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + basicExpressionCheckers
@@ -50,4 +51,5 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allEqualityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker> get() = equalityOperatorCallCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allAnonymousFunctionAsExpressionCheckers: Set<FirAnonymousFunctionAsExpressionChecker> get() = anonymousFunctionAsExpressionCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allStringConcatenationCallCheckers: Set<FirStringConcatenationCallChecker> get() = stringConcatenationCallCheckers + basicExpressionCheckers
@CheckersComponentInternal internal val allResolvedQualifierCheckers: Set<FirResolvedQualifierChecker> get() = resolvedQualifierCheckers + basicExpressionCheckers
}
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
@@ -43,3 +44,4 @@ typealias FirSafeCallExpressionChecker = FirExpressionChecker<FirSafeCallExpress
typealias FirEqualityOperatorCallChecker = FirExpressionChecker<FirEqualityOperatorCall>
typealias FirAnonymousFunctionAsExpressionChecker = FirExpressionChecker<FirAnonymousFunction>
typealias FirStringConcatenationCallChecker = FirExpressionChecker<FirStringConcatenationCall>
typealias FirResolvedQualifierChecker = FirExpressionChecker<FirResolvedQualifier>
@@ -398,6 +398,8 @@ object FirErrors {
// Context tracking
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
val TYPE_PARAMETER_ON_LHS_OF_DOT by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
val NO_COMPANION_OBJECT by error1<KtSimpleNameExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val EXPRESSION_EXPECTED_PACKAGE_FOUND by error0<KtSimpleNameExpression>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Function contracts
val ERROR_IN_CONTRACT_DESCRIPTION by error1<KtElement, String>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.isUnit
object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() {
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
val lastQualifiedAccess = context.qualifiedAccesses.lastOrNull()
if (lastQualifiedAccess?.explicitReceiver === expression) return
val lastGetClass = context.getClassCalls.lastOrNull()
if (lastGetClass?.argument === expression) return
// Note: if it's real Unit, it will be filtered by ClassKind.OBJECT check below
if (!expression.typeRef.isUnit) return
when (val symbol = expression.symbol) {
is FirRegularClassSymbol -> {
if (symbol.fir.classKind == ClassKind.OBJECT) return
reporter.reportOn(expression.source, FirErrors.NO_COMPANION_OBJECT, symbol, context)
}
null -> {
reporter.reportOn(expression.source, FirErrors.EXPRESSION_EXPECTED_PACKAGE_FOUND, context)
}
}
}
}
@@ -182,6 +182,10 @@ abstract class AbstractDiagnosticCollectorVisitor(
visitWithQualifiedAccess(qualifiedAccessExpression)
}
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Nothing?) {
visitWithQualifiedAccess(variableAssignment)
}
override fun visitGetClassCall(getClassCall: FirGetClassCall, data: Nothing?) {
visitWithGetClassCall(getClassCall)
}
@@ -56,7 +56,7 @@ class ExpressionCheckersDiagnosticComponent(
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) {
checkers.allBasicExpressionCheckers.check(resolvedQualifier, data, reporter)
checkers.allResolvedQualifierCheckers.check(resolvedQualifier, data, reporter)
}
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) {
@@ -106,6 +106,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_CLA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_SUPER_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPOSED_TYPE_PARAMETER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPRESSION_EXPECTED_PACKAGE_FOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT
@@ -183,6 +184,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SET_METHOD
@@ -879,6 +881,12 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
"Type parameter ''{0}'' cannot have or inherit a companion object, so it cannot be on the left hand side of dot",
SYMBOL
)
map.put(
NO_COMPANION_OBJECT,
"Classifier ''{0}'' does not have a companion object, and thus must be initialized here",
SYMBOL
)
map.put(EXPRESSION_EXPECTED_PACKAGE_FOUND, "Expression expected, but a package name found")
// Function contracts
map.put(ERROR_IN_CONTRACT_DESCRIPTION, "Error in contract description", TO_STRING)
@@ -441,6 +441,13 @@ object LightTreePositioningStrategies {
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
if (node.tokenType == KtNodeTypes.BINARY_EXPRESSION &&
tree.findDescendantByTypes(node, KtTokens.ALL_ASSIGNMENTS) != null
) {
tree.findExpressionDeep(node)?.let {
return markElement(it, startOffset, endOffset, tree, node)
}
}
if (node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION && node.tokenType != KtNodeTypes.SAFE_ACCESS_EXPRESSION) {
return super.mark(node, startOffset, endOffset, tree)
}
@@ -492,7 +499,7 @@ object LightTreePositioningStrategies {
return markElement(tree.referenceExpression(node, locateReferencedName) ?: node, startOffset, endOffset, tree, node)
}
if (node.tokenType == KtNodeTypes.PROPERTY_DELEGATE) {
return markElement(tree.findReferenceExpressionDeep(node) ?: node, startOffset, endOffset, tree, node)
return markElement(tree.findExpressionDeep(node) ?: node, startOffset, endOffset, tree, node)
}
if (node.tokenType in nodeTypesWithOperation) {
return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node)
@@ -661,7 +668,7 @@ object LightTreePositioningStrategies {
}
val descendants =
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } };
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } }
if (descendants.isNotEmpty())
return descendants.map { markSingleElement(it, it, startOffset, endOffset, tree, node) }
return super.mark(node, startOffset, endOffset, tree)
@@ -756,7 +763,7 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.referenceExpression(
return result
}
private fun FlyweightCapableTreeStructure<LighterASTNode>.findReferenceExpressionDeep(node: LighterASTNode): LighterASTNode? =
private fun FlyweightCapableTreeStructure<LighterASTNode>.findExpressionDeep(node: LighterASTNode): LighterASTNode? =
findFirstDescendant(node) { it.isExpression() }
private fun FlyweightCapableTreeStructure<LighterASTNode>.rightParenthesis(node: LighterASTNode): LighterASTNode? =
@@ -863,7 +870,7 @@ fun FlyweightCapableTreeStructure<LighterASTNode>.findDescendantByType(node: Lig
?.firstNotNullResult { child -> child?.let { findDescendantByType(it, type) } }
}
fun FlyweightCapableTreeStructure<LighterASTNode>.findDescendantByTypes(node: LighterASTNode, types: Set<IElementType>): LighterASTNode? {
fun FlyweightCapableTreeStructure<LighterASTNode>.findDescendantByTypes(node: LighterASTNode, types: TokenSet): LighterASTNode? {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
return childrenRef.get()?.firstOrNull { types.contains(it?.tokenType) } ?: childrenRef.get()
@@ -93,4 +93,9 @@ object CommonExpressionCheckers : ExpressionCheckers() {
get() = setOf(
FirAnonymousFunctionChecker,
)
override val resolvedQualifierCheckers: Set<FirResolvedQualifierChecker>
get() = setOf(
FirStandaloneQualifierChecker,
)
}
@@ -66,10 +66,24 @@ fun <R : FirTypeRef> R.copyWithNewSourceKind(newKind: FirFakeSourceElementKind):
* @param stepsToWholeQualifier distance between the original psi and the whole qualifier psi
*/
fun FirSourceElement.getWholeQualifierSourceIfPossible(stepsToWholeQualifier: Int): FirSourceElement {
if (this !is FirRealPsiSourceElement<*>) return this
val qualifiersChain = generateSequence(psi) { it.parent }
val wholeQualifier = qualifiersChain.drop(stepsToWholeQualifier).first()
return wholeQualifier.toFirPsiSourceElement() as FirRealPsiSourceElement
if (stepsToWholeQualifier == 0) return this
return when (this) {
is FirRealPsiSourceElement<*> -> {
val qualifiersChain = generateSequence(psi) { it.parent }
val wholeQualifier = qualifiersChain.drop(stepsToWholeQualifier).first()
wholeQualifier.toFirPsiSourceElement() as FirRealPsiSourceElement
}
is FirLightSourceElement -> {
val qualifiersChain = generateSequence(lighterASTNode) { treeStructure.getParent(it) }
val wholeQualifier = qualifiersChain.drop(stepsToWholeQualifier).first()
wholeQualifier.toFirLightSourceElement(
treeStructure,
startOffset = this.startOffset,
endOffset = wholeQualifier.endOffset + (this.endOffset - this.lighterASTNode.endOffset)
)
}
is FirFakeSourceElement<*> -> {
this
}
}
}
@@ -776,6 +776,9 @@ object PositioningStrategies {
val SELECTOR_BY_QUALIFIED: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
override fun mark(element: PsiElement): List<TextRange> {
if (element is KtBinaryExpression && element.operationToken in KtTokens.ALL_ASSIGNMENTS) {
element.left?.let { return mark(it) }
}
if (element is KtQualifiedExpression) {
when (val selectorExpression = element.selectorExpression) {
is KtElement -> return mark(selectorExpression)
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
package test
import test.C.E1
@@ -16,6 +17,7 @@ class A {
}
fun test() {
// Note: FIR resolve this to test/C instead of test/A.B.C
C
D()
}
@@ -2,25 +2,25 @@ package foo
class X {}
val s = java
val ss = System
val sss = X
val x = "${System}"
val xs = java.lang
val xss = java.lang.System
val xsss = foo.X
val xssss = foo
val f = { System }
val s = <!EXPRESSION_EXPECTED_PACKAGE_FOUND!>java<!>
val ss = <!NO_COMPANION_OBJECT!>System<!>
val sss = <!NO_COMPANION_OBJECT!>X<!>
val x = "${<!NO_COMPANION_OBJECT!>System<!>}"
val xs = java.<!EXPRESSION_EXPECTED_PACKAGE_FOUND!>lang<!>
val xss = java.lang.<!NO_COMPANION_OBJECT!>System<!>
val xsss = foo.<!NO_COMPANION_OBJECT!>X<!>
val xssss = <!EXPRESSION_EXPECTED_PACKAGE_FOUND!>foo<!>
val f = { <!NO_COMPANION_OBJECT!>System<!> }
fun main() {
java = null
System = null
System!!
java.lang.System = null
java.lang.System!!
System is Int
<!EXPRESSION_EXPECTED_PACKAGE_FOUND!>java<!> = null
<!NO_COMPANION_OBJECT!>System<!> = null
<!NO_COMPANION_OBJECT!>System<!>!!
java.lang.<!NO_COMPANION_OBJECT!>System<!> = null
java.lang.<!NO_COMPANION_OBJECT!>System<!>!!
<!NO_COMPANION_OBJECT!>System<!> is Int
<!INVISIBLE_REFERENCE!>System<!>()
(System)
foo@ System
(<!NO_COMPANION_OBJECT!>System<!>)
foo@ <!NO_COMPANION_OBJECT!>System<!>
null <!UNRESOLVED_REFERENCE!>in<!> System
}
+1 -1
View File
@@ -30,7 +30,7 @@ fun test(l : java.util.List<Int>) {
checkSubtype<Set<Int>?>(Collections.singleton<Int>(1))
Collections.singleton<Int>(<!ARGUMENT_TYPE_MISMATCH!>1.0<!>)
List<Int>
<!NO_COMPANION_OBJECT!>List<!><Int>
val o = "sdf" as Object
@@ -10,7 +10,7 @@ val s: String = "test"
// FILE: test.kt
fun ff() {
val a = Test<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
val b = foo<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>s<!>
System<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.println(a + b)
val a = <!NO_COMPANION_OBJECT!>Test<!><!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
val b = <!EXPRESSION_EXPECTED_PACKAGE_FOUND!>foo<!><!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>s<!>
<!NO_COMPANION_OBJECT!>System<!><!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.println(a + b)
}
@@ -36,7 +36,7 @@ val a = A.x
val c = B.<!UNRESOLVED_REFERENCE!>x<!>
val d = b.<!UNRESOLVED_REFERENCE!>x<!>
val s = System // error
val s = <!NO_COMPANION_OBJECT!>System<!> // error
fun test() {
System.out.println()
java.lang.System.out.println()
@@ -33,7 +33,7 @@ fun f() {
A().Inner()
A.Companion.<!UNRESOLVED_REFERENCE!>Nested<!>
A.Companion.<!UNRESOLVED_REFERENCE!>Inner<!>
A.Inner
A.<!NO_COMPANION_OBJECT!>Inner<!>
A.Companion.c
A.Companion.Obj2
A.Companion.Obj2.c
@@ -1 +1 @@
val a: String = <!INITIALIZER_TYPE_MISMATCH!>Nothing<!>
val a: String = <!INITIALIZER_TYPE_MISMATCH, NO_COMPANION_OBJECT!>Nothing<!>
@@ -16,8 +16,8 @@ class E private constructor() {
}
}
val a = A
val a = <!NO_COMPANION_OBJECT!>A<!>
val <!EXPOSED_PROPERTY_TYPE!>b<!> = B
val c = C
val c = <!NO_COMPANION_OBJECT!>C<!>
val d = D
val e = E(42)
@@ -7,10 +7,10 @@ class C
fun test() {
val interface_as_fun = <!UNRESOLVED_REFERENCE!>A<!>()
val interface_as_val = A
val interface_as_val = <!NO_COMPANION_OBJECT!>A<!>
val object_as_fun = <!INVISIBLE_REFERENCE!>B<!>()
val class_as_val = C
val class_as_val = <!NO_COMPANION_OBJECT!>C<!>
}
fun <T> bar() {
@@ -9,10 +9,10 @@ object X {
fun testX() {
val interface_as_fun = X.<!UNRESOLVED_REFERENCE!>A<!>()
val interface_as_val = X.A
val interface_as_val = X.<!NO_COMPANION_OBJECT!>A<!>
val object_as_fun = X.<!INVISIBLE_REFERENCE!>B<!>()
val class_as_val = X.C
val class_as_val = X.<!NO_COMPANION_OBJECT!>C<!>
}
class Y {
@@ -24,10 +24,10 @@ class Y {
fun testY() {
val interface_as_fun = Y.<!UNRESOLVED_REFERENCE!>A<!>()
val interface_as_val = Y.A
val interface_as_val = Y.<!NO_COMPANION_OBJECT!>A<!>
val object_as_fun = Y.<!INVISIBLE_REFERENCE!>B<!>()
val class_as_val = Y.C
val class_as_val = Y.<!NO_COMPANION_OBJECT!>C<!>
}
fun test(x: X) {
@@ -9,7 +9,7 @@ val Int.foo: Int get() = 4
fun Int.extFun() = 4
fun String.test() {
some
<!EXPRESSION_EXPECTED_PACKAGE_FOUND!>some<!>
some.A()
"".<!INAPPLICABLE_CANDIDATE!>some<!>
@@ -11,7 +11,7 @@ sealed class Tree {
fun maxIsClass(): Int = <!NO_ELSE_IN_WHEN!>when<!>(this) {
Empty -> -1
Leaf -> 0
<!NO_COMPANION_OBJECT!>Leaf<!> -> 0
is Node -> this.left.max()
}
@@ -6,14 +6,14 @@ private class C {
private typealias TA = C
private val test1: C = <!INVISIBLE_REFERENCE!>C<!>()
private val test1co: C.Companion = <!INITIALIZER_TYPE_MISMATCH!>C<!>
private val test1co: C.Companion = <!INITIALIZER_TYPE_MISMATCH, NO_COMPANION_OBJECT!>C<!>
private val test2: TA = <!INITIALIZER_TYPE_MISMATCH!>TA(<!NO_VALUE_FOR_PARAMETER!>)<!><!>
private val test2co = TA
// FILE: file2.kt
private val test1: C = C()
private val test1co: C.Companion = <!INITIALIZER_TYPE_MISMATCH!>C<!>
private val test1co: C.Companion = <!INITIALIZER_TYPE_MISMATCH, NO_COMPANION_OBJECT!>C<!>
private val test2: TA = <!INITIALIZER_TYPE_MISMATCH!>TA(<!NO_VALUE_FOR_PARAMETER!>)<!><!>
private val test2co = TA
@@ -22,6 +22,6 @@ package e
fun e() {}
// FILE: f.kt
@file:JvmPackageName(f)
@file:JvmPackageName(<!EXPRESSION_EXPECTED_PACKAGE_FOUND!>f<!>)
package f
const val name = "f"
@@ -16,7 +16,7 @@ fun <S> generate(@BuilderInference g: suspend Controller<S>.() -> Unit): S = TOD
class A
val test1 = generate {
yield(A)
yield(<!NO_COMPANION_OBJECT!>A<!>)
}
val test2: Int = <!INITIALIZER_TYPE_MISMATCH!>generate {
@@ -10,7 +10,7 @@ fun <T : Any> T?.sure() : T = this!!
fun <E> List<*>.toArray(ar: Array<E>): Array<E> = ar
fun testArrays(ci: List<Int?>, cii: List<Int?>?) {
val c1: Array<Int?> = cii.sure().toArray(<!ARGUMENT_TYPE_MISMATCH!>Array<!><Int?>)
val c1: Array<Int?> = cii.sure().toArray(<!ARGUMENT_TYPE_MISMATCH, NO_COMPANION_OBJECT!>Array<!><Int?>)
val c2: Array<Int?> = ci.toArray(Array<Int?>(<!NO_VALUE_FOR_PARAMETER, NO_VALUE_FOR_PARAMETER!>)<!>)
@@ -6,7 +6,7 @@ public class Test {
// FILE: test.kt
fun ff() {
val a = Test.FOO
val b = Test<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
val b = <!NO_COMPANION_OBJECT!>Test<!><!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
System.out.println(a + b)
System<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.println(a + b)
<!NO_COMPANION_OBJECT!>System<!><!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.println(a + b)
}
@@ -3,7 +3,7 @@
// TESTCASE NUMBER: 1
fun case_1(value_1: Any): String {
when (value_1) {
EmptyClass -> return ""
<!NO_COMPANION_OBJECT!>EmptyClass<!> -> return ""
}
return ""
@@ -12,7 +12,7 @@ fun case_1(value_1: Any): String {
// TESTCASE NUMBER: 2
fun case_2(value_1: Any): String {
when (value_1) {
Any -> return ""
<!NO_COMPANION_OBJECT!>Any<!> -> return ""
}
return ""
@@ -21,7 +21,7 @@ fun case_2(value_1: Any): String {
// TESTCASE NUMBER: 3
fun case_3(value_1: Any): String {
when (value_1) {
Nothing -> return ""
<!NO_COMPANION_OBJECT!>Nothing<!> -> return ""
}
return ""
@@ -1888,6 +1888,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NO_COMPANION_OBJECT) { firDiagnostic ->
NoCompanionObjectImpl(
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a.fir),
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.EXPRESSION_EXPECTED_PACKAGE_FOUND) { firDiagnostic ->
ExpressionExpectedPackageFoundImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.ERROR_IN_CONTRACT_DESCRIPTION) { firDiagnostic ->
ErrorInContractDescriptionImpl(
firDiagnostic.a,
@@ -1325,6 +1325,15 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val typeParameter: KtTypeParameterSymbol
}
abstract class NoCompanionObject : KtFirDiagnostic<KtSimpleNameExpression>() {
override val diagnosticClass get() = NoCompanionObject::class
abstract val klass: KtClassLikeSymbol
}
abstract class ExpressionExpectedPackageFound : KtFirDiagnostic<KtSimpleNameExpression>() {
override val diagnosticClass get() = ExpressionExpectedPackageFound::class
}
abstract class ErrorInContractDescription : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = ErrorInContractDescription::class
abstract val reason: String
@@ -2151,6 +2151,21 @@ internal class TypeParameterOnLhsOfDotImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NoCompanionObjectImpl(
override val klass: KtClassLikeSymbol,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NoCompanionObject(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ExpressionExpectedPackageFoundImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.ExpressionExpectedPackageFound(), KtAbstractFirDiagnostic<KtSimpleNameExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ErrorInContractDescriptionImpl(
override val reason: String,
firDiagnostic: FirPsiDiagnostic<*>,