FirForLoopChecker: report also OPERATOR_MODIFIER if appropriate + minor
This commits checks iterator/hasNext/next functions whether they are declared as operator or not. Also, it changes logic of hasNext/next error reporting, now we're able to report errors about both these functions.
This commit is contained in:
+24
-1
@@ -143,6 +143,16 @@ FILE: forLoopChecker.kt
|
|||||||
|
|
||||||
public abstract operator fun next(): R|kotlin/Int|
|
public abstract operator fun next(): R|kotlin/Int|
|
||||||
|
|
||||||
|
}
|
||||||
|
public abstract class ImproperIterator6 : R|kotlin/Any| {
|
||||||
|
public constructor(): R|ImproperIterator6| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract fun hasNext(): R|kotlin/Boolean|
|
||||||
|
|
||||||
|
public abstract fun next(): R|kotlin/Int|
|
||||||
|
|
||||||
}
|
}
|
||||||
public abstract class NotRange8 : R|kotlin/Any| {
|
public abstract class NotRange8 : R|kotlin/Any| {
|
||||||
public constructor(): R|NotRange8| {
|
public constructor(): R|NotRange8| {
|
||||||
@@ -152,7 +162,15 @@ FILE: forLoopChecker.kt
|
|||||||
public abstract operator fun iterator(): R|ImproperIterator5|
|
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| {
|
public abstract class NotRange9 : R|kotlin/Any| {
|
||||||
|
public constructor(): R|NotRange9| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract fun iterator(): R|ImproperIterator6|
|
||||||
|
|
||||||
|
}
|
||||||
|
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|, notRange9: R|NotRange9|, range0: R|Range0|, range1: R|Range1|): R|kotlin/Unit| {
|
||||||
lval <iterator>: R|ERROR CLASS: Unresolved name: iterator| = R|<local>/notRange1|.<Unresolved name: iterator>#()
|
lval <iterator>: R|ERROR CLASS: Unresolved name: iterator| = R|<local>/notRange1|.<Unresolved name: iterator>#()
|
||||||
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
|
while(R|<local>/<iterator>|.<Unresolved name: hasNext>#()) {
|
||||||
lval i: R|ERROR CLASS: Unresolved name: next| = R|<local>/<iterator>|.<Unresolved name: next>#()
|
lval i: R|ERROR CLASS: Unresolved name: next| = R|<local>/<iterator>|.<Unresolved name: next>#()
|
||||||
@@ -193,6 +211,11 @@ FILE: forLoopChecker.kt
|
|||||||
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator5.next|()
|
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator5.next|()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lval <iterator>: R|ImproperIterator6| = R|<local>/notRange9|.R|/NotRange9.iterator|()
|
||||||
|
while(R|<local>/<iterator>|.R|/ImproperIterator6.hasNext|()) {
|
||||||
|
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/ImproperIterator6.next|()
|
||||||
|
}
|
||||||
|
|
||||||
lval <iterator>: R|GoodIterator| = R|<local>/range0|.R|/Range0.iterator|()
|
lval <iterator>: R|GoodIterator| = R|<local>/range0|.R|/Range0.iterator|()
|
||||||
while(R|<local>/<iterator>|.R|/GoodIterator.hasNext|()) {
|
while(R|<local>/<iterator>|.R|/GoodIterator.hasNext|()) {
|
||||||
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/GoodIterator.next|()
|
lval i: R|kotlin/Int| = R|<local>/<iterator>|.R|/GoodIterator.next|()
|
||||||
|
|||||||
+24
-2
@@ -70,20 +70,42 @@ abstract class ImproperIterator5 {
|
|||||||
abstract operator fun next() : Int
|
abstract operator fun next() : Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ImproperIterator6 {
|
||||||
|
abstract fun hasNext() : Boolean
|
||||||
|
abstract fun next() : Int
|
||||||
|
}
|
||||||
|
|
||||||
abstract class NotRange8() {
|
abstract class NotRange8() {
|
||||||
abstract operator fun iterator() : ImproperIterator5
|
abstract operator fun iterator() : ImproperIterator5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class NotRange9() {
|
||||||
|
abstract fun iterator(): ImproperIterator6
|
||||||
|
}
|
||||||
|
|
||||||
fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, notRange8: NotRange8, range0: Range0, range1: Range1) {
|
|
||||||
|
fun test(
|
||||||
|
notRange1: NotRange1,
|
||||||
|
notRange2: NotRange2,
|
||||||
|
notRange3: NotRange3,
|
||||||
|
notRange4: NotRange4,
|
||||||
|
notRange5: NotRange5,
|
||||||
|
notRange6: NotRange6,
|
||||||
|
notRange7: NotRange7,
|
||||||
|
notRange8: NotRange8,
|
||||||
|
notRange9: NotRange9,
|
||||||
|
range0: Range0,
|
||||||
|
range1: Range1
|
||||||
|
) {
|
||||||
for (i in <!ITERATOR_MISSING!>notRange1<!>);
|
for (i in <!ITERATOR_MISSING!>notRange1<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange2<!>);
|
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
||||||
for (i in <!NEXT_MISSING!>notRange3<!>);
|
for (i in <!NEXT_MISSING!>notRange3<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
||||||
for (i in notRange5);
|
for (i in notRange5);
|
||||||
for (i in notRange6);
|
for (i in notRange6);
|
||||||
for (i in notRange7);
|
for (i in notRange7);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange8<!>);
|
||||||
|
for (i in <!OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED, OPERATOR_MODIFIER_REQUIRED!>notRange9<!>);
|
||||||
for (i in range0);
|
for (i in range0);
|
||||||
for (i in range1);
|
for (i in range1);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -185,6 +185,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<KtModifierKeywordToken>("modifier")
|
parameter<KtModifierKeywordToken>("modifier")
|
||||||
parameter<String>("target")
|
parameter<String>("target")
|
||||||
}
|
}
|
||||||
|
val OPERATOR_MODIFIER_REQUIRED by error<FirSourceElement, PsiElement> {
|
||||||
|
parameter<FirNamedFunctionSymbol>("functionSymbol")
|
||||||
|
parameter<String>("name")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val INLINE_CLASSES by object : DiagnosticGroup("Inline classes") {
|
val INLINE_CLASSES by object : DiagnosticGroup("Inline classes") {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
@@ -173,6 +174,7 @@ object FirErrors {
|
|||||||
val INCOMPATIBLE_MODIFIERS by error2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
val INCOMPATIBLE_MODIFIERS by error2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
||||||
val REDUNDANT_OPEN_IN_INTERFACE by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.OPEN_MODIFIER)
|
val REDUNDANT_OPEN_IN_INTERFACE by warning0<KtModifierListOwner>(SourceElementPositioningStrategies.OPEN_MODIFIER)
|
||||||
val WRONG_MODIFIER_TARGET by error2<PsiElement, KtModifierKeywordToken, String>()
|
val WRONG_MODIFIER_TARGET by error2<PsiElement, KtModifierKeywordToken, String>()
|
||||||
|
val OPERATOR_MODIFIER_REQUIRED by error2<FirSourceElement, PsiElement, FirNamedFunctionSymbol, String>()
|
||||||
|
|
||||||
// Inline classes
|
// Inline classes
|
||||||
val INLINE_CLASS_NOT_TOP_LEVEL by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
|
val INLINE_CLASS_NOT_TOP_LEVEL by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
|
||||||
|
|||||||
+49
-33
@@ -19,16 +19,20 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_ON_NULLA
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_AMBIGUITY
|
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_MISSING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_NONE_APPLICABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_NONE_APPLICABLE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_MODIFIER_REQUIRED
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.isOperator
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
|
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableWrongReceiver
|
import org.jetbrains.kotlin.fir.resolve.calls.InapplicableWrongReceiver
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
|
|
||||||
@@ -54,18 +58,15 @@ object FirForLoopChecker : FirBlockChecker() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val hasNextCall = whileLoop.condition as FirFunctionCall
|
val hasNextCall = whileLoop.condition as FirFunctionCall
|
||||||
if (checkSpecialFunctionCall(
|
checkSpecialFunctionCall(
|
||||||
hasNextCall,
|
hasNextCall,
|
||||||
reporter,
|
reporter,
|
||||||
source,
|
source,
|
||||||
context,
|
context,
|
||||||
HAS_NEXT_FUNCTION_AMBIGUITY,
|
HAS_NEXT_FUNCTION_AMBIGUITY,
|
||||||
HAS_NEXT_MISSING,
|
HAS_NEXT_MISSING,
|
||||||
noneApplicableFactory = HAS_NEXT_FUNCTION_NONE_APPLICABLE
|
noneApplicableFactory = HAS_NEXT_FUNCTION_NONE_APPLICABLE
|
||||||
)
|
)
|
||||||
) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val elementDeclaration = whileLoop.block.statements.firstOrNull() as? FirProperty ?: continue
|
val elementDeclaration = whileLoop.block.statements.firstOrNull() as? FirProperty ?: continue
|
||||||
if (elementDeclaration.initializer?.source?.kind != FirFakeSourceElementKind.DesugaredForLoop) continue
|
if (elementDeclaration.initializer?.source?.kind != FirFakeSourceElementKind.DesugaredForLoop) continue
|
||||||
val nextCall = elementDeclaration.initializer as FirFunctionCall
|
val nextCall = elementDeclaration.initializer as FirFunctionCall
|
||||||
@@ -91,33 +92,48 @@ object FirForLoopChecker : FirBlockChecker() {
|
|||||||
noneApplicableFactory: FirDiagnosticFactory1<FirSourceElement, KtExpression, Collection<AbstractFirBasedSymbol<*>>>? = null,
|
noneApplicableFactory: FirDiagnosticFactory1<FirSourceElement, KtExpression, Collection<AbstractFirBasedSymbol<*>>>? = null,
|
||||||
unsafeCallFactory: FirDiagnosticFactory0<FirSourceElement, KtExpression>? = null,
|
unsafeCallFactory: FirDiagnosticFactory0<FirSourceElement, KtExpression>? = null,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val calleeReference = call.calleeReference
|
when (val calleeReference = call.calleeReference) {
|
||||||
if (calleeReference is FirErrorNamedReference) {
|
is FirErrorNamedReference -> {
|
||||||
when (val diagnostic = calleeReference.diagnostic) {
|
when (val diagnostic = calleeReference.diagnostic) {
|
||||||
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
|
is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) {
|
||||||
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates, context)
|
reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates, context)
|
||||||
} else if (noneApplicableFactory != null) {
|
} else if (noneApplicableFactory != null) {
|
||||||
reporter.reportOn(reportSource, noneApplicableFactory, diagnostic.candidates, context)
|
reporter.reportOn(reportSource, noneApplicableFactory, diagnostic.candidates, context)
|
||||||
}
|
}
|
||||||
is ConeUnresolvedNameError -> {
|
is ConeUnresolvedNameError -> {
|
||||||
reporter.reportOn(reportSource, missingFactory, context)
|
reporter.reportOn(reportSource, missingFactory, context)
|
||||||
}
|
}
|
||||||
is ConeInapplicableCandidateError -> {
|
is ConeInapplicableCandidateError -> {
|
||||||
if (unsafeCallFactory != null || noneApplicableFactory != null) {
|
if (unsafeCallFactory != null || noneApplicableFactory != null) {
|
||||||
diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.forEach {
|
diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.forEach {
|
||||||
if (it is InapplicableWrongReceiver) {
|
if (it is InapplicableWrongReceiver) {
|
||||||
if (unsafeCallFactory != null) {
|
if (unsafeCallFactory != null) {
|
||||||
reporter.reportOn(reportSource, unsafeCallFactory, context)
|
reporter.reportOn(
|
||||||
} else {
|
reportSource, unsafeCallFactory, context
|
||||||
reporter.reportOn(reportSource, noneApplicableFactory!!, listOf(diagnostic.candidate.symbol), context)
|
)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(
|
||||||
|
reportSource, noneApplicableFactory!!, listOf(diagnostic.candidate.symbol), context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
is FirResolvedNamedReference -> {
|
||||||
|
val symbol = calleeReference.resolvedSymbol
|
||||||
|
if (symbol is FirNamedFunctionSymbol) {
|
||||||
|
val function = symbol.fir
|
||||||
|
if (!function.isOperator) {
|
||||||
|
reporter.reportOn(reportSource, OPERATOR_MODIFIER_REQUIRED, symbol, function.name.asString(), context)
|
||||||
|
// Don't return true as we want to report other errors
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ 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) {
|
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 <!ITERATOR_MISSING!>notRange1<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange2<!>);
|
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>);
|
||||||
for (i in <!NEXT_MISSING!>notRange3<!>);
|
for (i in <!NEXT_MISSING!>notRange3<!>);
|
||||||
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
for (i in <!HAS_NEXT_MISSING!>notRange4<!>);
|
||||||
for (i in notRange5);
|
for (i in notRange5);
|
||||||
|
|||||||
+28
-1
@@ -111,4 +111,31 @@ fun test2() {
|
|||||||
Anc() + Anc()
|
Anc() + Anc()
|
||||||
Anc() - Anc()
|
Anc() - Anc()
|
||||||
Anc2() + Anc2()
|
Anc2() + Anc2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int.iterator(): MyIntIterator = null!!
|
||||||
|
|
||||||
|
operator fun Double.iterator(): MyDoubleIterator = null!!
|
||||||
|
|
||||||
|
operator fun Boolean.iterator(): MyBooleanIterator = null!!
|
||||||
|
|
||||||
|
interface MyIntIterator {
|
||||||
|
operator fun hasNext(): Boolean
|
||||||
|
operator fun next(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyDoubleIterator {
|
||||||
|
operator fun hasNext(): Boolean
|
||||||
|
fun next(): Double
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyBooleanIterator {
|
||||||
|
fun hasNext(): Boolean
|
||||||
|
operator fun next(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(i: Int, d: Double, b: Boolean) {
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>i<!>) {}
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>d<!>) {}
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>b<!>) {}
|
||||||
|
}
|
||||||
|
|||||||
+28
-1
@@ -111,4 +111,31 @@ fun test2() {
|
|||||||
Anc() + Anc()
|
Anc() + Anc()
|
||||||
Anc() <!OPERATOR_MODIFIER_REQUIRED!>-<!> Anc()
|
Anc() <!OPERATOR_MODIFIER_REQUIRED!>-<!> Anc()
|
||||||
Anc2() + Anc2()
|
Anc2() + Anc2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int.iterator(): MyIntIterator = null!!
|
||||||
|
|
||||||
|
operator fun Double.iterator(): MyDoubleIterator = null!!
|
||||||
|
|
||||||
|
operator fun Boolean.iterator(): MyBooleanIterator = null!!
|
||||||
|
|
||||||
|
interface MyIntIterator {
|
||||||
|
operator fun hasNext(): Boolean
|
||||||
|
operator fun next(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyDoubleIterator {
|
||||||
|
operator fun hasNext(): Boolean
|
||||||
|
fun next(): Double
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MyBooleanIterator {
|
||||||
|
fun hasNext(): Boolean
|
||||||
|
operator fun next(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(i: Int, d: Double, b: Boolean) {
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>i<!>) {}
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>d<!>) {}
|
||||||
|
for (element in <!OPERATOR_MODIFIER_REQUIRED!>b<!>) {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ package
|
|||||||
|
|
||||||
public fun test(): kotlin.Unit
|
public fun test(): kotlin.Unit
|
||||||
public fun test2(): kotlin.Unit
|
public fun test2(): kotlin.Unit
|
||||||
|
public fun test3(/*0*/ i: kotlin.Int, /*1*/ d: kotlin.Double, /*2*/ b: kotlin.Boolean): kotlin.Unit
|
||||||
|
public operator fun kotlin.Boolean.iterator(): MyBooleanIterator
|
||||||
|
public operator fun kotlin.Double.iterator(): MyDoubleIterator
|
||||||
|
public fun kotlin.Int.iterator(): MyIntIterator
|
||||||
|
|
||||||
public open class Anc : Base {
|
public open class Anc : Base {
|
||||||
public constructor Anc()
|
public constructor Anc()
|
||||||
@@ -65,3 +69,28 @@ public final class Example2 {
|
|||||||
public final operator fun rangeTo(/*0*/ o: Example2): Example2
|
public final operator fun rangeTo(/*0*/ o: Example2): Example2
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface MyBooleanIterator {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun hasNext(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract operator fun next(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MyDoubleIterator {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract operator fun hasNext(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract fun next(): kotlin.Double
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MyIntIterator {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract operator fun hasNext(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public abstract operator fun next(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
class Coll {
|
|
||||||
operator fun iterator(): It? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
class It {
|
|
||||||
operator fun next() = 1
|
|
||||||
operator fun hasNext() = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
for (x in <!HAS_NEXT_FUNCTION_NONE_APPLICABLE!>Coll()<!>) {}
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class Coll {
|
class Coll {
|
||||||
operator fun iterator(): It? = null
|
operator fun iterator(): It? = null
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ class X
|
|||||||
operator fun <T> X.iterator(): Iterable<T> = TODO()
|
operator fun <T> X.iterator(): Iterable<T> = TODO()
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
for (i in <!HAS_NEXT_MISSING!>X()<!>) {
|
for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>X()<!>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -186,6 +186,11 @@ private object FirToKtConversionCreator {
|
|||||||
KtSymbol::class.createType(),
|
KtSymbol::class.createType(),
|
||||||
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration")
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirDeclaration")
|
||||||
),
|
),
|
||||||
|
FirNamedFunctionSymbol::class to HLFunctionCallConversion(
|
||||||
|
"firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol({0}.fir)",
|
||||||
|
KtFunctionLikeSymbol::class.createType(),
|
||||||
|
importsToAdd = listOf("org.jetbrains.kotlin.fir.declarations.FirSimpleFunction")
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val allowedTypesWithoutTypeParams = setOf(
|
private val allowedTypesWithoutTypeParams = setOf(
|
||||||
|
|||||||
+9
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
@@ -630,6 +631,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.OPERATOR_MODIFIER_REQUIRED) { firDiagnostic ->
|
||||||
|
OperatorModifierRequiredImpl(
|
||||||
|
firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firDiagnostic.a.fir),
|
||||||
|
firDiagnostic.b,
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INLINE_CLASS_NOT_TOP_LEVEL) { firDiagnostic ->
|
add(FirErrors.INLINE_CLASS_NOT_TOP_LEVEL) { firDiagnostic ->
|
||||||
InlineClassNotTopLevelImpl(
|
InlineClassNotTopLevelImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic<*>,
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
|||||||
+7
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnosticWithPsi
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
|
||||||
@@ -459,6 +460,12 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val target: String
|
abstract val target: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class OperatorModifierRequired : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = OperatorModifierRequired::class
|
||||||
|
abstract val functionSymbol: KtFunctionLikeSymbol
|
||||||
|
abstract val name: String
|
||||||
|
}
|
||||||
|
|
||||||
abstract class InlineClassNotTopLevel : KtFirDiagnostic<KtDeclaration>() {
|
abstract class InlineClassNotTopLevel : KtFirDiagnostic<KtDeclaration>() {
|
||||||
override val diagnosticClass get() = InlineClassNotTopLevel::class
|
override val diagnosticClass get() = InlineClassNotTopLevel::class
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableLikeSymbol
|
||||||
@@ -727,6 +728,15 @@ internal class WrongModifierTargetImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class OperatorModifierRequiredImpl(
|
||||||
|
override val functionSymbol: KtFunctionLikeSymbol,
|
||||||
|
override val name: String,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.OperatorModifierRequired(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class InlineClassNotTopLevelImpl(
|
internal class InlineClassNotTopLevelImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user