FIR: implement diagnostics for qualifier as stand-alone expression case
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ class Factory {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val f = Function
|
||||
val f = <!NO_COMPANION_OBJECT!>Function<!>
|
||||
val x = Function.Default
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-1
@@ -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;
|
||||
|
||||
+1
@@ -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"
|
||||
|
||||
+4
@@ -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") {
|
||||
|
||||
+4
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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
|
||||
}
|
||||
|
||||
+2
@@ -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)
|
||||
|
||||
+36
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -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)
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+8
@@ -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)
|
||||
|
||||
+11
-4
@@ -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()
|
||||
|
||||
+5
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+2
-2
@@ -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() {
|
||||
|
||||
Vendored
+4
-4
@@ -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
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
Vendored
+1
-1
@@ -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!>)<!>)
|
||||
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -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 ""
|
||||
|
||||
+13
@@ -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,
|
||||
|
||||
+9
@@ -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
|
||||
|
||||
+15
@@ -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<*>,
|
||||
|
||||
Reference in New Issue
Block a user