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);
|
||||
|
||||
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);
|
||||
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(UNDERSCORE_IS_RESERVED, "Names _, __, ___, ..., are reserved in Kotlin");
|
||||
MAP.put(YIELD_IS_RESERVED, "{0}", STRING);
|
||||
MAP.put(INVALID_CHARACTERS, "Name {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> {
|
||||
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.suppressDiagnosticsInDebugMode
|
||||
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.resolve.PossiblyBareType.bare
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||
@@ -227,6 +228,8 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
val referenceExpression = type.referenceExpression ?: return
|
||||
|
||||
checkReservedYield(referenceExpression, c.trace)
|
||||
c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifier)
|
||||
|
||||
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.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
@@ -185,7 +186,9 @@ public class ValueArgumentsToParametersMapper {
|
||||
ValueArgumentName argumentName = argument.getArgumentName();
|
||||
assert argumentName != null;
|
||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(argumentName.getAsName());
|
||||
KtReferenceExpression nameReference = argumentName.getReferenceExpression();
|
||||
KtSimpleNameExpression nameReference = argumentName.getReferenceExpression();
|
||||
|
||||
KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace());
|
||||
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||
nameReference,
|
||||
|
||||
+4
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
@@ -162,6 +163,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
@Override
|
||||
public KotlinTypeInfo visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||
KtPsiUtilKt.checkReservedYield(expression, context.trace);
|
||||
|
||||
// TODO : other members
|
||||
// TODO : type substitutions???
|
||||
CallExpressionResolver callExpressionResolver = components.callExpressionResolver;
|
||||
@@ -942,6 +945,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
boolean isStatement
|
||||
) {
|
||||
KtSimpleNameExpression labelExpression = expression.getTargetLabel();
|
||||
KtPsiUtilKt.checkReservedYield(labelExpression, context.trace);
|
||||
if (labelExpression != null) {
|
||||
PsiElement labelIdentifier = labelExpression.getIdentifier();
|
||||
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.psi.*
|
||||
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.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
@@ -632,6 +633,8 @@ class DoubleColonExpressionResolver(
|
||||
outerContext: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
checkReservedYield(reference, outerContext.trace)
|
||||
|
||||
// we should preserve information about `call` because callable references are analyzed two times,
|
||||
// otherwise there will be not completed calls in trace
|
||||
val call = outerContext.trace[BindingContext.CALL, reference] ?: CallMaker.makeCall(reference, receiver, null, reference, emptyList())
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
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.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.resolve.BindingContext
|
||||
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? {
|
||||
checkReservedYieldBeforeLambda(expression, context.trace)
|
||||
if (!expression.functionLiteral.hasBody()) return null
|
||||
|
||||
val expectedType = context.expectedType
|
||||
@@ -160,6 +164,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
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(
|
||||
expression: KtLambdaExpression,
|
||||
context: ExpressionTypingContext
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
||||
@@ -138,6 +139,8 @@ public class LabelResolver {
|
||||
@NotNull ResolutionContext context
|
||||
) {
|
||||
KtSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
KtPsiUtilKt.checkReservedYield(labelElement, context.trace);
|
||||
|
||||
Name labelName = expression.getLabelNameAsName();
|
||||
if (labelElement == null || labelName == null) return null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user