Replace some FIR syntax errors with more proper diagnostics

This commit is contained in:
Mikhail Glukhikh
2020-03-24 19:33:34 +03:00
parent 2f63c8a46a
commit b27152f903
53 changed files with 339 additions and 320 deletions
@@ -7,7 +7,7 @@ class B: A() {
<!UNRESOLVED_REFERENCE!>invoke<!>() <!UNRESOLVED_REFERENCE!>invoke<!>()
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!> { <!SUPER_IS_NOT_AN_EXPRESSION!>super<!> {
println('weird') println(<!ILLEGAL_CONST_EXPRESSION!>'weird'<!>)
} }
} }
} }
@@ -5,5 +5,5 @@ class Foo {
fun test() { fun test() {
var f = Foo() var f = Foo()
<!ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY!>f += f<!> <!ASSIGN_OPERATOR_AMBIGUITY!>f += f<!>
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
@@ -15,4 +16,7 @@ object DeclarationCheckers {
val MEMBER_DECLARATIONS: List<FirDeclarationChecker<FirMemberDeclaration>> = DECLARATIONS + listOf( val MEMBER_DECLARATIONS: List<FirDeclarationChecker<FirMemberDeclaration>> = DECLARATIONS + listOf(
FirInfixFunctionDeclarationChecker FirInfixFunctionDeclarationChecker
) )
val CONSTRUCTORS: List<FirDeclarationChecker<FirConstructor>> = MEMBER_DECLARATIONS + listOf(
FirConstructorChecker
)
} }
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2020 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.declaration
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
object FirConstructorChecker : FirDeclarationChecker<FirConstructor>() {
override fun check(declaration: FirConstructor, context: CheckerContext, reporter: DiagnosticReporter) {
val containingClass = context.containingDeclarations.lastOrNull() as? FirClass<*> ?: return
val source = declaration.source
val elementType = source?.elementType
if (elementType != KtNodeTypes.PRIMARY_CONSTRUCTOR && elementType != KtNodeTypes.SECONDARY_CONSTRUCTOR) {
return
}
when (containingClass.classKind) {
ClassKind.OBJECT -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
ClassKind.INTERFACE -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_INTERFACE)
ClassKind.ENUM_ENTRY -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
ClassKind.ENUM_CLASS -> if (declaration.visibility != Visibilities.PRIVATE) {
reporter.report(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM)
}
ClassKind.CLASS -> if (containingClass is FirRegularClass && containingClass.modality == Modality.SEALED &&
declaration.visibility != Visibilities.PRIVATE
) {
reporter.report(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED)
}
ClassKind.ANNOTATION_CLASS -> {
// DO NOTHING
}
}
}
private inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
source: T?,
factory: FirDiagnosticFactory0<T, P>
) {
source?.let { report(factory.on(it)) }
}
}
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.fir.analysis.collectors.components.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirBreakExpression
import org.jetbrains.kotlin.fir.expressions.FirContinueExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
import org.jetbrains.kotlin.fir.expressions.FirLoopJump
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers
@@ -66,11 +70,38 @@ abstract class AbstractDiagnosticCollector(
element.acceptChildren(this) element.acceptChildren(this)
} }
override fun visitRegularClass(regularClass: FirRegularClass) { private fun visitJump(loopJump: FirLoopJump) {
loopJump.runComponents()
loopJump.acceptChildren(this)
loopJump.target.labeledElement.takeIf { it is FirErrorLoop }?.accept(this)
}
override fun visitBreakExpression(breakExpression: FirBreakExpression) {
visitJump(breakExpression)
}
override fun visitContinueExpression(continueExpression: FirContinueExpression) {
visitJump(continueExpression)
}
private fun visitClassAndChildren(klass: FirClass<*>, type: ConeKotlinType) {
val typeRef = buildResolvedTypeRef { val typeRef = buildResolvedTypeRef {
type = regularClass.defaultType() this.type = type
} }
visitWithDeclarationAndReceiver(regularClass, regularClass.name, typeRef) visitWithDeclarationAndReceiver(klass, (klass as? FirRegularClass)?.name, typeRef)
}
override fun visitRegularClass(regularClass: FirRegularClass) {
visitClassAndChildren(regularClass, regularClass.defaultType())
}
override fun visitSealedClass(sealedClass: FirSealedClass) {
visitClassAndChildren(sealedClass, sealedClass.defaultType())
}
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
visitClassAndChildren(anonymousObject, anonymousObject.defaultType())
} }
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) { override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
@@ -34,7 +34,7 @@ class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollec
} }
override fun visitConstructor(constructor: FirConstructor, data: CheckerContext) { override fun visitConstructor(constructor: FirConstructor, data: CheckerContext) {
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(constructor, data, it) } runCheck { DeclarationCheckers.CONSTRUCTORS.check(constructor, data, it) }
} }
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) { override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0 import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.*
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -68,21 +66,24 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceElement, *> { private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceElement, *> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return when (kind) { return when (kind) {
DiagnosticKind.Syntax -> FirErrors.SYNTAX_ERROR Syntax -> FirErrors.SYNTAX_ERROR
DiagnosticKind.ReturnNotAllowed -> FirErrors.RETURN_NOT_ALLOWED ReturnNotAllowed -> FirErrors.RETURN_NOT_ALLOWED
DiagnosticKind.UnresolvedLabel -> FirErrors.UNRESOLVED_LABEL UnresolvedLabel -> FirErrors.UNRESOLVED_LABEL
DiagnosticKind.IllegalConstExpression -> FirErrors.ILLEGAL_CONST_EXPRESSION IllegalConstExpression -> FirErrors.ILLEGAL_CONST_EXPRESSION
DiagnosticKind.ConstructorInObject -> FirErrors.CONSTRUCTOR_IN_OBJECT DeserializationError -> FirErrors.DESERIALIZATION_ERROR
DiagnosticKind.DeserializationError -> FirErrors.DESERIALIZATION_ERROR InferenceError -> FirErrors.INFERENCE_ERROR
DiagnosticKind.InferenceError -> FirErrors.INFERENCE_ERROR NoSupertype -> FirErrors.NO_SUPERTYPE
DiagnosticKind.NoSupertype -> FirErrors.NO_SUPERTYPE TypeParameterAsSupertype -> FirErrors.TYPE_PARAMETER_AS_SUPERTYPE
DiagnosticKind.TypeParameterAsSupertype -> FirErrors.TYPE_PARAMETER_AS_SUPERTYPE EnumAsSupertype -> FirErrors.ENUM_AS_SUPERTYPE
DiagnosticKind.EnumAsSupertype -> FirErrors.ENUM_AS_SUPERTYPE RecursionInSupertypes -> FirErrors.RECURSION_IN_SUPERTYPES
DiagnosticKind.RecursionInSupertypes -> FirErrors.RECURSION_IN_SUPERTYPES RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES
DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES SuperNotAllowed -> FirErrors.SUPER_IS_NOT_AN_EXPRESSION
DiagnosticKind.SuperNotAllowed -> FirErrors.SUPER_IS_NOT_AN_EXPRESSION Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION
DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION ExpressionRequired -> FirErrors.EXPRESSION_REQUIRED
DiagnosticKind.Other -> FirErrors.OTHER_ERROR JumpOutsideLoop -> FirErrors.BREAK_OR_CONTINUE_OUTSIDE_A_LOOP
NotLoopLabel -> FirErrors.NOT_A_LOOP_LABEL
VariableExpected -> FirErrors.VARIABLE_EXPECTED
Other -> FirErrors.OTHER_ERROR
else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass")
} }
} }
@@ -29,6 +29,9 @@ object FirErrors {
val RECURSION_IN_SUPERTYPES by error0<FirSourceElement, PsiElement>() val RECURSION_IN_SUPERTYPES by error0<FirSourceElement, PsiElement>()
val RECURSION_IN_IMPLICIT_TYPES by error0<FirSourceElement, PsiElement>() val RECURSION_IN_IMPLICIT_TYPES by error0<FirSourceElement, PsiElement>()
val ERROR_FROM_JAVA_RESOLUTION by error0<FirSourceElement, PsiElement>() val ERROR_FROM_JAVA_RESOLUTION by error0<FirSourceElement, PsiElement>()
val EXPRESSION_REQUIRED by error0<FirSourceElement, PsiElement>()
val BREAK_OR_CONTINUE_OUTSIDE_A_LOOP by error0<FirSourceElement, PsiElement>()
val NOT_A_LOOP_LABEL by error0<FirSourceElement, PsiElement>()
val OTHER_ERROR by error0<FirSourceElement, PsiElement>() val OTHER_ERROR by error0<FirSourceElement, PsiElement>()
val TYPE_MISMATCH by error2<FirSourceElement, PsiElement, ConeKotlinType, ConeKotlinType>() val TYPE_MISMATCH by error2<FirSourceElement, PsiElement, ConeKotlinType, ConeKotlinType>()
val VARIABLE_EXPECTED by error0<FirSourceElement, PsiElement>() val VARIABLE_EXPECTED by error0<FirSourceElement, PsiElement>()
@@ -37,9 +40,12 @@ object FirErrors {
val INAPPLICABLE_INFIX_MODIFIER by existing<FirSourceElement, PsiElement, String>(Errors.INAPPLICABLE_INFIX_MODIFIER) val INAPPLICABLE_INFIX_MODIFIER by existing<FirSourceElement, PsiElement, String>(Errors.INAPPLICABLE_INFIX_MODIFIER)
val CONSTRUCTOR_IN_OBJECT by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_OBJECT) val CONSTRUCTOR_IN_OBJECT by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_OBJECT)
val CONSTRUCTOR_IN_INTERFACE by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_INTERFACE)
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM)
val NON_PRIVATE_CONSTRUCTOR_IN_SEALED by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED)
val REPEATED_MODIFIER by error1<FirSourceElement, KtModifierKeywordToken>() val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
val REDUNDANT_MODIFIER by error2<FirSourceElement, KtModifierKeywordToken, KtModifierKeywordToken>() val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, KtModifierKeywordToken, KtModifierKeywordToken>() val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
val INCOMPATIBLE_MODIFIERS by error2<FirSourceElement, KtModifierKeywordToken, KtModifierKeywordToken>() val INCOMPATIBLE_MODIFIERS by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.builder package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
@@ -36,7 +35,6 @@ import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.KtUnaryExpression import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.resolve.constants.evaluate.* import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -57,6 +55,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
abstract fun T.getReferencedNameAsName(): Name abstract fun T.getReferencedNameAsName(): Name
abstract fun T.getLabelName(): String? abstract fun T.getLabelName(): String?
abstract fun T.getExpressionInParentheses(): T? abstract fun T.getExpressionInParentheses(): T?
abstract fun T.getAnnotatedExpression(): T?
abstract fun T.getChildNodeByType(type: IElementType): T? abstract fun T.getChildNodeByType(type: IElementType): T?
abstract val T?.selectorExpression: T? abstract val T?.selectorExpression: T?
@@ -173,12 +172,13 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
fun FirLoopJumpBuilder.bindLabel(expression: T): FirLoopJumpBuilder { fun FirLoopJumpBuilder.bindLabel(expression: T): FirLoopJumpBuilder {
val labelName = expression.getLabelName() val labelName = expression.getLabelName()
val lastLoopTarget = context.firLoopTargets.lastOrNull() val lastLoopTarget = context.firLoopTargets.lastOrNull()
val sourceElement = expression.toFirSourceElement()
if (labelName == null) { if (labelName == null) {
target = lastLoopTarget ?: FirLoopTarget(labelName).apply { target = lastLoopTarget ?: FirLoopTarget(labelName).apply {
bind( bind(
buildErrorLoop( buildErrorLoop(
expression.getSourceOrNull(), sourceElement,
ConeSimpleDiagnostic("Cannot bind unlabeled jump to a loop", DiagnosticKind.Syntax) ConeSimpleDiagnostic("Cannot bind unlabeled jump to a loop", DiagnosticKind.JumpOutsideLoop)
) )
) )
} }
@@ -192,7 +192,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
target = FirLoopTarget(labelName).apply { target = FirLoopTarget(labelName).apply {
bind( bind(
buildErrorLoop( buildErrorLoop(
expression.getSourceOrNull(), ConeSimpleDiagnostic("Cannot bind label $labelName to a loop", DiagnosticKind.Syntax) sourceElement,
ConeSimpleDiagnostic(
"Cannot bind label $labelName to a loop",
lastLoopTarget?.let { DiagnosticKind.NotLoopLabel } ?: DiagnosticKind.JumpOutsideLoop
)
) )
) )
} }
@@ -200,14 +204,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
return this return this
} }
/**** Conversion utils ****/
private fun <T> T.getSourceOrNull(): FirSourceElement? {
return if (this is PsiElement) FirPsiSourceElement(this) else null
}
fun generateConstantExpressionByLiteral(expression: T): FirExpression { fun generateConstantExpressionByLiteral(expression: T): FirExpression {
val type = expression.elementType val type = expression.elementType
val text: String = expression.asText val text: String = expression.asText
val sourceElement = expression.toFirSourceElement()
val convertedText: Any? = when (type) { val convertedText: Any? = when (type) {
INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type) INTEGER_CONSTANT, FLOAT_CONSTANT -> parseNumericLiteral(text, type)
BOOLEAN_CONSTANT -> parseBoolean(text) BOOLEAN_CONSTANT -> parseBoolean(text)
@@ -217,7 +217,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
INTEGER_CONSTANT -> { INTEGER_CONSTANT -> {
val kind = when { val kind = when {
convertedText !is Long -> return buildErrorExpression { convertedText !is Long -> return buildErrorExpression {
source = expression.getSourceOrNull() source = sourceElement
diagnostic = ConeSimpleDiagnostic( diagnostic = ConeSimpleDiagnostic(
"Incorrect constant expression: $text", "Incorrect constant expression: $text",
DiagnosticKind.IllegalConstExpression DiagnosticKind.IllegalConstExpression
@@ -240,44 +240,44 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
buildConstOrErrorExpression( buildConstOrErrorExpression(
expression.getSourceOrNull(), sourceElement,
kind, kind,
convertedText, convertedText,
ConeSimpleDiagnostic("Incorrect integer literal: $text", DiagnosticKind.Syntax) ConeSimpleDiagnostic("Incorrect integer literal: $text", DiagnosticKind.IllegalConstExpression)
) )
} }
FLOAT_CONSTANT -> FLOAT_CONSTANT ->
if (convertedText is Float) { if (convertedText is Float) {
buildConstOrErrorExpression( buildConstOrErrorExpression(
expression.getSourceOrNull(), sourceElement,
FirConstKind.Float, FirConstKind.Float,
convertedText, convertedText,
ConeSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.Syntax) ConeSimpleDiagnostic("Incorrect float: $text", DiagnosticKind.IllegalConstExpression)
) )
} else { } else {
buildConstOrErrorExpression( buildConstOrErrorExpression(
expression.getSourceOrNull(), sourceElement,
FirConstKind.Double, FirConstKind.Double,
convertedText as Double, convertedText as Double,
ConeSimpleDiagnostic("Incorrect double: $text", DiagnosticKind.Syntax) ConeSimpleDiagnostic("Incorrect double: $text", DiagnosticKind.IllegalConstExpression)
) )
} }
CHARACTER_CONSTANT -> CHARACTER_CONSTANT ->
buildConstOrErrorExpression( buildConstOrErrorExpression(
expression.getSourceOrNull(), sourceElement,
FirConstKind.Char, FirConstKind.Char,
text.parseCharacter(), text.parseCharacter(),
ConeSimpleDiagnostic("Incorrect character: $text", DiagnosticKind.Syntax) ConeSimpleDiagnostic("Incorrect character: $text", DiagnosticKind.IllegalConstExpression)
) )
BOOLEAN_CONSTANT -> BOOLEAN_CONSTANT ->
buildConstExpression( buildConstExpression(
expression.getSourceOrNull(), sourceElement,
FirConstKind.Boolean, FirConstKind.Boolean,
convertedText as Boolean convertedText as Boolean
) )
NULL -> NULL ->
buildConstExpression( buildConstExpression(
expression.getSourceOrNull(), sourceElement,
FirConstKind.Null, FirConstKind.Null,
null null
) )
@@ -287,7 +287,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
fun Array<out T?>.toInterpolatingCall( fun Array<out T?>.toInterpolatingCall(
base: KtStringTemplateExpression?, base: T,
convertTemplateEntry: T?.(String) -> FirExpression convertTemplateEntry: T?.(String) -> FirExpression
): FirExpression { ): FirExpression {
return buildStringConcatenationCall { return buildStringConcatenationCall {
@@ -300,11 +300,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
OPEN_QUOTE, CLOSING_QUOTE -> continue@L OPEN_QUOTE, CLOSING_QUOTE -> continue@L
LITERAL_STRING_TEMPLATE_ENTRY -> { LITERAL_STRING_TEMPLATE_ENTRY -> {
sb.append(entry.asText) sb.append(entry.asText)
buildConstExpression(entry.getSourceOrNull(), FirConstKind.String, entry.asText) buildConstExpression(entry.toFirSourceElement(), FirConstKind.String, entry.asText)
} }
ESCAPE_STRING_TEMPLATE_ENTRY -> { ESCAPE_STRING_TEMPLATE_ENTRY -> {
sb.append(entry.unescapedValue) sb.append(entry.unescapedValue)
buildConstExpression(entry.getSourceOrNull(), FirConstKind.String, entry.unescapedValue) buildConstExpression(entry.toFirSourceElement(), FirConstKind.String, entry.unescapedValue)
} }
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true hasExpressions = true
@@ -322,7 +322,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
else -> { else -> {
hasExpressions = true hasExpressions = true
buildErrorExpression { buildErrorExpression {
source = entry.getSourceOrNull() source = entry.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Incorrect template entry: ${entry.asText}", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic("Incorrect template entry: ${entry.asText}", DiagnosticKind.Syntax)
} }
} }
@@ -361,7 +361,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
// TODO: Refactor, support receiver capturing in case of a.b // TODO: Refactor, support receiver capturing in case of a.b
fun generateIncrementOrDecrementBlock( fun generateIncrementOrDecrementBlock(
baseExpression: KtUnaryExpression?, baseExpression: T,
operationReference: T?,
argument: T?, argument: T?,
callName: Name, callName: Name,
prefix: Boolean, prefix: Boolean,
@@ -383,7 +384,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val resultInitializer = buildFunctionCall { val resultInitializer = buildFunctionCall {
source = baseSource source = baseSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = baseExpression?.operationReference?.toFirSourceElement() source = operationReference?.toFirSourceElement()
name = callName name = callName
} }
explicitReceiver = generateResolvedAccessExpression(source, temporaryVariable) explicitReceiver = generateResolvedAccessExpression(source, temporaryVariable)
@@ -432,13 +433,13 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
when (tokenType) { when (tokenType) {
REFERENCE_EXPRESSION -> { REFERENCE_EXPRESSION -> {
return buildSimpleNamedReference { return buildSimpleNamedReference {
source = left.getSourceOrNull() source = left.toFirSourceElement()
name = left.getReferencedNameAsName() name = left.getReferencedNameAsName()
} }
} }
THIS_EXPRESSION -> { THIS_EXPRESSION -> {
return buildExplicitThisReference { return buildExplicitThisReference {
source = left.getSourceOrNull() source = left.toFirSourceElement()
labelName = left.getLabelName() labelName = left.getLabelName()
} }
} }
@@ -450,7 +451,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
firMemberAccess.calleeReference firMemberAccess.calleeReference
} else { } else {
buildErrorNamedReference { buildErrorNamedReference {
source = left.getSourceOrNull() source = left.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported qualified LValue: ${left.asText}", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic("Unsupported qualified LValue: ${left.asText}", DiagnosticKind.Syntax)
} }
} }
@@ -458,11 +459,14 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
PARENTHESIZED -> { PARENTHESIZED -> {
return initializeLValue(left.getExpressionInParentheses(), convertQualified) return initializeLValue(left.getExpressionInParentheses(), convertQualified)
} }
ANNOTATED_EXPRESSION -> {
return initializeLValue(left.getAnnotatedExpression(), convertQualified)
}
} }
} }
return buildErrorNamedReference { return buildErrorNamedReference {
source = left.getSourceOrNull() source = left?.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Unsupported LValue: $tokenType", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic("Unsupported LValue: $tokenType", DiagnosticKind.VariableExpected)
} }
} }
@@ -497,7 +501,9 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
argumentList = buildBinaryArgumentList( argumentList = buildBinaryArgumentList(
this@generateAssignment?.convert() ?: buildErrorExpression { this@generateAssignment?.convert() ?: buildErrorExpression {
source = null source = null
diagnostic = ConeSimpleDiagnostic("Unsupported left value of assignment: ${baseSource?.psi?.text}", DiagnosticKind.Syntax) diagnostic = ConeSimpleDiagnostic(
"Unsupported left value of assignment: ${baseSource?.psi?.text}", DiagnosticKind.ExpressionRequired
)
}, },
value value
) )
@@ -678,7 +684,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
fun List<Pair<T, FirProperty>>.generateCopyFunction( fun List<Pair<T, FirProperty>>.generateCopyFunction(
session: FirSession, session: FirSession,
classOrObject: KtClassOrObject?, classOrObject: T,
classBuilder: AbstractFirRegularClassBuilder, classBuilder: AbstractFirRegularClassBuilder,
packageFqName: FqName, packageFqName: FqName,
classFqName: FqName, classFqName: FqName,
@@ -71,6 +71,14 @@ open class BaseConverter(
return null return null
} }
override fun LighterASTNode.getAnnotatedExpression(): LighterASTNode? {
this.forEachChildren {
if (it.isExpression()) return it
}
return null
}
override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? { override fun LighterASTNode.getChildNodeByType(type: IElementType): LighterASTNode? {
return this.getChildNodesByType(type).firstOrNull() return this.getChildNodesByType(type).firstOrNull()
} }
@@ -462,7 +462,7 @@ class DeclarationsConverter(
baseSession, this, context.packageFqName, context.className, firPrimaryConstructor baseSession, this, context.packageFqName, context.className, firPrimaryConstructor
) )
zippedParameters.generateCopyFunction( zippedParameters.generateCopyFunction(
baseSession, null, this, context.packageFqName, context.className, firPrimaryConstructor baseSession, classNode, this, context.packageFqName, context.className, firPrimaryConstructor
) )
// TODO: equals, hashCode, toString // TODO: equals, hashCode, toString
} }
@@ -718,15 +718,7 @@ class DeclarationsConverter(
} }
} }
val delegatedSelfTypeRef = val delegatedSelfTypeRef = classWrapper.delegatedSelfTypeRef
if (classWrapper.isObjectLiteral()) buildErrorTypeRef {
source = secondaryConstructor.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic(
"Constructor in object",
DiagnosticKind.ConstructorInObject
)
}
else classWrapper.delegatedSelfTypeRef
val explicitVisibility = modifiers.getVisibility() val explicitVisibility = modifiers.getVisibility()
val status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply { val status = FirDeclarationStatusImpl(explicitVisibility, Modality.FINAL).apply {
@@ -777,15 +769,7 @@ class DeclarationsConverter(
val isImplicit = constructorDelegationCall.asText.isEmpty() val isImplicit = constructorDelegationCall.asText.isEmpty()
val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent val isThis = (isImplicit && classWrapper.hasPrimaryConstructor) || thisKeywordPresent
val delegatedType = val delegatedType =
if (classWrapper.isObjectLiteral() || classWrapper.isInterface()) when { when {
isThis -> buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("Constructor in object", DiagnosticKind.ConstructorInObject)
}
else -> buildErrorTypeRef {
diagnostic = ConeSimpleDiagnostic("No super type", DiagnosticKind.Syntax)
}
}
else when {
isThis -> classWrapper.delegatedSelfTypeRef isThis -> classWrapper.delegatedSelfTypeRef
else -> classWrapper.delegatedSuperTypeRef else -> classWrapper.delegatedSuperTypeRef
} }
@@ -55,7 +55,11 @@ class ExpressionsConverter(
) : BaseConverter(session, tree, offset, context) { ) : BaseConverter(session, tree, offset, context) {
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R { inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R {
return expression?.let { convertExpression(it, errorReason) } as? R ?: (buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax)) as R) return expression?.let {
convertExpression(it, errorReason)
} as? R ?: buildErrorExpression(
null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired)
) as R
} }
/***** EXPRESSIONS *****/ /***** EXPRESSIONS *****/
@@ -103,7 +107,7 @@ class ExpressionsConverter(
OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression) OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression)
FUN -> declarationsConverter.convertFunctionDeclaration(expression) FUN -> declarationsConverter.convertFunctionDeclaration(expression)
else -> buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax)) else -> buildErrorExpression(null, ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired))
} }
} }
@@ -310,9 +314,13 @@ class ExpressionsConverter(
private fun convertUnaryExpression(unaryExpression: LighterASTNode): FirExpression { private fun convertUnaryExpression(unaryExpression: LighterASTNode): FirExpression {
lateinit var operationTokenName: String lateinit var operationTokenName: String
var argument: LighterASTNode? = null var argument: LighterASTNode? = null
var operationReference: LighterASTNode? = null
unaryExpression.forEachChildren { unaryExpression.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
OPERATION_REFERENCE -> operationTokenName = it.asText OPERATION_REFERENCE -> {
operationReference = it
operationTokenName = it.asText
}
else -> if (it.isExpression()) argument = it else -> if (it.isExpression()) argument = it
} }
} }
@@ -330,7 +338,8 @@ class ExpressionsConverter(
conventionCallName != null -> { conventionCallName != null -> {
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
return generateIncrementOrDecrementBlock( return generateIncrementOrDecrementBlock(
null, unaryExpression,
operationReference,
argument, argument,
callName = conventionCallName, callName = conventionCallName,
prefix = unaryExpression.tokenType == PREFIX_EXPRESSION prefix = unaryExpression.tokenType == PREFIX_EXPRESSION
@@ -548,7 +557,7 @@ class ExpressionsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate * @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseStringTemplate
*/ */
private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression { private fun convertStringTemplate(stringTemplate: LighterASTNode): FirExpression {
return stringTemplate.getChildrenAsArray().toInterpolatingCall(null) { convertShortOrLongStringTemplate(it) } return stringTemplate.getChildrenAsArray().toInterpolatingCall(stringTemplate) { convertShortOrLongStringTemplate(it) }
} }
private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression { private fun LighterASTNode?.convertShortOrLongStringTemplate(errorReason: String): FirExpression {
@@ -1053,8 +1062,9 @@ class ExpressionsConverter(
} }
val jumpBuilder = if (isBreak) FirBreakExpressionBuilder() else FirContinueExpressionBuilder() val jumpBuilder = if (isBreak) FirBreakExpressionBuilder() else FirContinueExpressionBuilder()
val sourceElement = jump.toFirSourceElement()
return jumpBuilder.apply { return jumpBuilder.apply {
source = jump.toFirSourceElement() source = sourceElement
}.bindLabel(jump).build() }.bindLabel(jump).build()
} }
@@ -82,6 +82,10 @@ class RawFirBuilder(
return (this as KtParenthesizedExpression).expression return (this as KtParenthesizedExpression).expression
} }
override fun PsiElement.getAnnotatedExpression(): PsiElement? {
return (this as KtAnnotatedExpression).baseExpression
}
override val PsiElement?.selectorExpression: PsiElement? override val PsiElement?.selectorExpression: PsiElement?
get() = (this as? KtQualifiedExpression)?.selectorExpression get() = (this as? KtQualifiedExpression)?.selectorExpression
@@ -135,14 +139,14 @@ class RawFirBuilder(
if (stubMode) buildExpressionStub() if (stubMode) buildExpressionStub()
else with(this()) { else with(this()) {
convertSafe() ?: buildErrorExpression( convertSafe() ?: buildErrorExpression(
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax), this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired),
) )
} }
private fun KtExpression?.toFirExpression(errorReason: String): FirExpression = private fun KtExpression?.toFirExpression(errorReason: String): FirExpression =
if (stubMode) buildExpressionStub() if (stubMode) buildExpressionStub()
else convertSafe() ?: buildErrorExpression( else convertSafe() ?: buildErrorExpression(
this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.Syntax), this?.toFirSourceElement(), ConeSimpleDiagnostic(errorReason, DiagnosticKind.ExpressionRequired),
) )
private fun KtExpression.toFirStatement(errorReason: String): FirStatement = private fun KtExpression.toFirStatement(errorReason: String): FirStatement =
@@ -152,16 +156,13 @@ class RawFirBuilder(
convert() convert()
private fun KtDeclaration.toFirDeclaration( private fun KtDeclaration.toFirDeclaration(
delegatedSuperType: FirTypeRef?, delegatedSelfType: FirResolvedTypeRef?, owner: KtClassOrObject, hasPrimaryConstructor: Boolean, delegatedSuperType: FirTypeRef, delegatedSelfType: FirResolvedTypeRef, owner: KtClassOrObject, hasPrimaryConstructor: Boolean,
): FirDeclaration { ): FirDeclaration {
return when (this) { return when (this) {
is KtSecondaryConstructor -> { is KtSecondaryConstructor -> {
toFirConstructor( toFirConstructor(
delegatedSuperType, delegatedSuperType,
delegatedSelfType ?: buildErrorTypeRef { delegatedSelfType,
source = this@toFirDeclaration.toFirSourceElement()
diagnostic = ConeSimpleDiagnostic("Constructor in object", DiagnosticKind.ConstructorInObject)
},
owner, owner,
hasPrimaryConstructor, hasPrimaryConstructor,
) )
@@ -172,7 +173,7 @@ class RawFirBuilder(
primaryConstructor?.valueParameters?.isEmpty() ?: owner.secondaryConstructors.let { constructors -> primaryConstructor?.valueParameters?.isEmpty() ?: owner.secondaryConstructors.let { constructors ->
constructors.isEmpty() || constructors.any { it.valueParameters.isEmpty() } constructors.isEmpty() || constructors.any { it.valueParameters.isEmpty() }
} }
toFirEnumEntry(delegatedSelfType!!, ownerClassHasDefaultConstructor) toFirEnumEntry(delegatedSelfType, ownerClassHasDefaultConstructor)
} }
else -> convert() else -> convert()
} }
@@ -397,7 +398,7 @@ class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef?, delegatedSelfTypeRef: FirTypeRef?,
delegatedEnumSuperTypeRef: FirTypeRef?, delegatedEnumSuperTypeRef: FirTypeRef?,
classKind: ClassKind, classKind: ClassKind,
): FirTypeRef? { ): FirTypeRef {
var superTypeCallEntry: KtSuperTypeCallEntry? = null var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperTypeRef: FirTypeRef? = null var delegatedSuperTypeRef: FirTypeRef? = null
for (superTypeListEntry in superTypeListEntries) { for (superTypeListEntry in superTypeListEntries) {
@@ -452,7 +453,7 @@ class RawFirBuilder(
if (container.superTypeRefs.isEmpty()) { if (container.superTypeRefs.isEmpty()) {
container.superTypeRefs += defaultDelegatedSuperTypeRef container.superTypeRefs += defaultDelegatedSuperTypeRef
} }
if (this is KtClass && this.isInterface()) return delegatedSuperTypeRef if (this is KtClass && this.isInterface()) return delegatedSuperTypeRef ?: implicitAnyType
// TODO: in case we have no primary constructor, // TODO: in case we have no primary constructor,
// it may be not possible to determine delegated super type right here // it may be not possible to determine delegated super type right here
@@ -687,13 +688,13 @@ class RawFirBuilder(
symbol = FirAnonymousObjectSymbol() symbol = FirAnonymousObjectSymbol()
val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this) val delegatedSelfType = objectDeclaration.toDelegatedSelfType(this)
objectDeclaration.extractAnnotationsTo(this) objectDeclaration.extractAnnotationsTo(this)
objectDeclaration.extractSuperTypeListEntriesTo(this, delegatedSelfType, null, ClassKind.CLASS) val delegatedSuperType = objectDeclaration.extractSuperTypeListEntriesTo(this, delegatedSelfType, null, ClassKind.CLASS)
typeRef = delegatedSelfType typeRef = delegatedSelfType
for (declaration in objectDeclaration.declarations) { for (declaration in objectDeclaration.declarations) {
declarations += declaration.toFirDeclaration( declarations += declaration.toFirDeclaration(
delegatedSuperType = null, delegatedSuperType,
delegatedSelfType = null, delegatedSelfType,
owner = objectDeclaration, owner = objectDeclaration,
hasPrimaryConstructor = false, hasPrimaryConstructor = false,
) )
@@ -866,7 +867,7 @@ class RawFirBuilder(
} }
private fun KtSecondaryConstructor.toFirConstructor( private fun KtSecondaryConstructor.toFirConstructor(
delegatedSuperTypeRef: FirTypeRef?, delegatedSuperTypeRef: FirTypeRef,
delegatedSelfTypeRef: FirTypeRef, delegatedSelfTypeRef: FirTypeRef,
owner: KtClassOrObject, owner: KtClassOrObject,
hasPrimaryConstructor: Boolean, hasPrimaryConstructor: Boolean,
@@ -885,7 +886,11 @@ class RawFirBuilder(
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD) isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
} }
symbol = FirConstructorSymbol(callableIdForClassConstructor()) symbol = FirConstructorSymbol(callableIdForClassConstructor())
delegatedConstructor = getDelegationCall().convert(delegatedSuperTypeRef, delegatedSelfTypeRef, hasPrimaryConstructor) delegatedConstructor = getDelegationCall().convert(
delegatedSuperTypeRef,
delegatedSelfTypeRef,
hasPrimaryConstructor
)
this@RawFirBuilder.context.firFunctionTargets += target this@RawFirBuilder.context.firFunctionTargets += target
extractAnnotationsTo(this) extractAnnotationsTo(this)
typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef) typeParameters += typeParametersFromSelfType(delegatedSelfTypeRef)
@@ -898,7 +903,7 @@ class RawFirBuilder(
} }
private fun KtConstructorDelegationCall.convert( private fun KtConstructorDelegationCall.convert(
delegatedSuperTypeRef: FirTypeRef?, delegatedSuperTypeRef: FirTypeRef,
delegatedSelfTypeRef: FirTypeRef, delegatedSelfTypeRef: FirTypeRef,
hasPrimaryConstructor: Boolean, hasPrimaryConstructor: Boolean,
): FirDelegatedConstructorCall { ): FirDelegatedConstructorCall {
@@ -906,10 +911,7 @@ class RawFirBuilder(
val source = this.toFirSourceElement() val source = this.toFirSourceElement()
val delegatedType = when { val delegatedType = when {
isThis -> delegatedSelfTypeRef isThis -> delegatedSelfTypeRef
else -> delegatedSuperTypeRef ?: buildErrorTypeRef { else -> delegatedSuperTypeRef
this.source = source
diagnostic = ConeSimpleDiagnostic("No super type", DiagnosticKind.Syntax)
}
} }
return buildDelegatedConstructorCall { return buildDelegatedConstructorCall {
this.source = source this.source = source
@@ -1449,7 +1451,7 @@ class RawFirBuilder(
conventionCallName != null -> { conventionCallName != null -> {
if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) { if (operationToken in OperatorConventions.INCREMENT_OPERATIONS) {
return generateIncrementOrDecrementBlock( return generateIncrementOrDecrementBlock(
expression, argument, expression, expression.operationReference, argument,
callName = conventionCallName, callName = conventionCallName,
prefix = expression is KtPrefixExpression, prefix = expression is KtPrefixExpression,
) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") } ) { (this as KtExpression).toFirExpression("Incorrect expression inside inc/dec") }
@@ -45,8 +45,8 @@ FILE: constructorInObject.kt
} }
public? final? val anonObject: <implicit> = object : R|kotlin/Any| { public? final? val anonObject: <implicit> = object : R|kotlin/Any| {
public? constructor(): <ERROR TYPE REF: Constructor in object> { public? constructor(): R|anonymous| {
super<<ERROR TYPE REF: No super type>>() super<R|kotlin/Any|>()
} }
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -22,7 +23,7 @@ internal class FirErrorExpressionImpl(
override val source: FirSourceElement?, override val source: FirSourceElement?,
override val diagnostic: ConeDiagnostic, override val diagnostic: ConeDiagnostic,
) : FirErrorExpression() { ) : FirErrorExpression() {
override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, diagnostic) override var typeRef: FirTypeRef = FirErrorTypeRefImpl(source, ConeStubDiagnostic(diagnostic))
override val annotations: List<FirAnnotationCall> get() = emptyList() override val annotations: List<FirAnnotationCall> get() = emptyList()
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) { override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
@@ -27,7 +28,7 @@ internal class FirErrorLoopImpl(
override val diagnostic: ConeDiagnostic, override val diagnostic: ConeDiagnostic,
) : FirErrorLoop() { ) : FirErrorLoop() {
override var block: FirBlock = FirEmptyExpressionBlock() override var block: FirBlock = FirEmptyExpressionBlock()
override var condition: FirExpression = FirErrorExpressionImpl(source, diagnostic) override var condition: FirExpression = FirErrorExpressionImpl(source, ConeStubDiagnostic(diagnostic))
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) { override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
annotations.forEach { it.accept(visitor, data) } annotations.forEach { it.accept(visitor, data) }
@@ -9,10 +9,14 @@ class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind
enum class DiagnosticKind { enum class DiagnosticKind {
Syntax, Syntax,
ExpressionRequired,
NotLoopLabel,
JumpOutsideLoop,
VariableExpected,
ReturnNotAllowed, ReturnNotAllowed,
UnresolvedLabel, UnresolvedLabel,
IllegalConstExpression, IllegalConstExpression,
ConstructorInObject,
DeserializationError, DeserializationError,
InferenceError, InferenceError,
NoSupertype, NoSupertype,
@@ -139,8 +139,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(errorLoop) { impl(errorLoop) {
default("block", "FirEmptyExpressionBlock()") default("block", "FirEmptyExpressionBlock()")
default("condition", "FirErrorExpressionImpl(source, diagnostic)") default("condition", "FirErrorExpressionImpl(source, ConeStubDiagnostic(diagnostic))")
useTypes(emptyExpressionBlock) useTypes(emptyExpressionBlock, coneStubDiagnosticType)
} }
impl(expression, "FirExpressionStub") { impl(expression, "FirExpressionStub") {
@@ -390,8 +390,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
impl(errorExpression) { impl(errorExpression) {
defaultEmptyList("annotations") defaultEmptyList("annotations")
default("typeRef", "FirErrorTypeRefImpl(source, diagnostic)") default("typeRef", "FirErrorTypeRefImpl(source, ConeStubDiagnostic(diagnostic))")
useTypes(errorTypeRefImpl) useTypes(errorTypeRefImpl, coneStubDiagnosticType)
} }
impl(resolvedFunctionTypeRef) { impl(resolvedFunctionTypeRef) {
@@ -65,6 +65,7 @@ val pureAbstractElementType = generatedType("FirPureAbstractElement")
val effectDeclarationType = type("fir.contracts.description", "ConeEffectDeclaration") val effectDeclarationType = type("fir.contracts.description", "ConeEffectDeclaration")
val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription") val emptyContractDescriptionType = generatedType("contracts.impl", "FirEmptyContractDescription")
val coneDiagnosticType = generatedType("diagnostics", "ConeDiagnostic") val coneDiagnosticType = generatedType("diagnostics", "ConeDiagnostic")
val coneStubDiagnosticType = generatedType("diagnostics", "ConeStubDiagnostic")
val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl") val dslBuilderAnnotationType = generatedType("builder", "FirBuilderDsl")
val firImplementationDetailType = generatedType("FirImplementationDetail") val firImplementationDetailType = generatedType("FirImplementationDetail")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
@Target(AnnotationTarget.EXPRESSION) @Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE) @Retention(AnnotationRetention.SOURCE)
annotation class Annotation annotation class Annotation
+11 -11
View File
@@ -3,26 +3,26 @@ class C {
fun f (a : Boolean, b : Boolean) { fun f (a : Boolean, b : Boolean) {
b@ while (true) b@ while (true)
a@ { a@ {
break@f <!NOT_A_LOOP_LABEL!>break@f<!>
break break
break@b break@b
break@a <!NOT_A_LOOP_LABEL!>break@a<!>
} }
continue <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue<!>
b@ while (true) b@ while (true)
a@ { a@ {
continue@f <!NOT_A_LOOP_LABEL!>continue@f<!>
continue continue
continue@b continue@b
continue@a <!NOT_A_LOOP_LABEL!>continue@a<!>
} }
break <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break<!>
continue@f <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue@f<!>
break@f <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break@f<!>
} }
fun containsBreak(a: String?, b: String?) { fun containsBreak(a: String?, b: String?) {
@@ -50,7 +50,7 @@ class C {
fun containsIllegalBreak(a: String?) { fun containsIllegalBreak(a: String?) {
loop@ while(a == null) { loop@ while(a == null) {
break@label <!NOT_A_LOOP_LABEL!>break@label<!>
} }
a.compareTo("2") a.compareTo("2")
} }
@@ -78,7 +78,7 @@ class C {
l@ for (el in array) { l@ for (el in array) {
break break
} }
if (true) break else break@l if (true) break else <!NOT_A_LOOP_LABEL!>break@l<!>
} }
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2") a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
} }
@@ -86,7 +86,7 @@ class C {
fun twoLabelsOnLoop() { fun twoLabelsOnLoop() {
label1@ label2@ for (i in 1..100) { label1@ label2@ for (i in 1..100) {
if (i > 0) { if (i > 0) {
break@label1 <!NOT_A_LOOP_LABEL!>break@label1<!>
} }
else { else {
break@label2 break@label2
@@ -1,92 +0,0 @@
// !LANGUAGE: +AllowBreakAndContinueInsideWhen
fun breakContinueInWhen(i: Int) {
for (y in 0..10) {
when(i) {
0 -> continue
1 -> break
2 -> {
for(z in 0..10) {
break
}
for(w in 0..10) {
continue
}
}
}
}
}
fun breakContinueInWhenWithWhile(i: Int, j: Int) {
while (i > 0) {
when (i) {
0 -> continue
1 -> break
2 -> {
while (j > 0) {
break
}
}
}
}
}
fun breakContinueInWhenWithDoWhile(i: Int, j: Int) {
do {
when (i) {
0 -> continue
1 -> break
2 -> {
do {
if (j == 5) break
if (j == 10) continue
} while (j > 0)
}
}
} while (i > 0)
}
fun labeledBreakContinue(i: Int) {
outer@ for (y in 0..10) {
when (i) {
0 -> continue@outer
1 -> break@outer
}
}
}
fun testBreakContinueInWhenInWhileCondition() {
var i = 0
while (
when (i) {
1 -> break
2 -> continue
else -> true
}
) {
++i
}
}
fun testBreakContinueInWhenInDoWhileCondition() {
var i = 0
do {
++i
} while (
when (i) {
1 -> break
2 -> continue
else -> true
}
)
}
fun testBreakContinueInWhenInForIteratorExpression(xs: List<Any>, i: Int) {
for (x in when (i) {
1 -> break
2 -> continue
else -> xs
}) {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +AllowBreakAndContinueInsideWhen // !LANGUAGE: +AllowBreakAndContinueInsideWhen
fun breakContinueInWhen(i: Int) { fun breakContinueInWhen(i: Int) {
@@ -1,13 +1,13 @@
fun test(c : Char) { fun test(c : Char) {
test('') test(<!ILLEGAL_CONST_EXPRESSION!>''<!>)
test('a') test('a')
test('aa') test(<!ILLEGAL_CONST_EXPRESSION!>'aa'<!>)
<!INAPPLICABLE_CANDIDATE!>test<!>('a) <!INAPPLICABLE_CANDIDATE!>test<!>(<!ILLEGAL_CONST_EXPRESSION!>'a)<!>
<!UNRESOLVED_REFERENCE!>test<!>(' <!UNRESOLVED_REFERENCE!>test<!>(<!ILLEGAL_CONST_EXPRESSION!>'<!>
<!UNRESOLVED_REFERENCE!>test<!>(0<!SYNTAX!><!>' <!UNRESOLVED_REFERENCE!>test<!>(0<!ILLEGAL_CONST_EXPRESSION!><!SYNTAX!><!>'<!>
<!UNRESOLVED_REFERENCE!>test<!>('\n') <!UNRESOLVED_REFERENCE!>test<!>('\n')
<!UNRESOLVED_REFERENCE!>test<!>('\\') <!UNRESOLVED_REFERENCE!>test<!>('\\')
<!UNRESOLVED_REFERENCE!>test<!>(''<!SYNTAX!><!>'') <!UNRESOLVED_REFERENCE!>test<!>(<!ILLEGAL_CONST_EXPRESSION!>''<!><!ILLEGAL_CONST_EXPRESSION!><!SYNTAX!><!>''<!>)
test('\'') test('\'')
test('\"') test('\"')
} }
@@ -2,11 +2,11 @@
// KT-451 Incorrect character literals cause assertion failures // KT-451 Incorrect character literals cause assertion failures
fun ff() { fun ff() {
val b = '' val b = <!ILLEGAL_CONST_EXPRESSION!>''<!>
val c = '23' val c = <!ILLEGAL_CONST_EXPRESSION!>'23'<!>
val d = 'a val d = <!ILLEGAL_CONST_EXPRESSION!>'a<!>
val e = 'ab val e = <!ILLEGAL_CONST_EXPRESSION!>'ab<!>
val f = '\' val f = <!ILLEGAL_CONST_EXPRESSION!>'\'<!>
} }
fun test() { fun test() {
@@ -19,19 +19,19 @@ fun test() {
'\'' '\''
'\\' '\\'
'\$' '\$'
'\x' <!ILLEGAL_CONST_EXPRESSION!>'\x'<!>
'\123' <!ILLEGAL_CONST_EXPRESSION!>'\123'<!>
'\ra' <!ILLEGAL_CONST_EXPRESSION!>'\ra'<!>
'\000' <!ILLEGAL_CONST_EXPRESSION!>'\000'<!>
'\000' <!ILLEGAL_CONST_EXPRESSION!>'\000'<!>
'\u0000' '\u0000'
'\u000a' '\u000a'
'\u000A' '\u000A'
'\u' <!ILLEGAL_CONST_EXPRESSION!>'\u'<!>
'\u0' <!ILLEGAL_CONST_EXPRESSION!>'\u0'<!>
'\u00' <!ILLEGAL_CONST_EXPRESSION!>'\u00'<!>
'\u000' <!ILLEGAL_CONST_EXPRESSION!>'\u000'<!>
'\u000z' <!ILLEGAL_CONST_EXPRESSION!>'\u000z'<!>
'\\u000' <!ILLEGAL_CONST_EXPRESSION!>'\\u000'<!>
'\' <!ILLEGAL_CONST_EXPRESSION!>'\'<!>
} }
+16 -16
View File
@@ -14,7 +14,7 @@ class C() : B() {
this.c = 34 this.c = 34
super.c = 3535 //repeat for 'c' super.c = 3535 //repeat for 'c'
getInt() = 12 <!VARIABLE_EXPECTED!>getInt()<!> = 12
} }
fun foo1(c: C) { fun foo1(c: C) {
@@ -42,27 +42,27 @@ fun cannotBe() {
var i: Int = 5 var i: Int = 5
<!UNRESOLVED_REFERENCE!>z<!> = 30; <!UNRESOLVED_REFERENCE!>z<!> = 30;
"" = ""; <!VARIABLE_EXPECTED!>""<!> = "";
foo() = Unit; <!VARIABLE_EXPECTED!>foo()<!> = Unit;
(i as Int) = 34 (<!VARIABLE_EXPECTED!>i as Int<!>) = 34
(i is Int) = false (<!VARIABLE_EXPECTED!>i is Int<!>) = false
A() = A() <!VARIABLE_EXPECTED!>A()<!> = A()
5 = 34 <!VARIABLE_EXPECTED!>5<!> = 34
} }
fun canBe(i0: Int, j: Int) { fun canBe(i0: Int, j: Int) {
var i = i0 var i = i0
(label@ i) = 34 (<!VARIABLE_EXPECTED!>label@ i<!>) = 34
(label@ j) = 34 //repeat for j (<!VARIABLE_EXPECTED!>label@ j<!>) = 34 //repeat for j
val a = A() val a = A()
(l@ a.a) = 3894 (<!VARIABLE_EXPECTED!>l@ a.a<!>) = 3894
} }
fun canBe2(j: Int) { fun canBe2(j: Int) {
(label@ j) = 34 (<!VARIABLE_EXPECTED!>label@ j<!>) = 34
} }
class A() { class A() {
@@ -77,11 +77,11 @@ class Test() {
<!VARIABLE_EXPECTED!>getInt()<!> += 343 <!VARIABLE_EXPECTED!>getInt()<!> += 343
(f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343 (f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343
1++ <!VARIABLE_EXPECTED!>1<!>++
(r@ 1)++ (<!VARIABLE_EXPECTED!>r@ 1<!>)++
getInt()++ <!VARIABLE_EXPECTED!>getInt()<!>++
(m@ getInt())++ (<!VARIABLE_EXPECTED!>m@ getInt()<!>)++
this<!UNRESOLVED_REFERENCE!>++<!> this<!UNRESOLVED_REFERENCE!>++<!>
@@ -106,7 +106,7 @@ class Test() {
<!VARIABLE_EXPECTED!>b<!> += 34 <!VARIABLE_EXPECTED!>b<!> += 34
a++ a++
(l@ a)++ (<!VARIABLE_EXPECTED!>l@ a<!>)++
(a)++ (a)++
} }
@@ -1,24 +1,24 @@
object A1() { object A1<!CONSTRUCTOR_IN_OBJECT!>()<!> {
constructor(x: Int = "", y: Int) : this() { <!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = "", y: Int)<!> : this() {
x + y x + y
} }
} }
object A2 public constructor(private val prop: Int) { object A2 public <!CONSTRUCTOR_IN_OBJECT!>constructor(private val prop: Int)<!> {
constructor(x: Int = "", y: Int) : this(x * y) { <!CONSTRUCTOR_IN_OBJECT!>constructor(x: Int = "", y: Int)<!> : this(x * y) {
x + y x + y
} }
} }
val x = object (val prop: Int) { val x = object <!CONSTRUCTOR_IN_OBJECT!>(val prop: Int)<!> {
<!CONSTRUCTOR_IN_OBJECT, CONSTRUCTOR_IN_OBJECT!>constructor()<!> : <!UNRESOLVED_REFERENCE!>this<!>(1) { <!CONSTRUCTOR_IN_OBJECT!>constructor()<!> : <!UNRESOLVED_REFERENCE!>this<!>(1) {
val x = 1 val x = 1
x * x x * x
} }
} }
class A3 { class A3 {
companion object B(val prop: Int) { companion object B<!CONSTRUCTOR_IN_OBJECT!>(val prop: Int)<!> {
public constructor() : this(2) public <!CONSTRUCTOR_IN_OBJECT!>constructor()<!> : this(2)
} }
} }
@@ -11,7 +11,7 @@ fun test(a: Any) {
a foo"asd${a}sfsa" a foo"asd${a}sfsa"
a foo"""sdf""" a foo"""sdf"""
a foo'd' a foo'd'
a foo'' a foo<!ILLEGAL_CONST_EXPRESSION!>''<!>
a foo""foo a a foo""foo a
a foo"asd"foo a a foo"asd"foo a
@@ -19,17 +19,17 @@ fun test(a: Any) {
a foo"asd${a}sfsa"foo a a foo"asd${a}sfsa"foo a
a foo"""sdf"""foo a a foo"""sdf"""foo a
a foo'd'foo a a foo'd'foo a
a foo''foo a a foo<!ILLEGAL_CONST_EXPRESSION!>''<!>foo a
a in"foo" a in"foo"
a in"""foo""" a in"""foo"""
a in's' a in's'
a in'' a in<!ILLEGAL_CONST_EXPRESSION!>''<!>
a !in"foo" a !in"foo"
a !in"""foo""" a !in"""foo"""
a !in's' a !in's'
a !in'' a !in<!ILLEGAL_CONST_EXPRESSION!>''<!>
if("s"is Any) {} if("s"is Any) {}
if("s"is Any) {} if("s"is Any) {}
@@ -9,7 +9,7 @@ interface T2 constructor() {}
interface T3 private constructor(a: Int) {} interface T3 private constructor(a: Int) {}
interface T4 { interface T4 {
constructor(a: Int) { <!CONSTRUCTOR_IN_INTERFACE!>constructor(a: Int)<!> {
val b: Int = 1 val b: Int = 1
} }
} }
@@ -18,4 +18,4 @@ class G {
companion object F<T> companion object F<T>
} }
object H<T, R>() object H<T, R><!CONSTRUCTOR_IN_OBJECT!>()<!>
@@ -9,7 +9,7 @@ annotation class Foo(
annotation class Bar( annotation class Bar(
val a: Array<String> = [' '], val a: Array<String> = [' '],
val b: Array<String> = ["", ''], val b: Array<String> = ["", <!ILLEGAL_CONST_EXPRESSION!>''<!>],
val c: Array<String> = [1] val c: Array<String> = [1]
) )
@@ -1,17 +1,17 @@
fun test() { fun test() {
l@ for (i in if (true) 1..10 else continue@l) {} l@ for (i in if (true) 1..10 else <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue@l<!>) {}
for (i in if (true) 1..10 else continue) {} for (i in if (true) 1..10 else <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue<!>) {}
while (break) {} while (<!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break<!>) {}
l@ while (break@l) {} l@ while (<!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break@l<!>) {}
do {} while (continue) do {} while (<!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue<!>)
l@ do {} while (continue@l) l@ do {} while (<!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue@l<!>)
//KT-5704 //KT-5704
var i = 0 var i = 0
while (if(i++ == 10) break else continue) {} while (if(i++ == 10) <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break<!> else <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>continue<!>) {}
} }
fun test2(b: Boolean) { fun test2(b: Boolean) {
@@ -1,5 +1,5 @@
fun foo1() = while (b()) {} fun foo1() = <!EXPRESSION_REQUIRED!>while (b()) {}<!>
fun foo2() = <!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in 10) {}<!> fun foo2() = <!UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE, UNRESOLVED_REFERENCE!>for (i in 10) {}<!>
@@ -19,7 +19,7 @@ class Test3 {
} }
fun test4() { fun test4() {
break@test4 <!BREAK_OR_CONTINUE_OUTSIDE_A_LOOP!>break@test4<!>
} }
class Test5 { class Test5 {
@@ -43,11 +43,11 @@ class Test6 {
class Test7 { class Test7 {
fun Test7() { fun Test7() {
Test8@ while (true) { Test8@ while (true) {
break@Test7 <!NOT_A_LOOP_LABEL!>break@Test7<!>
} }
Test7@ while (true) { Test7@ while (true) {
break@Test8 <!NOT_A_LOOP_LABEL!>break@Test8<!>
} }
} }
} }
@@ -15,7 +15,7 @@ fun main() {
} }
//KT-351 Distinguish statement and expression positions //KT-351 Distinguish statement and expression positions
val w = while (true) {} val w = <!EXPRESSION_REQUIRED!>while (true) {}<!>
fun foo() { fun foo() {
var z = 2 var z = 2
@@ -152,12 +152,12 @@ fun bar(a: Unit) {}
fun testStatementInExpressionContext() { fun testStatementInExpressionContext() {
var z = 34 var z = 34
val a1: Unit = z = 334 val a1: Unit = <!EXPRESSION_REQUIRED!>z = 334<!>
val f = for (i in 1..10) {} val f = for (i in 1..10) {}
if (true) return z = 34 if (true) return <!EXPRESSION_REQUIRED!>z = 34<!>
return while (true) {} return <!EXPRESSION_REQUIRED!>while (true) {}<!>
} }
fun testStatementInExpressionContext2() { fun testStatementInExpressionContext2() {
val a2: Unit = while(true) {} val a2: Unit = <!EXPRESSION_REQUIRED!>while(true) {}<!>
} }
@@ -1 +1 @@
data object Object(val x: Int, val y: Int) data object Object<!CONSTRUCTOR_IN_OBJECT!>(val x: Int, val y: Int)<!>
@@ -4,7 +4,7 @@
fun foo(block: () -> (() -> Int)) {} fun foo(block: () -> (() -> Int)) {}
fun test() { fun test() {
val x = fun named1(x: Int): Int { return 1 } val x = <!EXPRESSION_REQUIRED!>fun named1(x: Int): Int { return 1 }<!>
x <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Int>>() } x <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Int>>() }
foo { fun named2(): Int {return 1} } foo { fun named2(): Int {return 1} }
@@ -45,12 +45,12 @@ fun test() {
x4 checkType { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Unit>>() } x4 checkType { <!UNRESOLVED_REFERENCE!>_<!><Function1<Int, Unit>>() }
{ y: Int -> fun named14(): Int {return 1} } { y: Int -> fun named14(): Int {return 1} }
val b = <!UNRESOLVED_REFERENCE!>(fun named15(): Boolean { return true })()<!> val b = <!UNRESOLVED_REFERENCE!>(<!EXPRESSION_REQUIRED!>fun named15(): Boolean { return true }<!>)()<!>
baz(fun named16(){}) baz(<!EXPRESSION_REQUIRED!>fun named16(){}<!>)
} }
fun bar() = fun named() {} fun bar() = <!EXPRESSION_REQUIRED!>fun named() {}<!>
fun <T> run(block: () -> T): T = null!! fun <T> run(block: () -> T): T = null!!
fun run2(block: () -> Unit): Unit = null!! fun run2(block: () -> Unit): Unit = null!!
@@ -1,7 +1,7 @@
enum class E public constructor(val x: Int) { enum class E <!NON_PRIVATE_CONSTRUCTOR_IN_ENUM!>public constructor(val x: Int)<!> {
FIRST(); FIRST();
internal constructor(): this(42) <!NON_PRIVATE_CONSTRUCTOR_IN_ENUM!>internal constructor(): this(42)<!>
constructor(y: Int, z: Int): this(y + z) constructor(y: Int, z: Int): this(y + z)
} }
@@ -5,5 +5,5 @@ fun foo() {
fun A.foo() {} fun A.foo() {}
(fun A.foo() {}) (fun A.foo() {})
run(fun foo() {}) run(<!EXPRESSION_REQUIRED!>fun foo() {}<!>)
} }
@@ -6,12 +6,12 @@ fun foo(i: Int) = i
fun bar(l: Long) = l fun bar(l: Long) = l
fun main() { fun main() {
val i = <!ILLEGAL_CONST_EXPRESSION, ILLEGAL_CONST_EXPRESSION, ILLEGAL_CONST_EXPRESSION!>111111111111111777777777777777<!> val i = <!ILLEGAL_CONST_EXPRESSION!>111111111111111777777777777777<!>
//todo add diagnostic text messages //todo add diagnostic text messages
//report only 'The value is out of range' //report only 'The value is out of range'
//not 'An integer literal does not conform to the expected type Int/Long' //not 'An integer literal does not conform to the expected type Int/Long'
val l: Long = <!ILLEGAL_CONST_EXPRESSION, ILLEGAL_CONST_EXPRESSION!>1111111111111117777777777777777<!> val l: Long = <!ILLEGAL_CONST_EXPRESSION!>1111111111111117777777777777777<!>
foo(<!ILLEGAL_CONST_EXPRESSION, ILLEGAL_CONST_EXPRESSION!>11111111111111177777777777777<!>) foo(<!ILLEGAL_CONST_EXPRESSION!>11111111111111177777777777777<!>)
bar(<!ILLEGAL_CONST_EXPRESSION, ILLEGAL_CONST_EXPRESSION!>11111111111111177777777777777<!>) bar(<!ILLEGAL_CONST_EXPRESSION!>11111111111111177777777777777<!>)
} }
@@ -8,5 +8,5 @@ operator fun RemAndRemAssign.remAssign(x: Int) {}
fun test() { fun test() {
var c = RemAndRemAssign var c = RemAndRemAssign
<!ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY!>c %= 1<!> <!ASSIGN_OPERATOR_AMBIGUITY!>c %= 1<!>
} }
@@ -11,7 +11,7 @@ fun test(m: MyInt) {
m += m m += m
var i = 1 var i = 1
<!ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY!>i += 34<!> <!ASSIGN_OPERATOR_AMBIGUITY!>i += 34<!>
} }
@@ -9,5 +9,5 @@ fun test() {
val c = C() val c = C()
c += "" c += ""
var c1 = C() var c1 = C()
<!ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY!>c1 += ""<!> <!ASSIGN_OPERATOR_AMBIGUITY!>c1 += ""<!>
} }
@@ -15,5 +15,5 @@ fun test() {
val c = C() val c = C()
c.c += "" c.c += ""
var c1 = C1() var c1 = C1()
<!ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY, ASSIGN_OPERATOR_AMBIGUITY!>c1.c += ""<!> <!ASSIGN_OPERATOR_AMBIGUITY!>c1.c += ""<!>
} }
@@ -13,11 +13,11 @@ fun box() : Boolean {
var c = A() var c = A()
val d = c; val d = c;
c %= A(); c %= A();
return (c != d) && (c.p = "yeah") return (c != d) && <!EXPRESSION_REQUIRED!>(c.p = "yeah")<!>
} }
fun box2() : Boolean { fun box2() : Boolean {
var c = A() var c = A()
return (c.p = "yeah") && true return <!EXPRESSION_REQUIRED!>(c.p = "yeah")<!> && true
} }
@@ -1,7 +1,7 @@
sealed class Sealed protected constructor(val x: Int) { sealed class Sealed <!NON_PRIVATE_CONSTRUCTOR_IN_SEALED!>protected constructor(val x: Int)<!> {
object FIRST : Sealed() object FIRST : Sealed()
public constructor(): this(42) <!NON_PRIVATE_CONSTRUCTOR_IN_SEALED!>public constructor(): this(42)<!>
constructor(y: Int, z: Int): this(y + z) constructor(y: Int, z: Int): this(y + z)
} }
@@ -1,17 +1,17 @@
object A { object A {
constructor() <!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
init {} init {}
} }
enum class B { enum class B {
X() { X() {
<!UNRESOLVED_REFERENCE!>constructor()<!> <!CONSTRUCTOR_IN_OBJECT, UNRESOLVED_REFERENCE!>constructor()<!>
} }
} }
class C { class C {
companion object { companion object {
constructor() <!CONSTRUCTOR_IN_OBJECT!>constructor()<!>
} }
} }
@@ -1,3 +0,0 @@
interface A {
constructor()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface A { interface A {
<!CONSTRUCTOR_IN_INTERFACE!>constructor()<!> <!CONSTRUCTOR_IN_INTERFACE!>constructor()<!>
} }
@@ -4,7 +4,7 @@ fun <T : CharSequence> foo(x: Array<Any>, block: (T, Int) -> Int) {
@Suppress("UNCHECKED_CAST") r = block(x[0] as T, "" as Int) @Suppress("UNCHECKED_CAST") r = block(x[0] as T, "" as Int)
// to prevent unused assignment diagnostic for the above statement // to prevent unused assignment diagnostic for the above statement
r.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() r.hashCode()
var i = 1 var i = 1
@@ -311,7 +311,7 @@ abstract class AbstractFirBaseDiagnosticsTest : BaseDiagnosticsTest() {
private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> { private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> {
val result = mutableListOf<ActualDiagnostic>() val result = mutableListOf<ActualDiagnostic>()
filter { it.factory != FirErrors.SYNTAX_ERROR }.mapTo(result) { mapTo(result) {
val oldDiagnostic = (it as FirPsiDiagnostic<*>).asPsiBasedDiagnostic() val oldDiagnostic = (it as FirPsiDiagnostic<*>).asPsiBasedDiagnostic()
ActualDiagnostic(oldDiagnostic, null, true) ActualDiagnostic(oldDiagnostic, null, true)
} }