[FIR] Implement WRONG_LONG_SUFFIX diagnostics, fix tests

This commit is contained in:
Ivan Kochurkin
2021-04-07 14:04:55 +03:00
committed by TeamCityServer
parent 62ffc0033d
commit fb06da2d75
19 changed files with 60 additions and 34 deletions
@@ -5,7 +5,7 @@ fun takeAny(x: Any) {}
fun takeString(x: String) {}
fun test_0() {
1l
1L
1
10000000000
}
@@ -56,6 +56,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
VALUE_ARGUMENTS,
SUPERTYPES_LIST,
RETURN_WITH_LABEL,
LONG_LITERAL_SUFFIX,
;
@@ -61,6 +61,7 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
val EMPTY_CHARACTER_LITERAL by error<FirSourceElement, PsiElement>()
val TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL by error<FirSourceElement, PsiElement>()
val ILLEGAL_ESCAPE by error<FirSourceElement, PsiElement>()
val WRONG_LONG_SUFFIX by error<FirSourceElement, KtElement>(PositioningStrategy.LONG_LITERAL_SUFFIX)
}
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
@@ -86,6 +86,7 @@ object FirErrors {
val EMPTY_CHARACTER_LITERAL by error0<FirSourceElement, PsiElement>()
val TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL by error0<FirSourceElement, PsiElement>()
val ILLEGAL_ESCAPE by error0<FirSourceElement, PsiElement>()
val WRONG_LONG_SUFFIX by error0<FirSourceElement, KtElement>(SourceElementPositioningStrategies.LONG_LITERAL_SUFFIX)
// Unresolved
val HIDDEN by error1<FirSourceElement, PsiElement, AbstractFirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -522,6 +522,9 @@ object LightTreePositioningStrategies {
return markElement(tree.returnKeyword(node) ?: node, startOffset, endOffset, tree)
}
}
val LONG_LITERAL_SUFFIX = object : LightTreePositioningStrategy() {
}
}
fun FirSourceElement.hasValOrVar(): Boolean =
@@ -177,4 +177,9 @@ object SourceElementPositioningStrategies {
LightTreePositioningStrategies.RETURN_WITH_LABEL,
PositioningStrategies.RETURN_WITH_LABEL
)
val LONG_LITERAL_SUFFIX = SourceElementPositioningStrategy(
LightTreePositioningStrategies.LONG_LITERAL_SUFFIX,
PositioningStrategies.LONG_LITERAL_SUFFIX
)
}
@@ -179,6 +179,7 @@ private fun ConeSimpleDiagnostic.getFactory(): FirDiagnosticFactory0<FirSourceEl
DiagnosticKind.UnknownCallableKind -> FirErrors.UNKNOWN_CALLABLE_KIND
DiagnosticKind.IllegalProjectionUsage -> FirErrors.ILLEGAL_PROJECTION_USAGE
DiagnosticKind.MissingStdlibClass -> FirErrors.MISSING_STDLIB_CLASS
DiagnosticKind.WrongLongSuffix -> FirErrors.WRONG_LONG_SUFFIX
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
DiagnosticKind.IncorrectCharacterLiteral -> FirErrors.INCORRECT_CHARACTER_LITERAL
DiagnosticKind.EmptyCharacterLiteral -> FirErrors.EMPTY_CHARACTER_LITERAL
@@ -291,20 +291,37 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
return when (type) {
INTEGER_CONSTANT -> {
var diagnostic: DiagnosticKind = DiagnosticKind.IllegalConstExpression
val number: Long?
val kind = when {
convertedText !is Long -> return reportIncorrectConstant(DiagnosticKind.IllegalConstExpression)
hasUnsignedLongSuffix(text) -> {
if (text.endsWith("l")) {
diagnostic = DiagnosticKind.WrongLongSuffix
number = null
} else {
number = convertedText
}
ConstantValueKind.UnsignedLong
}
hasLongSuffix(text) -> {
if (text.endsWith("l")) {
diagnostic = DiagnosticKind.WrongLongSuffix
number = null
} else {
number = convertedText
}
ConstantValueKind.Long
}
hasUnsignedSuffix(text) -> {
number = convertedText
ConstantValueKind.UnsignedIntegerLiteral
}
else -> {
number = convertedText
ConstantValueKind.IntegerLiteral
}
}
@@ -312,8 +329,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
buildConstOrErrorExpression(
sourceElement,
kind,
convertedText,
ConeSimpleDiagnostic("Incorrect integer literal: $text", DiagnosticKind.IllegalConstExpression)
number,
ConeSimpleDiagnostic("Incorrect integer literal: $text", diagnostic)
)
}
FLOAT_CONSTANT ->
@@ -36,5 +36,7 @@ enum class DiagnosticKind {
TooManyCharactersInCharacterLiteral,
IllegalEscape,
WrongLongSuffix,
Other
}
@@ -1,10 +0,0 @@
val a1: Int = 1l
val a2: Int = 0x1l
val a3: Int = 0X1l
val a4: Int = 0b1l
val a5: Int = 0B1l
val a6: Long = 1l
val a7: Long = 0x1l
val a8: Long = 0X1l
val a9: Long = 0b1l
val a10: Long = 0B1l
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
val a1: Int = 1<!WRONG_LONG_SUFFIX!>l<!>
val a2: Int = 0x1<!WRONG_LONG_SUFFIX!>l<!>
val a3: Int = 0X1<!WRONG_LONG_SUFFIX!>l<!>
@@ -1,4 +0,0 @@
val a1 = 1ul
val a2 = 0x1ul
val a3 = 0B1ul
val a4 = 1Ul
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
val a1 = 1u<!WRONG_LONG_SUFFIX!>l<!>
val a2 = 0x1u<!WRONG_LONG_SUFFIX!>l<!>
val a3 = 0B1u<!WRONG_LONG_SUFFIX!>l<!>
@@ -1,11 +0,0 @@
// TESTCASE NUMBER: 1
val value_1 = 0l
// TESTCASE NUMBER: 2
val value_2 = 1000000000000000l
// TESTCASE NUMBER: 3
val value_3 = 0X0l
// TESTCASE NUMBER: 4
val value_4 = 0b101l
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -2,10 +2,10 @@
// TESTCASE NUMBER: 1
fun case_1() {
0l checkType { check<Long>() }
10000000000000l checkType { check<Long>() }
0X000Af10cDl checkType { check<Long>() }
0x0_0l checkType { check<Long>() }
0b100_000_111_111l checkType { check<Long>() }
0b0l checkType { check<Long>() }
0<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
10000000000000<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
0X000Af10cD<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
0x0_0<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
0b100_000_111_111<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
0b0<!WRONG_LONG_SUFFIX!>l<!> <!INAPPLICABLE_CANDIDATE!>checkType<!> { <!NONE_APPLICABLE!>check<!><Long>() }
}
@@ -149,6 +149,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.WRONG_LONG_SUFFIX) { firDiagnostic ->
WrongLongSuffixImpl(
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.HIDDEN) { firDiagnostic ->
HiddenImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir as FirDeclaration),
@@ -124,6 +124,10 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = IllegalEscape::class
}
abstract class WrongLongSuffix : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = WrongLongSuffix::class
}
abstract class Hidden : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = Hidden::class
abstract val hidden: KtSymbol
@@ -173,6 +173,13 @@ internal class IllegalEscapeImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class WrongLongSuffixImpl(
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.WrongLongSuffix(), KtAbstractFirDiagnostic<KtElement> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class HiddenImpl(
override val hidden: KtSymbol,
firDiagnostic: FirPsiDiagnostic<*>,