Introduce FirForLoopChecker

This commit is contained in:
Mikhail Glukhikh
2021-04-02 13:19:04 +03:00
parent 4ddc0ed3fe
commit 2e14b65644
35 changed files with 708 additions and 118 deletions
@@ -0,0 +1,206 @@
FILE: forLoopChecker.kt
public final class NotRange1 : R|kotlin/Any| {
public constructor(): R|NotRange1| {
super<R|kotlin/Any|>()
}
}
public abstract class NotRange2 : R|kotlin/Any| {
public constructor(): R|NotRange2| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|kotlin/Unit|
}
public abstract class ImproperIterator1 : R|kotlin/Any| {
public constructor(): R|ImproperIterator1| {
super<R|kotlin/Any|>()
}
public abstract operator fun hasNext(): R|kotlin/Boolean|
}
public abstract class NotRange3 : R|kotlin/Any| {
public constructor(): R|NotRange3| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|ImproperIterator1|
}
public abstract class ImproperIterator2 : R|kotlin/Any| {
public constructor(): R|ImproperIterator2| {
super<R|kotlin/Any|>()
}
public abstract operator fun next(): R|kotlin/Boolean|
}
public abstract class NotRange4 : R|kotlin/Any| {
public constructor(): R|NotRange4| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|ImproperIterator2|
}
public abstract class ImproperIterator3 : R|kotlin/Any| {
public constructor(): R|ImproperIterator3| {
super<R|kotlin/Any|>()
}
public abstract operator fun hasNext(): R|kotlin/Int|
public abstract operator fun next(): R|kotlin/Int|
}
public abstract class NotRange5 : R|kotlin/Any| {
public constructor(): R|NotRange5| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|ImproperIterator3|
}
public abstract class AmbiguousHasNextIterator : R|kotlin/Any| {
public constructor(): R|AmbiguousHasNextIterator| {
super<R|kotlin/Any|>()
}
public abstract operator fun hasNext(): R|kotlin/Boolean|
public final val hasNext: R|kotlin/Boolean|
public get(): R|kotlin/Boolean| {
^ Boolean(false)
}
public abstract operator fun next(): R|kotlin/Int|
}
public abstract class NotRange6 : R|kotlin/Any| {
public constructor(): R|NotRange6| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|AmbiguousHasNextIterator|
}
public abstract class ImproperIterator4 : R|kotlin/Any| {
public constructor(): R|ImproperIterator4| {
super<R|kotlin/Any|>()
}
public final val hasNext: R|kotlin/Int|
public get(): R|kotlin/Int| {
^ Int(1)
}
public abstract operator fun next(): R|kotlin/Int|
}
public abstract class NotRange7 : R|kotlin/Any| {
public constructor(): R|NotRange7| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|ImproperIterator3|
}
public abstract class GoodIterator : R|kotlin/Any| {
public constructor(): R|GoodIterator| {
super<R|kotlin/Any|>()
}
public abstract operator fun hasNext(): R|kotlin/Boolean|
public abstract operator fun next(): R|kotlin/Int|
}
public abstract class Range0 : R|kotlin/Any| {
public constructor(): R|Range0| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|GoodIterator|
}
public abstract class Range1 : R|kotlin/Any| {
public constructor(): R|Range1| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|kotlin/collections/Iterator<kotlin/Int>|
}
public abstract class ImproperIterator5 : R|kotlin/Any| {
public constructor(): R|ImproperIterator5| {
super<R|kotlin/Any|>()
}
public abstract val R|kotlin/String|.hasNext: R|kotlin/Boolean|
public get(): R|kotlin/Boolean|
public abstract operator fun next(): R|kotlin/Int|
}
public abstract class NotRange8 : R|kotlin/Any| {
public constructor(): R|NotRange8| {
super<R|kotlin/Any|>()
}
public abstract operator fun iterator(): R|ImproperIterator5|
}
public final fun test(notRange1: R|NotRange1|, notRange2: R|NotRange2|, notRange3: R|NotRange3|, notRange4: R|NotRange4|, notRange5: R|NotRange5|, notRange6: R|NotRange6|, notRange7: R|NotRange7|, notRange8: R|NotRange8|, range0: R|Range0|, range1: R|Range1|): R|kotlin/Unit| {
lval <iterator>: R|ERROR CLASS: Unresolved name: iterator| = R|<local>/notRange1|.<Unresolved name: iterator>#()
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
lval i: R|ERROR CLASS: Unresolved name: next| = R|<local>/<iterator>|.<Unresolved name: next>#()
}
lval <iterator>: R|kotlin/Unit| = R|<local>/notRange2|.R|/NotRange2.iterator|()
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
lval i: R|ERROR CLASS: Unresolved name: next| = R|<local>/<iterator>|.<Unresolved name: next>#()
}
lval <iterator>: R|ImproperIterator1| = R|<local>/notRange3|.R|/NotRange3.iterator|()
while(R|<local>/<iterator>|.R|/ImproperIterator1.hasNext|()) {
lval i: R|ERROR CLASS: Unresolved name: next| = R|<local>/<iterator>|.<Unresolved name: next>#()
}
lval <iterator>: R|ImproperIterator2| = R|<local>/notRange4|.R|/NotRange4.iterator|()
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
lval i: R|kotlin/Boolean| = R|<local>/<iterator>|.R|/ImproperIterator2.next|()
}
lval <iterator>: R|ImproperIterator3| = R|<local>/notRange5|.R|/NotRange5.iterator|()
while(R|<local>/<iterator>|.R|/ImproperIterator3.hasNext|()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator3.next|()
}
lval <iterator>: R|AmbiguousHasNextIterator| = R|<local>/notRange6|.R|/NotRange6.iterator|()
while(R|<local>/<iterator>|.R|/AmbiguousHasNextIterator.hasNext|()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/AmbiguousHasNextIterator.next|()
}
lval <iterator>: R|ImproperIterator3| = R|<local>/notRange7|.R|/NotRange7.iterator|()
while(R|<local>/<iterator>|.R|/ImproperIterator3.hasNext|()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator3.next|()
}
lval <iterator>: R|ImproperIterator5| = R|<local>/notRange8|.R|/NotRange8.iterator|()
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator5.next|()
}
lval <iterator>: R|GoodIterator| = R|<local>/range0|.R|/Range0.iterator|()
while(R|<local>/<iterator>|.R|/GoodIterator.hasNext|()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/GoodIterator.next|()
}
lval <iterator>: R|kotlin/collections/Iterator<kotlin/Int>| = R|<local>/range1|.R|/Range1.iterator|()
while(R|<local>/<iterator>|.R|kotlin/collections/Iterator.hasNext|()) {
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|SubstitutionOverride<kotlin/collections/Iterator.next: R|kotlin/Int|>|()
}
}
@@ -0,0 +1,89 @@
import java.util.*;
class NotRange1() {
}
abstract class NotRange2() {
abstract operator fun iterator() : Unit
}
abstract class ImproperIterator1 {
abstract operator fun hasNext() : Boolean
}
abstract class NotRange3() {
abstract operator fun iterator() : ImproperIterator1
}
abstract class ImproperIterator2 {
abstract operator fun next() : Boolean
}
abstract class NotRange4() {
abstract operator fun iterator() : ImproperIterator2
}
abstract class ImproperIterator3 {
abstract operator fun hasNext() : Int
abstract operator fun next() : Int
}
abstract class NotRange5() {
abstract operator fun iterator() : ImproperIterator3
}
abstract class AmbiguousHasNextIterator {
abstract operator fun hasNext() : Boolean
val hasNext : Boolean get() = false
abstract operator fun next() : Int
}
abstract class NotRange6() {
abstract operator fun iterator() : AmbiguousHasNextIterator
}
abstract class ImproperIterator4 {
val hasNext : Int get() = 1
abstract operator fun next() : Int
}
abstract class NotRange7() {
abstract operator fun iterator() : ImproperIterator3
}
abstract class GoodIterator {
abstract operator fun hasNext() : Boolean
abstract operator fun next() : Int
}
abstract class Range0() {
abstract operator fun iterator() : GoodIterator
}
abstract class Range1() {
abstract operator fun iterator() : Iterator<Int>
}
abstract class ImproperIterator5 {
abstract val String.hasNext : Boolean
abstract operator fun next() : Int
}
abstract class NotRange8() {
abstract operator fun iterator() : ImproperIterator5
}
fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, notRange8: NotRange8, range0: Range0, range1: Range1) {
for (i in <!ITERATOR_MISSING!>notRange1<!>);
for (i in <!HAS_NEXT_MISSING!>notRange2<!>);
for (i in <!NEXT_MISSING!>notRange3<!>);
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
for (i in notRange5);
for (i in notRange6);
for (i in notRange7);
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
for (i in range0);
for (i in range1);
}
@@ -4827,6 +4827,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("forLoopChecker.kt")
public void testForLoopChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/forLoopChecker.kt");
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker")
@TestDataPath("$PROJECT_ROOT")
@@ -4898,6 +4898,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("forLoopChecker.kt")
public void testForLoopChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/forLoopChecker.kt");
}
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolveWithStdlib/diagnostics/functionReturnTypeMismatchChecker")
@TestDataPath("$PROJECT_ROOT")
@@ -256,6 +256,15 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val ASSIGN_OPERATOR_AMBIGUITY by error<PsiElement> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
val ITERATOR_AMBIGUITY by error<FirSourceElement, PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
val HAS_NEXT_FUNCTION_AMBIGUITY by error<FirSourceElement, PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
val NEXT_AMBIGUITY by error<FirSourceElement, PsiElement>(PositioningStrategy.REFERENCE_BY_QUALIFIED) {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
}
val TYPES_AND_TYPE_PARAMETERS by object : DiagnosticGroup("Types & type parameters") {
@@ -612,6 +621,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<String>("operator")
parameter<FirExpression>("rhs")
}
val ITERATOR_ON_NULLABLE by error<FirSourceElement, KtExpression>()
val UNNECESSARY_SAFE_CALL by warning<PsiElement>(PositioningStrategy.SAFE_ACCESS) {
parameter<ConeKotlinType>("receiverType")
}
@@ -648,6 +658,15 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val CONVENTIONS by object : DiagnosticGroup("Conventions") {
val NO_GET_METHOD by error<KtArrayAccessExpression>(PositioningStrategy.ARRAY_ACCESS)
val NO_SET_METHOD by error<KtArrayAccessExpression>(PositioningStrategy.ARRAY_ACCESS)
val ITERATOR_MISSING by error<FirSourceElement, KtExpression>()
val HAS_NEXT_MISSING by error<FirSourceElement, KtExpression>()
val NEXT_MISSING by error<FirSourceElement, KtExpression>()
val HAS_NEXT_FUNCTION_NONE_APPLICABLE by error<FirSourceElement, KtExpression> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
val NEXT_NONE_APPLICABLE by error<FirSourceElement, KtExpression> {
parameter<Collection<AbstractFirBasedSymbol<*>>>("candidates")
}
}
val TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
@@ -208,6 +208,9 @@ object FirErrors {
// Ambiguity
val OVERLOAD_RESOLUTION_AMBIGUITY by error1<PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val ASSIGN_OPERATOR_AMBIGUITY by error1<PsiElement, Collection<AbstractFirBasedSymbol<*>>>()
val ITERATOR_AMBIGUITY by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val HAS_NEXT_FUNCTION_AMBIGUITY by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val NEXT_AMBIGUITY by error1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
// Types & type parameters
val TYPE_MISMATCH by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
@@ -362,6 +365,7 @@ object FirErrors {
val UNSAFE_IMPLICIT_INVOKE_CALL by error1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNSAFE_INFIX_CALL by error3<KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val UNSAFE_OPERATOR_CALL by error3<KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
val ITERATOR_ON_NULLABLE by error0<FirSourceElement, KtExpression>()
val UNNECESSARY_SAFE_CALL by warning1<PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.SAFE_ACCESS)
val UNEXPECTED_SAFE_CALL by error0<PsiElement>(SourceElementPositioningStrategies.SAFE_ACCESS)
val UNNECESSARY_NOT_NULL_ASSERTION by warning1<KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.OPERATOR)
@@ -382,6 +386,11 @@ object FirErrors {
// Conventions
val NO_GET_METHOD by error0<KtArrayAccessExpression>(SourceElementPositioningStrategies.ARRAY_ACCESS)
val NO_SET_METHOD by error0<KtArrayAccessExpression>(SourceElementPositioningStrategies.ARRAY_ACCESS)
val ITERATOR_MISSING by error0<FirSourceElement, KtExpression>()
val HAS_NEXT_MISSING by error0<FirSourceElement, KtExpression>()
val NEXT_MISSING by error0<FirSourceElement, KtExpression>()
val HAS_NEXT_FUNCTION_NONE_APPLICABLE by error1<FirSourceElement, KtExpression, Collection<AbstractFirBasedSymbol<*>>>()
val NEXT_NONE_APPLICABLE by error1<FirSourceElement, KtExpression, Collection<AbstractFirBasedSymbol<*>>>()
// Type alias
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
@@ -0,0 +1,124 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_NONE_APPLICABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_MISSING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_MISSING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_ON_NULLABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_MISSING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_NONE_APPLICABLE
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableWrongReceiver
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
object FirForLoopChecker : FirBlockChecker() {
override fun check(expression: FirBlock, context: CheckerContext, reporter: DiagnosticReporter) {
val statements = expression.statements
for ((iteratorDeclaration, whileLoop) in statements.windowed(2)) {
if (iteratorDeclaration !is FirProperty) continue
if (whileLoop !is FirWhileLoop) continue
if (iteratorDeclaration.source?.kind != FirFakeSourceElementKind.DesugaredForLoop) continue
val iteratorCall = iteratorDeclaration.initializer as FirFunctionCall
val source = iteratorCall.explicitReceiver?.source ?: iteratorCall.source
if (checkSpecialFunctionCall(
iteratorCall,
reporter,
source,
context,
ITERATOR_AMBIGUITY,
ITERATOR_MISSING,
unsafeCallFactory = ITERATOR_ON_NULLABLE
)
) {
continue
}
val hasNextCall = whileLoop.condition as FirFunctionCall
if (checkSpecialFunctionCall(
hasNextCall,
reporter,
source,
context,
HAS_NEXT_FUNCTION_AMBIGUITY,
HAS_NEXT_MISSING,
noneApplicableFactory = HAS_NEXT_FUNCTION_NONE_APPLICABLE
)
) {
continue
}
val elementDeclaration = whileLoop.block.statements.firstOrNull() as? FirProperty ?: continue
if (elementDeclaration.initializer?.source?.kind != FirFakeSourceElementKind.DesugaredForLoop) continue
val nextCall = elementDeclaration.initializer as FirFunctionCall
checkSpecialFunctionCall(
nextCall,
reporter,
source,
context,
NEXT_AMBIGUITY,
NEXT_MISSING,
noneApplicableFactory = NEXT_NONE_APPLICABLE
)
}
}
private fun checkSpecialFunctionCall(
call: FirFunctionCall,
reporter: DiagnosticReporter,
reportSource: FirSourceElement?,
context: CheckerContext,
ambiguityFactory: FirDiagnosticFactory1<FirSourceElement, PsiElement, Collection<AbstractFirBasedSymbol<*>>>,
missingFactory: FirDiagnosticFactory0<FirSourceElement, KtExpression>,
noneApplicableFactory: FirDiagnosticFactory1<FirSourceElement, KtExpression, Collection<AbstractFirBasedSymbol<*>>>? = null,
unsafeCallFactory: FirDiagnosticFactory0<FirSourceElement, KtExpression>? = null,
): Boolean {
val calleeReference = call.calleeReference
if (calleeReference is FirErrorNamedReference) {
when (val diagnostic = calleeReference.diagnostic) {
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates, context)
} else if (noneApplicableFactory != null) {
reporter.reportOn(reportSource, noneApplicableFactory, diagnostic.candidates, context)
}
is ConeUnresolvedNameError -> {
reporter.reportOn(reportSource, missingFactory, context)
}
is ConeInapplicableCandidateError -> {
if (unsafeCallFactory != null || noneApplicableFactory != null) {
diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.forEach {
if (it is InapplicableWrongReceiver) {
if (unsafeCallFactory != null) {
reporter.reportOn(reportSource, unsafeCallFactory, context)
} else {
reporter.reportOn(reportSource, noneApplicableFactory!!, listOf(diagnostic.candidate.symbol), context)
}
return true
}
}
}
}
}
return true
}
return false
}
}
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
@@ -92,7 +90,8 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) {
return
}
if (source.kind == FirFakeSourceElementKind.ImplicitConstructor) {
if (source.kind == FirFakeSourceElementKind.ImplicitConstructor || source.kind == FirFakeSourceElementKind.DesugaredForLoop) {
// See FirForLoopChecker
return
}
for (coneDiagnostic in diagnostic.toFirDiagnostics(source, qualifiedAccessSource)) {
@@ -110,6 +110,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FORBIDDEN_VARARG_
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.FUN_INTERFACE_CONSTRUCTOR_REFERENCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.GENERIC_THROWABLE_SUBCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.HIDDEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_UNDERSCORE
@@ -134,6 +135,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_B
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LEAKED_IN_PLACE_LAMBDA
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_ANNOTATION_CLASS_ERROR
@@ -152,6 +154,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_N
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_PARAMETER_NOT_FOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NESTED_CLASS_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_AMBIGUITY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NONE_APPLICABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_FINAL_MEMBER_IN_FINAL_CLASS
@@ -439,6 +442,9 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
// Ambiguity
map.put(OVERLOAD_RESOLUTION_AMBIGUITY, "Overload resolution ambiguity between candidates: {0}", SYMBOLS)
map.put(ASSIGN_OPERATOR_AMBIGUITY, "Ambiguity between assign operator candidates: {0}", SYMBOLS)
map.put(ITERATOR_AMBIGUITY, "Method ''iterator()'' is ambiguous for this expression: {0}", SYMBOLS)
map.put(HAS_NEXT_FUNCTION_AMBIGUITY, "Method ''hasNext()'' is ambiguous for this expression: {0}", SYMBOLS)
map.put(NEXT_AMBIGUITY, "Method ''next()'' is ambiguous for this expression: {0}", SYMBOLS)
// Types & type parameters
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING)
@@ -60,4 +60,9 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirReturnAllowedChecker,
FirFunctionReturnTypeMismatchChecker
)
override val blockCheckers: Set<FirBlockChecker>
get() = setOf(
FirForLoopChecker
)
}
@@ -944,13 +944,19 @@ class ExpressionsConverter(
}
}
val fakeSource = forLoop.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
val target: FirLoopTarget
// NB: FirForLoopChecker relies on this block existence and structure
return buildBlock {
source = forLoop.toFirSourceElement()
source = fakeSource
val iteratorVal = generateTemporaryVariable(
this@ExpressionsConverter.baseSession, null, Name.special("<iterator>"),
this@ExpressionsConverter.baseSession, fakeSource, ITERATOR_NAME,
buildFunctionCall {
calleeReference = buildSimpleNamedReference { name = Name.identifier("iterator") }
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = OperatorNameConventions.ITERATOR
}
explicitReceiver = rangeExpression
}
)
@@ -958,8 +964,12 @@ class ExpressionsConverter(
statements += FirWhileLoopBuilder().apply {
source = forLoop.toFirSourceElement()
condition = buildFunctionCall {
calleeReference = buildSimpleNamedReference { name = Name.identifier("hasNext") }
explicitReceiver = generateResolvedAccessExpression(null, iteratorVal)
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = OperatorNameConventions.HAS_NEXT
}
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
}
// break/continue in the for loop condition will refer to an outer loop if any.
// So, prepare the loop target after building the condition.
@@ -975,8 +985,12 @@ class ExpressionsConverter(
this@ExpressionsConverter.baseSession, null,
if (multiDeclaration != null) DESTRUCTURING_NAME else parameter!!.firValueParameter.name,
buildFunctionCall {
calleeReference = buildSimpleNamedReference { name = Name.identifier("next") }
explicitReceiver = generateResolvedAccessExpression(null, iteratorVal)
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = OperatorNameConventions.NEXT
}
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
},
parameter!!.firValueParameter.returnTypeRef
)
@@ -1708,16 +1708,17 @@ open class RawFirBuilder(
val ktParameter = expression.loopParameter
val fakeSource = expression.toFirPsiSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
val target: FirLoopTarget
// NB: FirForLoopChecker relies on this block existence and structure
return buildBlock {
source = fakeSource
val rangeSource = expression.loopRange?.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
val iteratorVal = generateTemporaryVariable(
baseSession, rangeSource, Name.special("<iterator>"),
baseSession, rangeSource, ITERATOR_NAME,
buildFunctionCall {
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = Name.identifier("iterator")
name = OperatorNameConventions.ITERATOR
}
explicitReceiver = rangeExpression
},
@@ -1729,7 +1730,7 @@ open class RawFirBuilder(
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = Name.identifier("hasNext")
name = OperatorNameConventions.HAS_NEXT
}
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
}
@@ -1755,7 +1756,7 @@ open class RawFirBuilder(
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = fakeSource
name = Name.identifier("next")
name = OperatorNameConventions.NEXT
}
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
},
@@ -1207,5 +1207,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val ANONYMOUS_OBJECT_NAME = Name.special("<anonymous>")
val DESTRUCTURING_NAME = Name.special("<destruct>")
val ITERATOR_NAME = Name.special("<iterator>")
}
}
@@ -78,14 +78,14 @@ abstract class NotRange8() {
fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, notRange8: NotRange8, range0: Range0, range1: Range1) {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in notRange1)<!>;
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in notRange2)<!>;
<!UNRESOLVED_REFERENCE!>for (i in notRange3)<!>;
<!UNRESOLVED_REFERENCE!>for (i in notRange4)<!>;
for (i in <!ITERATOR_MISSING!>notRange1<!>);
for (i in <!HAS_NEXT_MISSING!>notRange2<!>);
for (i in <!NEXT_MISSING!>notRange3<!>);
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
for (i in notRange5);
for (i in notRange6);
for (i in notRange7);
<!UNRESOLVED_REFERENCE!>for (i in notRange8)<!>;
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
for (i in range0);
for (i in range1);
+2 -2
View File
@@ -22,11 +22,11 @@ fun testUnresolved() {
is String -> <!UNRESOLVED_REFERENCE!>a<!>
}
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (j in <!UNRESOLVED_REFERENCE!>collection<!>) {
for (j in <!ITERATOR_MISSING, UNRESOLVED_REFERENCE!>collection<!>) {
var i: Int = j
i += 1
foo1(j)
}<!>
}
}
fun foo1(i: Int) {}
@@ -1,22 +0,0 @@
// !WITH_NEW_INFERENCE
// See also KT-7428
class Container<K>(val k: K)
// iterator() must be an extension, otherwise code will not compile
operator fun <K> Container<K>.iterator(): Iterator<K> = null!!
fun test() {
val container: Container<String>? = null
// Error
container<!UNSAFE_CALL!>.<!>iterator()
// for extension iterator, this code compiles, but should not
<!UNSAFE_CALL!>for (s in container) {}<!>
}
class OtherContainer<K>(val k: K) {
operator fun iterator(): Iterator<K> = null!!
}
fun test2() {
val other: OtherContainer<String>? = null
// Error
<!UNSAFE_CALL!>for (s in other) {}<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
// See also KT-7428
class Container<K>(val k: K)
@@ -1,7 +1,7 @@
fun foo1() = <!EXPRESSION_EXPECTED!>while (b()) {}<!>
fun foo2() = <!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in 10) {}<!>
fun foo2() = for (i in <!ITERATOR_MISSING!>10<!>) {}
fun foo3() = when (b()) {
true -> 1
@@ -8,7 +8,7 @@ class It {
}
fun test(c: Coll?) {
<!UNSAFE_CALL!>for (x in c) {}<!>
for (x in <!ITERATOR_ON_NULLABLE!>c<!>) {}
if (c != null) {
for(x in c) {}
@@ -8,5 +8,5 @@ class It {
}
fun test() {
<!UNSAFE_CALL, UNSAFE_CALL!>for (x in Coll()) {}<!>
for (x in <!HAS_NEXT_FUNCTION_NONE_APPLICABLE!>Coll()<!>) {}
}
@@ -1,15 +1,15 @@
// !WITH_NEW_INFERENCE
fun useDeclaredVariables() {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for ((a, b)<!SYNTAX!><!>) {
for ((a, b)<!SYNTAX!><!>) {
a
b
}<!>
}
}
fun checkersShouldRun() {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for ((@A a, _)<!SYNTAX!><!>) {
for ((@A a, _)<!SYNTAX!><!>) {
}<!>
}
}
annotation class A
@@ -11,6 +11,6 @@ fun test(nothing: Nothing?) {
}
fun sum(a : IntArray) : Int {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (n
<!SYNTAX!>return<!><!SYNTAX!><!> "?"<!>
for (n
<!SYNTAX!>return<!><!SYNTAX!><!> "?"
}
@@ -1,8 +1,8 @@
package b
fun foo() {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in <!UNRESOLVED_REFERENCE!>collection<!>) {
for (i in <!ITERATOR_MISSING, UNRESOLVED_REFERENCE!>collection<!>) {
{
break
}
}<!><!SYNTAX!><!>
}<!SYNTAX!><!>
@@ -4,6 +4,6 @@ class X
operator fun <T> X.iterator(): Iterable<T> = TODO()
fun test() {
<!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in X()) {
}<!>
for (i in <!HAS_NEXT_MISSING!>X()<!>) {
}
}
@@ -1,27 +0,0 @@
//KT-1821 Write test for ITERATOR_AMBIGUITY diagnostic
interface MyCollectionInterface {
}
interface MyAnotherCollectionInterface {
}
class MyCollection : MyCollectionInterface, MyAnotherCollectionInterface {
}
fun MyCollectionInterface.iterator() = MyIterator()
fun MyAnotherCollectionInterface.iterator() = MyIterator()
class MyIterator {
fun next() : MyElement = MyElement()
fun hasNext() = true
}
class MyElement
fun test1(collection: MyCollection) {
collection.<!OVERLOAD_RESOLUTION_AMBIGUITY!>iterator<!>()
<!OVERLOAD_RESOLUTION_AMBIGUITY, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (element in collection) {
}<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
//KT-1821 Write test for ITERATOR_AMBIGUITY diagnostic
interface MyCollectionInterface {
@@ -1,28 +0,0 @@
// FILE: J.java
import org.jetbrains.annotations.*;
import java.util.*;
public class J {
@NotNull
public static List<String> staticNN;
@Nullable
public static List<String> staticN;
public static List<String> staticJ;
}
// FILE: k.kt
fun test() {
// @NotNull platform type
val platformNN = J.staticNN
// @Nullable platform type
val platformN = J.staticN
// platform type with no annotation
val platformJ = J.staticJ
for (x in platformNN) {}
<!UNSAFE_CALL!>for (x in platformN) {}<!>
for (x in platformJ) {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: J.java
import org.jetbrains.annotations.*;
@@ -14,8 +14,8 @@ class MyClass {
var res = 0
m = create()
// See KT-7428
<!UNSAFE_CALL!>for ((k, v) in m)
res += (k.length + v.length)<!>
for ((k, v) in <!ITERATOR_ON_NULLABLE!>m<!>)
res += (k.length + v.length)
return res
}
}
@@ -25,7 +25,7 @@ fun whenInContract(x: Any?, boolean: Boolean) {
fun forInContract(x: Any?) {
contract {
<!ERROR_IN_CONTRACT_DESCRIPTION, UNRESOLVED_REFERENCE!>for (i in 0..1) {
<!ERROR_IN_CONTRACT_DESCRIPTION!>for (i in 0..1) {
returns() implies (x is String)
}<!>
}
@@ -23,5 +23,5 @@ typealias C2<T> = JHost.Consumer2<T, T>
val test1 = R { }
val test2 = C<String> { s -> println(s.length) }
val test3 = CStr { s -> <!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }
val test4 = CStrList { ss -> <!OVERLOAD_RESOLUTION_AMBIGUITY, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (s in ss) { <!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) }<!> }
val test4 = CStrList { ss -> for (s in <!ITERATOR_AMBIGUITY!>ss<!>) { <!OVERLOAD_RESOLUTION_AMBIGUITY!>println<!>(s.<!UNRESOLVED_REFERENCE!>length<!>) } }
val test5 = <!INAPPLICABLE_CANDIDATE!>C2<!><Int> { a, b -> val x: Int = a <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> b; println(x)}
@@ -7,7 +7,7 @@
* NOTE: right-hand side of an assignment must be expression
*/
fun case1() {
val x = <!OVERLOAD_RESOLUTION_AMBIGUITY, UNRESOLVED_REFERENCE!>for (<!SYNTAX!><!>) { }<!>
val x = for (<!SYNTAX!><!>) { }
val y = for (x in 1..2) { }
val a = <!EXPRESSION_EXPECTED!>while (<!SYNTAX!><!>) { }<!>
@@ -20,7 +20,7 @@ fun case1() {
* NOTE: right-hand side of an assignment must be expression
*/
fun case2() {
var x = <!OVERLOAD_RESOLUTION_AMBIGUITY, UNRESOLVED_REFERENCE!>for (<!SYNTAX!><!>) { }<!>
var x = for (<!SYNTAX!><!>) { }
var y = for (x in 1..2) { }
var a = <!EXPRESSION_EXPECTED!>while (<!SYNTAX!><!>) { }<!>
@@ -40,7 +40,7 @@ fun case3() {
var b :Any?
var c :Any?
x = <!OVERLOAD_RESOLUTION_AMBIGUITY, UNRESOLVED_REFERENCE!>for (<!SYNTAX!><!>) { }<!>
x = for (<!SYNTAX!><!>) { }
y = for (x in 1..2) { }
a = <!EXPRESSION_EXPECTED!>while (<!SYNTAX!><!>) { }<!>
@@ -823,6 +823,33 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ITERATOR_AMBIGUITY) { firDiagnostic ->
IteratorAmbiguityImpl(
firDiagnostic.a.map { abstractFirBasedSymbol ->
firSymbolBuilder.buildSymbol(abstractFirBasedSymbol.fir as FirDeclaration)
},
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.HAS_NEXT_FUNCTION_AMBIGUITY) { firDiagnostic ->
HasNextFunctionAmbiguityImpl(
firDiagnostic.a.map { abstractFirBasedSymbol ->
firSymbolBuilder.buildSymbol(abstractFirBasedSymbol.fir as FirDeclaration)
},
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.NEXT_AMBIGUITY) { firDiagnostic ->
NextAmbiguityImpl(
firDiagnostic.a.map { abstractFirBasedSymbol ->
firSymbolBuilder.buildSymbol(abstractFirBasedSymbol.fir as FirDeclaration)
},
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.TYPE_MISMATCH) { firDiagnostic ->
TypeMismatchImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
@@ -1704,6 +1731,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ITERATOR_ON_NULLABLE) { firDiagnostic ->
IteratorOnNullableImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.UNNECESSARY_SAFE_CALL) { firDiagnostic ->
UnnecessarySafeCallImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
@@ -1784,6 +1817,42 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ITERATOR_MISSING) { firDiagnostic ->
IteratorMissingImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.HAS_NEXT_MISSING) { firDiagnostic ->
HasNextMissingImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.NEXT_MISSING) { firDiagnostic ->
NextMissingImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.HAS_NEXT_FUNCTION_NONE_APPLICABLE) { firDiagnostic ->
HasNextFunctionNoneApplicableImpl(
firDiagnostic.a.map { abstractFirBasedSymbol ->
firSymbolBuilder.buildSymbol(abstractFirBasedSymbol.fir as FirDeclaration)
},
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.NEXT_NONE_APPLICABLE) { firDiagnostic ->
NextNoneApplicableImpl(
firDiagnostic.a.map { abstractFirBasedSymbol ->
firSymbolBuilder.buildSymbol(abstractFirBasedSymbol.fir as FirDeclaration)
},
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.TOPLEVEL_TYPEALIASES_ONLY) { firDiagnostic ->
ToplevelTypealiasesOnlyImpl(
firDiagnostic as FirPsiDiagnostic<*>,
@@ -588,6 +588,21 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val candidates: List<KtSymbol>
}
abstract class IteratorAmbiguity : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = IteratorAmbiguity::class
abstract val candidates: List<KtSymbol>
}
abstract class HasNextFunctionAmbiguity : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = HasNextFunctionAmbiguity::class
abstract val candidates: List<KtSymbol>
}
abstract class NextAmbiguity : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = NextAmbiguity::class
abstract val candidates: List<KtSymbol>
}
abstract class TypeMismatch : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = TypeMismatch::class
abstract val expectedType: KtType
@@ -1203,6 +1218,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val rhs: KtExpression
}
abstract class IteratorOnNullable : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = IteratorOnNullable::class
}
abstract class UnnecessarySafeCall : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = UnnecessarySafeCall::class
abstract val receiverType: KtType
@@ -1257,6 +1276,28 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = NoSetMethod::class
}
abstract class IteratorMissing : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = IteratorMissing::class
}
abstract class HasNextMissing : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = HasNextMissing::class
}
abstract class NextMissing : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = NextMissing::class
}
abstract class HasNextFunctionNoneApplicable : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = HasNextFunctionNoneApplicable::class
abstract val candidates: List<KtSymbol>
}
abstract class NextNoneApplicable : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = NextNoneApplicable::class
abstract val candidates: List<KtSymbol>
}
abstract class ToplevelTypealiasesOnly : KtFirDiagnostic<KtTypeAlias>() {
override val diagnosticClass get() = ToplevelTypealiasesOnly::class
}
@@ -943,6 +943,30 @@ internal class AssignOperatorAmbiguityImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class IteratorAmbiguityImpl(
override val candidates: List<KtSymbol>,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.IteratorAmbiguity(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class HasNextFunctionAmbiguityImpl(
override val candidates: List<KtSymbol>,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.HasNextFunctionAmbiguity(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NextAmbiguityImpl(
override val candidates: List<KtSymbol>,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NextAmbiguity(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class TypeMismatchImpl(
override val expectedType: KtType,
override val actualType: KtType,
@@ -1948,6 +1972,13 @@ internal class UnsafeOperatorCallImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class IteratorOnNullableImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.IteratorOnNullable(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class UnnecessarySafeCallImpl(
override val receiverType: KtType,
firDiagnostic: FirPsiDiagnostic<*>,
@@ -2038,6 +2069,43 @@ internal class NoSetMethodImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class IteratorMissingImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.IteratorMissing(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class HasNextMissingImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.HasNextMissing(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NextMissingImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NextMissing(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class HasNextFunctionNoneApplicableImpl(
override val candidates: List<KtSymbol>,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.HasNextFunctionNoneApplicable(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class NextNoneApplicableImpl(
override val candidates: List<KtSymbol>,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.NextNoneApplicable(), KtAbstractFirDiagnostic<KtExpression> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ToplevelTypealiasesOnlyImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,