diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 7c631af490d..ea4682b2279 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.types.expressions; import com.google.common.collect.Lists; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.tree.IElementType; @@ -39,6 +38,7 @@ import org.jetbrains.kotlin.incremental.KotlinLookupLocation; import org.jetbrains.kotlin.lexer.KtKeywordToken; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.parsing.ParseUtilsKt; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.psi.psiUtil.ReservedCheckingKt; @@ -75,12 +75,9 @@ import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperKt; import org.jetbrains.kotlin.util.OperatorNameConventions; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.lexer.KtTokens.*; @@ -237,8 +234,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context); } - private static final Pattern FP_LITERAL_PARTS = Pattern.compile("(?:([_\\d]*)\\.?([_\\d]*)e?[+-]?([_\\d]*))[f]?"); - private void checkUnderscores( @NotNull KtConstantExpression expression, @NotNull IElementType elementType, @@ -254,30 +249,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return; } - List parts; - - if (elementType == KtNodeTypes.INTEGER_CONSTANT) { - int start = 0; - int end = expression.getText().length(); - if (text.startsWith("0x") || text.startsWith("0b")) start += 2; - if (StringUtil.endsWithChar(text, 'l')) --end; - parts = Collections.singletonList(text.substring(start, end)); - } - else { - Matcher matcher = FP_LITERAL_PARTS.matcher(text); - parts = new ArrayList<>(); - if (matcher.matches()) { - for (int i = 0; i < matcher.groupCount(); i++) { - parts.add(matcher.group(i + 1)); - } - } - } - - for (String part : parts) { - if (part != null && (part.startsWith("_") || part.endsWith("_"))) { - context.trace.report(Errors.ILLEGAL_UNDERSCORE.on(expression)); - return; - } + if (ParseUtilsKt.hasIllegalUnderscore(expression.getText(), elementType)) { + context.trace.report(Errors.ILLEGAL_UNDERSCORE.on(expression)); } } diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/ParseUtils.kt b/compiler/psi/src/org/jetbrains/kotlin/parsing/ParseUtils.kt index f3d716de258..983a7b610b7 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/ParseUtils.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/ParseUtils.kt @@ -10,6 +10,22 @@ import com.intellij.util.text.LiteralFormatUtil import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.utils.extractRadix +private val FP_LITERAL_PARTS = "(?:([_\\d]*)\\.?([_\\d]*)e?[+-]?([_\\d]*))[f]?".toRegex() + +fun hasIllegalUnderscore(text: String, elementType: IElementType): Boolean { + val parts: List = if (elementType === KtNodeTypes.INTEGER_CONSTANT) { + var start = 0 + var end: Int = text.length + if (text.startsWith("0x", ignoreCase = true) || text.startsWith("0b", ignoreCase = true)) start += 2 + if (text.endsWith('l', ignoreCase = true)) --end + listOf(text.substring(start, end)) + } else { + FP_LITERAL_PARTS.findAll(text).flatMap { it.groupValues }.toList() + } + + return parts.any { it != null && (it.startsWith("_") || it.endsWith("_")) } +} + fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L') fun hasUnsignedSuffix(text: String) = text.endsWith('u') || text.endsWith('U') fun hasUnsignedLongSuffix(text: String) =