Reserve yield if it isn't function call.
This commit is contained in:
@@ -702,7 +702,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<KtExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_PD_METHOD_NONE_APPLICABLE = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<KtExpression, String, Collection<? extends ResolvedCall<?>>> DELEGATE_PD_METHOD_NONE_APPLICABLE = DiagnosticFactory2.create(WARNING);
|
||||||
|
|
||||||
DiagnosticFactory1<KtSimpleNameExpression, KotlinType> COMPARE_TO_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<KtSimpleNameExpression, KotlinType> COMPARE_TO_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR);
|
||||||
|
DiagnosticFactory1<PsiElement, String> YIELD_IS_RESERVED = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> UNDERSCORE_IS_RESERVED = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<PsiElement> UNDERSCORE_IS_RESERVED = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, String> INVALID_CHARACTERS = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, String> INVALID_CHARACTERS = DiagnosticFactory1.create(ERROR);
|
||||||
|
|
||||||
|
|||||||
+1
@@ -463,6 +463,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(COMPARE_TO_TYPE_MISMATCH, "''compareTo()'' must return Int, but returns {0}", RENDER_TYPE);
|
MAP.put(COMPARE_TO_TYPE_MISMATCH, "''compareTo()'' must return Int, but returns {0}", RENDER_TYPE);
|
||||||
|
|
||||||
MAP.put(UNDERSCORE_IS_RESERVED, "Names _, __, ___, ..., are reserved in Kotlin");
|
MAP.put(UNDERSCORE_IS_RESERVED, "Names _, __, ___, ..., are reserved in Kotlin");
|
||||||
|
MAP.put(YIELD_IS_RESERVED, "{0}", STRING);
|
||||||
MAP.put(INVALID_CHARACTERS, "Name {0}", STRING);
|
MAP.put(INVALID_CHARACTERS, "Name {0}", STRING);
|
||||||
|
|
||||||
MAP.put(INAPPLICABLE_OPERATOR_MODIFIER, "''operator'' modifier is inapplicable on this function: {0}", STRING);
|
MAP.put(INAPPLICABLE_OPERATOR_MODIFIER, "''operator'' modifier is inapplicable on this function: {0}", STRING);
|
||||||
|
|||||||
@@ -461,6 +461,25 @@ fun checkReservedPrefixWord(sink: DiagnosticSink, element: PsiElement, word: Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun checkReservedYield(expression: KtSimpleNameExpression?, sink: DiagnosticSink) {
|
||||||
|
// do not force identifier calculation for elements from stubs.
|
||||||
|
if (expression?.getReferencedName() != "yield") return
|
||||||
|
|
||||||
|
val identifier = expression.getIdentifier() ?: return
|
||||||
|
|
||||||
|
if (identifier.node.elementType == KtTokens.IDENTIFIER && "yield" == identifier.text) {
|
||||||
|
sink.report(Errors.YIELD_IS_RESERVED.on(identifier, "Identifier 'yield' is reserved. You ca call it via `yield`"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val MESSAGE_FOR_YIELD_BEFORE_LAMBDA = "Reserved yield block/lambda. Use 'yield() { ... }' or 'yield(fun...)'"
|
||||||
|
|
||||||
|
fun checkReservedYieldBeforeLambda(element: PsiElement, sink: DiagnosticSink) {
|
||||||
|
KtPsiUtil.getPreviousWord(element, "yield")?.let {
|
||||||
|
sink.report(Errors.YIELD_IS_RESERVED.on(it, MESSAGE_FOR_YIELD_BEFORE_LAMBDA))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun KtElement.nonStaticOuterClasses(): Sequence<KtClass> {
|
fun KtElement.nonStaticOuterClasses(): Sequence<KtClass> {
|
||||||
return generateSequence(containingClass()) { if (it.isInner()) it.containingClass() else null }
|
return generateSequence(containingClass()) { if (it.isInner()) it.containingClass() else null }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
|
||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||||
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
|
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
|
||||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||||
@@ -227,6 +228,8 @@ class TypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val referenceExpression = type.referenceExpression ?: return
|
val referenceExpression = type.referenceExpression ?: return
|
||||||
|
|
||||||
|
checkReservedYield(referenceExpression, c.trace)
|
||||||
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifier)
|
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifier)
|
||||||
|
|
||||||
result = resolveTypeForClassifier(c, classifier, qualifierResolutionResult, type, annotations)
|
result = resolveTypeForClassifier(c, classifier, qualifierResolutionResult, type, annotations)
|
||||||
|
|||||||
+4
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
|||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.OverrideResolver;
|
import org.jetbrains.kotlin.resolve.OverrideResolver;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||||
@@ -185,7 +186,9 @@ public class ValueArgumentsToParametersMapper {
|
|||||||
ValueArgumentName argumentName = argument.getArgumentName();
|
ValueArgumentName argumentName = argument.getArgumentName();
|
||||||
assert argumentName != null;
|
assert argumentName != null;
|
||||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(argumentName.getAsName());
|
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(argumentName.getAsName());
|
||||||
KtReferenceExpression nameReference = argumentName.getReferenceExpression();
|
KtSimpleNameExpression nameReference = argumentName.getReferenceExpression();
|
||||||
|
|
||||||
|
KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace());
|
||||||
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
||||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||||
nameReference,
|
nameReference,
|
||||||
|
|||||||
+4
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
@@ -162,6 +163,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext context) {
|
public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||||
|
KtPsiUtilKt.checkReservedYield(expression, context.trace);
|
||||||
|
|
||||||
// TODO : other members
|
// TODO : other members
|
||||||
// TODO : type substitutions???
|
// TODO : type substitutions???
|
||||||
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
||||||
@@ -942,6 +945,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
boolean isStatement
|
boolean isStatement
|
||||||
) {
|
) {
|
||||||
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
||||||
|
KtPsiUtilKt.checkReservedYield(labelExpression, context.trace);
|
||||||
if (labelExpression != null) {
|
if (labelExpression != null) {
|
||||||
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
||||||
UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace, components.languageVersionSettings);
|
UnderscoreChecker.INSTANCE.checkIdentifier(labelIdentifier, context.trace, components.languageVersionSettings);
|
||||||
|
|||||||
+3
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||||
@@ -632,6 +633,8 @@ class DoubleColonExpressionResolver(
|
|||||||
outerContext: ResolutionContext<*>,
|
outerContext: ResolutionContext<*>,
|
||||||
resolutionMode: ResolveArgumentsMode
|
resolutionMode: ResolveArgumentsMode
|
||||||
): OverloadResolutionResults<CallableDescriptor>? {
|
): OverloadResolutionResults<CallableDescriptor>? {
|
||||||
|
checkReservedYield(reference, outerContext.trace)
|
||||||
|
|
||||||
// we should preserve information about `call` because callable references are analyzed two times,
|
// we should preserve information about `call` because callable references are analyzed two times,
|
||||||
// otherwise there will be not completed calls in trace
|
// otherwise there will be not completed calls in trace
|
||||||
val call = outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
val call = outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.types.expressions
|
package org.jetbrains.kotlin.types.expressions
|
||||||
|
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.*
|
import org.jetbrains.kotlin.builtins.*
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
@@ -27,6 +28,8 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
|||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.checkReservedPrefixWord
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYieldBeforeLambda
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
||||||
@@ -137,6 +140,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? {
|
override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? {
|
||||||
|
checkReservedYieldBeforeLambda(expression, context.trace)
|
||||||
if (!expression.functionLiteral.hasBody()) return null
|
if (!expression.functionLiteral.hasBody()) return null
|
||||||
|
|
||||||
val expectedType = context.expectedType
|
val expectedType = context.expectedType
|
||||||
@@ -160,6 +164,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression)
|
return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkReservedYield(context: ExpressionTypingContext, expression: PsiElement) {
|
||||||
|
checkReservedPrefixWord(context.trace, expression, "yield", "yield block/lambda. Use 'yield() { ... }' or 'yield(fun...)'")
|
||||||
|
}
|
||||||
|
|
||||||
private fun createFunctionLiteralDescriptor(
|
private fun createFunctionLiteralDescriptor(
|
||||||
expression: KtLambdaExpression,
|
expression: KtLambdaExpression,
|
||||||
context: ExpressionTypingContext
|
context: ExpressionTypingContext
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
||||||
@@ -138,6 +139,8 @@ public class LabelResolver {
|
|||||||
@NotNull ResolutionContext context
|
@NotNull ResolutionContext context
|
||||||
) {
|
) {
|
||||||
KtSimpleNameExpression labelElement = expression.getTargetLabel();
|
KtSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||||
|
KtPsiUtilKt.checkReservedYield(labelElement, context.trace);
|
||||||
|
|
||||||
Name labelName = expression.getLabelNameAsName();
|
Name labelName = expression.getLabelNameAsName();
|
||||||
if (labelElement == null || labelName == null) return null;
|
if (labelElement == null || labelName == null) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION -UNREACHABLE_CODE -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
package p1.yield
|
||||||
|
|
||||||
|
import p1.yield.yield
|
||||||
|
import p1.yield.foo
|
||||||
|
|
||||||
|
val yield = 5
|
||||||
|
fun foo(){}
|
||||||
|
|
||||||
|
fun bar(yield: Int = 4) {}
|
||||||
|
|
||||||
|
fun yield(yield: Int) {
|
||||||
|
"$<!YIELD_IS_RESERVED!>yield<!>"
|
||||||
|
"${<!YIELD_IS_RESERVED!>yield<!>}"
|
||||||
|
|
||||||
|
<!YIELD_IS_RESERVED!>yield<!>
|
||||||
|
val foo = <!YIELD_IS_RESERVED!>yield<!> + <!YIELD_IS_RESERVED!>yield<!>
|
||||||
|
val foo2 = <!YIELD_IS_RESERVED!>yield<!>
|
||||||
|
|
||||||
|
bar(<!YIELD_IS_RESERVED!>yield<!> = 5)
|
||||||
|
|
||||||
|
yield(4)
|
||||||
|
<!YIELD_IS_RESERVED!>yield<!> {}
|
||||||
|
|
||||||
|
class yield<T: <!YIELD_IS_RESERVED!>yield<!><T>>
|
||||||
|
|
||||||
|
return@<!YIELD_IS_RESERVED!>yield<!>
|
||||||
|
return@<!YIELD_IS_RESERVED!>yield<!> Unit
|
||||||
|
|
||||||
|
val foo5: <!YIELD_IS_RESERVED!>yield<!><*>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun yield(i: (Int) -> Unit) {}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
package p2.yield
|
||||||
|
|
||||||
|
import p2.yield.yield
|
||||||
|
import p2.yield.foo
|
||||||
|
|
||||||
|
val yield = 5
|
||||||
|
fun foo(){}
|
||||||
|
|
||||||
|
fun bar(yield: Int = 4) {}
|
||||||
|
|
||||||
|
fun yield(yield: Int) {
|
||||||
|
"$`yield`"
|
||||||
|
"${`yield`}"
|
||||||
|
|
||||||
|
`yield`
|
||||||
|
val foo = `yield` + `yield`
|
||||||
|
val foo2 = `yield`
|
||||||
|
|
||||||
|
bar(`yield` = 5)
|
||||||
|
|
||||||
|
`yield`(4)
|
||||||
|
`yield` {}
|
||||||
|
|
||||||
|
class `yield`<T: `yield`<T>>
|
||||||
|
|
||||||
|
return@`yield`
|
||||||
|
return@`yield` Unit
|
||||||
|
|
||||||
|
val foo5: `yield`<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun yield(i: (Int) -> Unit) {}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
package p1 {
|
||||||
|
|
||||||
|
package p1.yield {
|
||||||
|
public val yield: kotlin.Int = 5
|
||||||
|
public fun bar(/*0*/ yield: kotlin.Int = ...): kotlin.Unit
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
|
public fun yield(/*0*/ i: (kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun yield(/*0*/ yield: kotlin.Int): kotlin.Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package p2 {
|
||||||
|
|
||||||
|
package p2.yield {
|
||||||
|
public val yield: kotlin.Int = 5
|
||||||
|
public fun bar(/*0*/ yield: kotlin.Int = ...): kotlin.Unit
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
|
public fun yield(/*0*/ i: (kotlin.Int) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun yield(/*0*/ yield: kotlin.Int): kotlin.Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION -UNREACHABLE_CODE -UNUSED_VARIABLE -WRONG_ANNOTATION_TARGET -UNUSED_LAMBDA_EXPRESSION
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
annotation class yield
|
||||||
|
|
||||||
|
fun bar(p: Int) {
|
||||||
|
<!YIELD_IS_RESERVED!>yield<!>@ p
|
||||||
|
`yield`@ p
|
||||||
|
|
||||||
|
@<!YIELD_IS_RESERVED!>yield<!>() p
|
||||||
|
@`yield`() p
|
||||||
|
|
||||||
|
for (yield in 1..5) {
|
||||||
|
|
||||||
|
}
|
||||||
|
{ yield: Int -> }
|
||||||
|
|
||||||
|
val (yield) = listOf(4)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> listOf(vararg e: T): List<T> = null!!
|
||||||
|
operator fun <T> List<T>.component1() = get(0)
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
package p3
|
||||||
|
|
||||||
|
enum class yield {
|
||||||
|
yield
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f1(yield: Int, foo: Int = <!YIELD_IS_RESERVED!>yield<!>) {}
|
||||||
|
|
||||||
|
fun f2(foo: <!YIELD_IS_RESERVED!>yield<!>) {}
|
||||||
|
|
||||||
|
// FILE: 3.kt
|
||||||
|
package p4
|
||||||
|
|
||||||
|
typealias yield = Number
|
||||||
|
|
||||||
|
fun <yield: Number> f1() {}
|
||||||
|
fun <y: <!YIELD_IS_RESERVED!>yield<!>> f2() {}
|
||||||
|
|
||||||
|
// FILE: 4.kt
|
||||||
|
object X {
|
||||||
|
fun yield() {}
|
||||||
|
|
||||||
|
fun test3(yield: Int) {
|
||||||
|
X::<!YIELD_IS_RESERVED!>yield<!>
|
||||||
|
|
||||||
|
<!YIELD_IS_RESERVED!>yield<!>::toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun bar(/*0*/ p: kotlin.Int): kotlin.Unit
|
||||||
|
public fun </*0*/ T> listOf(/*0*/ vararg e: T /*kotlin.Array<out T>*/): kotlin.collections.List<T>
|
||||||
|
public operator fun </*0*/ T> kotlin.collections.List<T>.component1(): T
|
||||||
|
|
||||||
|
public object X {
|
||||||
|
private constructor X()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final fun test3(/*0*/ yield: kotlin.Int): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
public final fun yield(): kotlin.Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
public final annotation class yield : kotlin.Annotation {
|
||||||
|
public constructor yield()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
package p3 {
|
||||||
|
public fun f1(/*0*/ yield: kotlin.Int, /*1*/ foo: kotlin.Int = ...): kotlin.Unit
|
||||||
|
public fun f2(/*0*/ foo: p3.yield): kotlin.Unit
|
||||||
|
|
||||||
|
public final enum class yield : kotlin.Enum<p3.yield> {
|
||||||
|
enum entry yield
|
||||||
|
|
||||||
|
private constructor yield()
|
||||||
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: p3.yield): kotlin.Int
|
||||||
|
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||||
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<p3.yield!>!
|
||||||
|
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): p3.yield
|
||||||
|
public final /*synthesized*/ fun values(): kotlin.Array<p3.yield>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package p4 {
|
||||||
|
public fun </*0*/ yield : kotlin.Number> f1(): kotlin.Unit
|
||||||
|
public fun </*0*/ y : p4.yield /* = kotlin.Number */> f2(): kotlin.Unit
|
||||||
|
public typealias yield = kotlin.Number
|
||||||
|
}
|
||||||
@@ -596,6 +596,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ReserveYield.kt")
|
||||||
|
public void testReserveYield() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ReserveYield.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ReserveYield2.kt")
|
||||||
|
public void testReserveYield2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ReserveYield2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ResolveOfJavaGenerics.kt")
|
@TestMetadata("ResolveOfJavaGenerics.kt")
|
||||||
public void testResolveOfJavaGenerics() throws Exception {
|
public void testResolveOfJavaGenerics() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ResolveOfJavaGenerics.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ResolveOfJavaGenerics.kt");
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ class KotlinCleanupInspection : LocalInspectionTool(), CleanupLocalInspectionToo
|
|||||||
Errors.DEPRECATED_TYPE_PARAMETER_SYNTAX,
|
Errors.DEPRECATED_TYPE_PARAMETER_SYNTAX,
|
||||||
Errors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS,
|
Errors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS,
|
||||||
Errors.COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT,
|
Errors.COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT,
|
||||||
ErrorsJs.WRONG_EXTERNAL_DECLARATION
|
ErrorsJs.WRONG_EXTERNAL_DECLARATION,
|
||||||
|
Errors.YIELD_IS_RESERVED
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun Diagnostic.isObsoleteLabel(): Boolean {
|
private fun Diagnostic.isObsoleteLabel(): Boolean {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.quickfix
|
|||||||
|
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementAsConstructorParameter
|
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementAsConstructorParameter
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
||||||
@@ -478,5 +479,6 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
EXPERIMENTAL_FEATURE_WARNING.registerFactory(ChangeCoroutineSupportFix)
|
EXPERIMENTAL_FEATURE_WARNING.registerFactory(ChangeCoroutineSupportFix)
|
||||||
|
|
||||||
UNRESOLVED_REFERENCE.registerFactory(CreateLabelFix)
|
UNRESOLVED_REFERENCE.registerFactory(CreateLabelFix)
|
||||||
|
YIELD_IS_RESERVED.registerFactory(UnsupportedYieldFix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.MESSAGE_FOR_YIELD_BEFORE_LAMBDA
|
||||||
|
|
||||||
|
class UnsupportedYieldFix(psiElement: PsiElement): KotlinQuickFixAction<PsiElement>(psiElement), CleanupFix {
|
||||||
|
override fun getFamilyName(): String = "Migrate unsupported yield syntax"
|
||||||
|
override fun getText(): String = familyName
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
|
val psiElement = element ?: return
|
||||||
|
|
||||||
|
if (psiElement is KtCallExpression) {
|
||||||
|
val ktExpression = (psiElement as KtCallElement).calleeExpression ?: return
|
||||||
|
|
||||||
|
// Add after "yield" reference in call
|
||||||
|
psiElement.addAfter(KtPsiFactory(psiElement).createCallArguments("()"), ktExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psiElement.node.elementType == KtTokens.IDENTIFIER) {
|
||||||
|
psiElement.replace(KtPsiFactory(psiElement).createIdentifier("`yield`"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : KotlinSingleIntentionActionFactory() {
|
||||||
|
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
|
if (diagnostic.psiElement.text != "yield") return null
|
||||||
|
|
||||||
|
val message = Errors.YIELD_IS_RESERVED.cast(diagnostic).a
|
||||||
|
if (message == MESSAGE_FOR_YIELD_BEFORE_LAMBDA) {
|
||||||
|
// Identifier -> Expression -> Call (normal call) or Identifier -> Operation Reference -> Binary Expression (for infix usage)
|
||||||
|
val grand = diagnostic.psiElement.parent.parent
|
||||||
|
if (grand is KtBinaryExpression || grand is KtCallExpression) {
|
||||||
|
return UnsupportedYieldFix(grand)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return UnsupportedYieldFix(diagnostic.psiElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -67,3 +67,48 @@ val x = C() willBeInfix 1
|
|||||||
fun infixTest() {
|
fun infixTest() {
|
||||||
arrayListOf(1, 2, 3) map { it }
|
arrayListOf(1, 2, 3) map { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun bar(yield: Int = 4) {}
|
||||||
|
|
||||||
|
fun yield(yield: Int) {
|
||||||
|
"$yield"
|
||||||
|
"${yield}"
|
||||||
|
|
||||||
|
yield
|
||||||
|
val foo = yield + yield
|
||||||
|
val foo2 = yield
|
||||||
|
|
||||||
|
bar(yield = 5)
|
||||||
|
|
||||||
|
yield(4)
|
||||||
|
yield {}
|
||||||
|
|
||||||
|
class yield<T: yield<T>>
|
||||||
|
|
||||||
|
return@yield
|
||||||
|
return@yield Unit
|
||||||
|
|
||||||
|
val foo5: yield<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun yield(i: (Int) -> Unit) {}
|
||||||
|
|
||||||
|
annotation class yield
|
||||||
|
|
||||||
|
@yield()
|
||||||
|
fun test2(p: Int) {
|
||||||
|
yield@ p
|
||||||
|
|
||||||
|
@yield fun f() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
object X {
|
||||||
|
fun yield() {}
|
||||||
|
|
||||||
|
fun test3(yield: Int) {
|
||||||
|
X::yield
|
||||||
|
|
||||||
|
yield::toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -66,3 +66,48 @@ val x = C() willBeInfix 1
|
|||||||
fun infixTest() {
|
fun infixTest() {
|
||||||
arrayListOf(1, 2, 3).map { it }
|
arrayListOf(1, 2, 3).map { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun bar(yield: Int = 4) {}
|
||||||
|
|
||||||
|
fun yield(yield: Int) {
|
||||||
|
"$`yield`"
|
||||||
|
"${`yield`}"
|
||||||
|
|
||||||
|
`yield`
|
||||||
|
val foo = `yield` + `yield`
|
||||||
|
val foo2 = `yield`
|
||||||
|
|
||||||
|
bar(`yield` = 5)
|
||||||
|
|
||||||
|
yield(4)
|
||||||
|
yield() {}
|
||||||
|
|
||||||
|
class yield<T: `yield`<T>>
|
||||||
|
|
||||||
|
return@`yield`
|
||||||
|
return@`yield` Unit
|
||||||
|
|
||||||
|
val foo5: `yield`<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun yield(i: (Int) -> Unit) {}
|
||||||
|
|
||||||
|
annotation class yield
|
||||||
|
|
||||||
|
@`yield`()
|
||||||
|
fun test2(p: Int) {
|
||||||
|
`yield`@ p
|
||||||
|
|
||||||
|
@`yield` fun f() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
object X {
|
||||||
|
fun yield() {}
|
||||||
|
|
||||||
|
fun test3(yield: Int) {
|
||||||
|
X::`yield`
|
||||||
|
|
||||||
|
`yield`::toInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Migrate unsupported yield syntax" "true"
|
||||||
|
object yield {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = yie<caret>ld
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// "Migrate unsupported yield syntax" "true"
|
||||||
|
object yield {}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = `yield`
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Migrate unsupported yield syntax" "true"
|
||||||
|
object yield {
|
||||||
|
operator fun invoke(f: () -> Unit) = f()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
yie<caret>ld { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// "Migrate unsupported yield syntax" "true"
|
||||||
|
object yield {
|
||||||
|
operator fun invoke(f: () -> Unit) = f()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
yield() { }
|
||||||
|
}
|
||||||
@@ -10575,4 +10575,25 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/quickfix/yieldUnsupported")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class YieldUnsupported extends AbstractQuickFixTest {
|
||||||
|
public void testAllFilesPresentInYieldUnsupported() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/yieldUnsupported"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("yieldAsSimpleName.kt")
|
||||||
|
public void testYieldAsSimpleName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/yieldUnsupported/yieldAsSimpleName.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("yieldBeforeLambda.kt")
|
||||||
|
public void testYieldBeforeLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/yieldUnsupported/yieldBeforeLambda.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user