[FIR] Optimize performance and fix UNDERSCORE_IS_RESERVED, simplify code
This commit is contained in:
+2
-2
@@ -1068,8 +1068,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<ConeKotlinType>("actualType")
|
||||
}
|
||||
|
||||
val UNDERSCORE_IS_RESERVED by error<KtElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<KtElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_IS_RESERVED by error<PsiElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<PsiElement>(PositioningStrategy.RESERVED_UNDERSCORE)
|
||||
|
||||
val EQUALITY_NOT_APPLICABLE by error<KtBinaryExpression> {
|
||||
parameter<String>("operator")
|
||||
|
||||
+2
-2
@@ -554,8 +554,8 @@ object FirErrors {
|
||||
val DELEGATE_SPECIAL_FUNCTION_AMBIGUITY by error2<KtExpression, String, Collection<FirBasedSymbol<*>>>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE by error2<KtExpression, String, Collection<FirBasedSymbol<*>>>()
|
||||
val DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH by error3<KtExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val UNDERSCORE_IS_RESERVED by error0<KtElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<KtElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_IS_RESERVED by error0<PsiElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<PsiElement>(SourceElementPositioningStrategies.RESERVED_UNDERSCORE)
|
||||
val EQUALITY_NOT_APPLICABLE by error3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val EQUALITY_NOT_APPLICABLE_WARNING by warning3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||
val INCOMPATIBLE_ENUM_COMPARISON_ERROR by error2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
|
||||
+92
-130
@@ -5,108 +5,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreUsageWithoutBackticks
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.text
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtDotQualifiedExpressionElementType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtTypeProjectionElementType
|
||||
|
||||
object FirReservedUnderscoreExpressionChecker : FirBasicExpressionChecker() {
|
||||
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = expression.source
|
||||
|
||||
if (expression is FirFunctionCall) {
|
||||
val calleeReferenceSource = expression.calleeReference.source
|
||||
if (calleeReferenceSource is FirLightSourceElement && calleeReferenceSource.lighterASTNode.tokenType == KtNodeTypes.OPERATION_REFERENCE) {
|
||||
return
|
||||
when (expression) {
|
||||
is FirResolvable -> {
|
||||
reportIfUnderscore(expression.calleeReference.source, context, reporter, isExpression = true)
|
||||
}
|
||||
|
||||
reportIfUnderscore(
|
||||
expression.calleeReference.source.text, expression.calleeReference.source, context, reporter,
|
||||
isExpression = true
|
||||
)
|
||||
} else if (expression is FirQualifiedAccess) {
|
||||
if (source is FirPsiSourceElement) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
} else if (source is FirLightSourceElement) {
|
||||
reportIfUnderscoreInQualifiedAccess(source, expression, context, reporter)
|
||||
}
|
||||
} else if (expression is FirGetClassCall) {
|
||||
for (argument in expression.argumentList.arguments) {
|
||||
reportIfUnderscore(argument.source.text, expression.source, context, reporter, isExpression = true)
|
||||
}
|
||||
} else if (expression is FirReturnExpression) {
|
||||
var labelName: String? = null
|
||||
if (source is FirPsiSourceElement) {
|
||||
labelName = (source.psi.parent as? KtLabeledExpression)?.getLabelName()
|
||||
} else if (source is FirLightSourceElement) {
|
||||
val parent = source.treeStructure.getParent(source.lighterASTNode)
|
||||
if (parent != null && parent.tokenType == KtNodeTypes.LABELED_EXPRESSION) {
|
||||
labelName = source.treeStructure.findDescendantByType(parent, KtNodeTypes.LABEL).toString()
|
||||
labelName = labelName.substring(0, labelName.length - 1)
|
||||
is FirResolvedQualifier -> {
|
||||
for (reservedUnderscoreDiagnostic in expression.nonFatalDiagnostics.filterIsInstance<ConeUnderscoreUsageWithoutBackticks>()) {
|
||||
reporter.reportOn(reservedUnderscoreDiagnostic.source, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
||||
}
|
||||
}
|
||||
|
||||
reportIfUnderscore(labelName, expression.source, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirPsiSourceElement,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(psi: PsiElement?) {
|
||||
if (psi is KtNameReferenceExpression) {
|
||||
reportIfUnderscore(psi.text, expression.source, context, reporter, isExpression = true)
|
||||
} else if (psi is KtDotQualifiedExpression || psi is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi.firstChild)
|
||||
processQualifiedAccess(psi.lastChild)
|
||||
}
|
||||
}
|
||||
|
||||
val psi = source.psi
|
||||
if (psi.parent !is KtDotQualifiedExpression && psi.parent !is KtCallableReferenceExpression) {
|
||||
processQualifiedAccess(psi)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscoreInQualifiedAccess(
|
||||
source: FirLightSourceElement,
|
||||
expression: FirStatement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
fun processQualifiedAccess(lightSourceElement: LighterASTNode?) {
|
||||
val tokenType = lightSourceElement?.tokenType
|
||||
if (tokenType is KtNameReferenceExpressionElementType) {
|
||||
reportIfUnderscore(lightSourceElement.toString(), expression.source, context, reporter, isExpression = true)
|
||||
} else if (lightSourceElement != null && (tokenType is KtDotQualifiedExpressionElementType || tokenType == KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION)) {
|
||||
val children = lightSourceElement.getChildren(source.treeStructure)
|
||||
processQualifiedAccess(children.first())
|
||||
processQualifiedAccess(children.last())
|
||||
}
|
||||
}
|
||||
|
||||
val astNode = source.lighterASTNode
|
||||
val parent = source.treeStructure.getParent(astNode)
|
||||
if (parent?.tokenType !is KtDotQualifiedExpressionElementType && parent?.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION) {
|
||||
processQualifiedAccess(astNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,27 +40,29 @@ object FirReservedUnderscoreExpressionChecker : FirBasicExpressionChecker() {
|
||||
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (
|
||||
declaration is FirClass ||
|
||||
declaration is FirFunction ||
|
||||
declaration is FirRegularClass ||
|
||||
declaration is FirTypeParameter ||
|
||||
declaration is FirProperty ||
|
||||
declaration is FirTypeAlias
|
||||
) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
} else if (declaration is FirFunction) {
|
||||
if (declaration is FirSimpleFunction) {
|
||||
reportIfUnderscore(declaration, context, reporter)
|
||||
}
|
||||
|
||||
if (declaration is FirFunction) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
reportIfUnderscore(
|
||||
parameter,
|
||||
context,
|
||||
reporter,
|
||||
isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
|
||||
)
|
||||
}
|
||||
val isSingleUnderscoreAllowed = declaration is FirAnonymousFunction || declaration is FirPropertyAccessor
|
||||
for (parameter in declaration.valueParameters) {
|
||||
reportIfUnderscore(
|
||||
parameter,
|
||||
context,
|
||||
reporter,
|
||||
isSingleUnderscoreAllowed = isSingleUnderscoreAllowed
|
||||
)
|
||||
}
|
||||
} else if (declaration is FirFile) {
|
||||
for (import in declaration.imports) {
|
||||
reportIfUnderscore(import.aliasName?.asString(), import.source, context, reporter)
|
||||
reportIfUnderscore(import.aliasSource, context, reporter, isExpression = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,64 +74,98 @@ private fun reportIfUnderscore(
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false
|
||||
) {
|
||||
val source = declaration.source
|
||||
val rawIdentifier = when (source) {
|
||||
val declarationSource = declaration.source
|
||||
val rawName = when (declarationSource) {
|
||||
is FirPsiSourceElement ->
|
||||
(source.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||
(declarationSource.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||
is FirLightSourceElement ->
|
||||
source.treeStructure.nameIdentifier(source.lighterASTNode)?.toString()
|
||||
declarationSource.treeStructure.nameIdentifier(declarationSource.lighterASTNode)?.toString()
|
||||
else ->
|
||||
null
|
||||
}
|
||||
|
||||
reportIfUnderscore(rawIdentifier, source, context, reporter, isSingleUnderscoreAllowed)
|
||||
reportIfUnderscore(rawName, declarationSource, context, reporter, isSingleUnderscoreAllowed)
|
||||
|
||||
val returnOrReceiverTypeRef = when (declaration) {
|
||||
is FirValueParameter -> declaration.returnTypeRef.source
|
||||
is FirFunction -> declaration.receiverTypeRef?.source
|
||||
is FirValueParameter -> declaration.returnTypeRef
|
||||
is FirFunction -> declaration.receiverTypeRef
|
||||
else -> null
|
||||
}
|
||||
|
||||
val isReportUnderscoreInReturnOrReceiverTypeRef = when (returnOrReceiverTypeRef) {
|
||||
is FirPsiSourceElement -> {
|
||||
val psi = returnOrReceiverTypeRef.psi
|
||||
psi is KtTypeReference && psi.anyDescendantOfType<LeafPsiElement> { isUnderscore(it.text) }
|
||||
}
|
||||
is FirLightSourceElement -> {
|
||||
val lighterASTNode = returnOrReceiverTypeRef.lighterASTNode
|
||||
lighterASTNode.tokenType == KtNodeTypes.TYPE_REFERENCE &&
|
||||
source?.treeStructure?.findFirstDescendant(lighterASTNode)
|
||||
{ it.tokenType == KtNodeTypes.REFERENCE_EXPRESSION && isUnderscore(it.toString()) } != null
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
if (returnOrReceiverTypeRef is FirResolvedTypeRef) {
|
||||
val delegatedTypeRef = returnOrReceiverTypeRef.delegatedTypeRef
|
||||
if (delegatedTypeRef is FirUserTypeRef) {
|
||||
for (qualifierPart in delegatedTypeRef.qualifier) {
|
||||
reportIfUnderscore(qualifierPart.source, context, reporter, isExpression = true)
|
||||
|
||||
if (isReportUnderscoreInReturnOrReceiverTypeRef) {
|
||||
reporter.reportOn(returnOrReceiverTypeRef, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
||||
for (typeArgument in qualifierPart.typeArgumentList.typeArguments) {
|
||||
reportIfUnderscore(typeArgument.source, context, reporter, isExpression = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
text: CharSequence?,
|
||||
source: FirSourceElement?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean = false,
|
||||
isExpression: Boolean = false
|
||||
isExpression: Boolean
|
||||
) {
|
||||
if (text == null || isSingleUnderscoreAllowed && text == "_") {
|
||||
if (source != null && source.kind !is FirFakeSourceElementKind) {
|
||||
var rawName: String? = null
|
||||
if (source is FirPsiSourceElement) {
|
||||
val psi = source.psi
|
||||
rawName = if (psi is KtNameReferenceExpression) {
|
||||
psi.getReferencedNameElement().node.text
|
||||
} else if (psi is KtTypeProjection) {
|
||||
psi.typeReference?.typeElement?.text
|
||||
} else if (psi is LeafPsiElement && psi.elementType == KtTokens.IDENTIFIER) {
|
||||
psi.text
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else if (source is FirLightSourceElement) {
|
||||
val tokenType = source.elementType
|
||||
rawName = if (tokenType is KtNameReferenceExpressionElementType || tokenType == KtTokens.IDENTIFIER) {
|
||||
source.lighterASTNode.toString()
|
||||
} else if (tokenType is KtTypeProjectionElementType) {
|
||||
source.lighterASTNode.getChildren(source.treeStructure).last().toString()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
if (rawName?.isUnderscore == true) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportIfUnderscore(
|
||||
rawName: CharSequence?,
|
||||
source: FirSourceElement?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
isSingleUnderscoreAllowed: Boolean
|
||||
) {
|
||||
if (source == null || rawName == null || isSingleUnderscoreAllowed && rawName == "_") {
|
||||
return
|
||||
}
|
||||
|
||||
if (isUnderscore(text)) {
|
||||
if (rawName.isUnderscore && source.kind !is FirFakeSourceElementKind) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
FirErrors.UNDERSCORE_IS_RESERVED,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isUnderscore(text: CharSequence) = text.all { it == '_' }
|
||||
val CharSequence.isUnderscore: Boolean
|
||||
get() = all { it == '_' }
|
||||
|
||||
|
||||
+10
@@ -387,6 +387,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_OF
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_VARIANCE_CONFLICT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNDERSCORE_IS_RESERVED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY
|
||||
@@ -1388,6 +1390,14 @@ class FirDefaultErrorMessages {
|
||||
RENDER_TYPE,
|
||||
RENDER_TYPE,
|
||||
)
|
||||
map.put(
|
||||
UNDERSCORE_IS_RESERVED,
|
||||
"Names _, __, ___, ..., are reserved in Kotlin"
|
||||
)
|
||||
map.put(
|
||||
UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
|
||||
"Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
||||
)
|
||||
map.put(
|
||||
EQUALITY_NOT_APPLICABLE,
|
||||
"Operator ''{0}'' cannot be applied to ''{1}'' and ''{2}''",
|
||||
|
||||
+6
-13
@@ -715,20 +715,13 @@ object LightTreePositioningStrategies {
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
if (node.tokenType == KtNodeTypes.RETURN) {
|
||||
val parent = tree.getParent(node)
|
||||
if (parent != null) {
|
||||
val label = tree.findDescendantByType(parent, KtNodeTypes.LABEL)
|
||||
if (label != null) {
|
||||
return markElement(label, startOffset, endOffset - 1, tree, node)
|
||||
}
|
||||
}
|
||||
val nameIdentifier = tree.nameIdentifier(node)
|
||||
if (nameIdentifier != null) {
|
||||
return markElement(nameIdentifier, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType == KtNodeTypes.LABEL_QUALIFIER) {
|
||||
return super.mark(node, startOffset, endOffset - 1, tree)
|
||||
}
|
||||
|
||||
val descendants =
|
||||
tree.collectDescendantsOfType(node, KtTokens.IDENTIFIER) { descendant -> descendant.toString().all { it == '_' } }
|
||||
if (descendants.isNotEmpty())
|
||||
return descendants.map { markSingleElement(it, it, startOffset, endOffset, tree, node) }
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeNotAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreIsReserved
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||
@@ -969,9 +966,16 @@ class ExpressionsConverter(
|
||||
private fun convertSimpleNameExpression(referenceExpression: LighterASTNode): FirQualifiedAccessExpression {
|
||||
return buildQualifiedAccessExpression {
|
||||
source = referenceExpression.toFirSourceElement()
|
||||
|
||||
val nameSource = this@buildQualifiedAccessExpression.source
|
||||
val rawText = referenceExpression.asText
|
||||
if (nameSource != null && rawText.isUnderscore) {
|
||||
nonFatalDiagnostics.add(ConeUnderscoreUsageWithoutBackticks(nameSource))
|
||||
}
|
||||
|
||||
calleeReference = buildSimpleNamedReference {
|
||||
source = this@buildQualifiedAccessExpression.source
|
||||
name = referenceExpression.asText.nameAsSafeName()
|
||||
source = nameSource
|
||||
name = rawText.nameAsSafeName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,7 +1054,7 @@ open class RawFirBuilder(
|
||||
null,
|
||||
ClassKind.CLASS,
|
||||
containerTypeParameters = emptyList(),
|
||||
containingClassIsExpectClass = false
|
||||
containingClassIsExpectClass = false
|
||||
)
|
||||
|
||||
for (declaration in objectDeclaration.declarations) {
|
||||
@@ -1667,7 +1667,20 @@ open class RawFirBuilder(
|
||||
expression.getQualifiedExpressionForSelector() != null -> expression.parent
|
||||
else -> expression
|
||||
}.toFirSourceElement()
|
||||
return generateAccessExpression(qualifiedSource, expression.toFirSourceElement(), expression.getReferencedNameAsName())
|
||||
|
||||
val expressionSource = expression.toFirSourceElement()
|
||||
var diagnostic: ConeDiagnostic? = null
|
||||
val rawText = expression.getReferencedNameElement().node.text
|
||||
if (rawText.isUnderscore) {
|
||||
diagnostic = ConeUnderscoreUsageWithoutBackticks(expressionSource)
|
||||
}
|
||||
|
||||
return generateAccessExpression(
|
||||
qualifiedSource,
|
||||
expressionSource,
|
||||
expression.getReferencedNameAsName(),
|
||||
diagnostic
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitConstantExpression(expression: KtConstantExpression, data: Unit): FirElement =
|
||||
|
||||
+6
-1
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
@@ -250,7 +251,8 @@ private fun FirExpression.createConventionCall(
|
||||
fun generateAccessExpression(
|
||||
qualifiedSource: FirSourceElement?,
|
||||
calleeReferenceSource: FirSourceElement?,
|
||||
name: Name
|
||||
name: Name,
|
||||
diagnostic: ConeDiagnostic? = null
|
||||
): FirQualifiedAccessExpression =
|
||||
buildQualifiedAccessExpression {
|
||||
this.source = qualifiedSource
|
||||
@@ -258,6 +260,9 @@ fun generateAccessExpression(
|
||||
this.source = calleeReferenceSource
|
||||
this.name = name
|
||||
}
|
||||
if (diagnostic != null) {
|
||||
this.nonFatalDiagnostics.add(diagnostic)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateResolvedAccessExpression(source: FirSourceElement?, variable: FirVariable): FirQualifiedAccessExpression =
|
||||
|
||||
@@ -844,20 +844,10 @@ object PositioningStrategies {
|
||||
if (nameIdentifier != null) {
|
||||
return super.mark(nameIdentifier)
|
||||
}
|
||||
} else if (element is KtImportDirective) {
|
||||
return super.mark(element.alias?.nameIdentifier ?: element)
|
||||
} else if (element is KtReturnExpression) {
|
||||
val prevSibling = element.getPrevSiblingIgnoringWhitespace()
|
||||
if (prevSibling is KtContainerNode) {
|
||||
return mark(prevSibling)
|
||||
}
|
||||
} else if (element !is LeafPsiElement) {
|
||||
val ranges = element.collectDescendantsOfType<LeafPsiElement> { descendant -> descendant.text.all { it == '_' } }
|
||||
.map { markSingleElement(it) }
|
||||
if (ranges.isNotEmpty()) {
|
||||
return ranges
|
||||
}
|
||||
} else if (element is KtLabelReferenceExpression) {
|
||||
return super.mark(element.getReferencedNameElement())
|
||||
}
|
||||
|
||||
return super.mark(element)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -2,9 +2,9 @@
|
||||
|
||||
import kotlin.Deprecated as <!UNDERSCORE_IS_RESERVED!>___<!>
|
||||
|
||||
@___("") data class Pair(val x: Int, val y: Int)
|
||||
@<!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>___<!>("") data class Pair(val x: Int, val y: Int)
|
||||
|
||||
class <!UNDERSCORE_IS_RESERVED, UNDERSCORE_IS_RESERVED!>_<!><<!UNDERSCORE_IS_RESERVED!>________<!>>
|
||||
class <!UNDERSCORE_IS_RESERVED!>_<!><<!UNDERSCORE_IS_RESERVED!>________<!>>
|
||||
val <!UNDERSCORE_IS_RESERVED!>______<!> = <!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>_<!><Int>()
|
||||
|
||||
fun <!UNDERSCORE_IS_RESERVED!>__<!>(<!UNDERSCORE_IS_RESERVED!>___<!>: Int, y: <!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>_<!><Int>?): Int {
|
||||
@@ -25,7 +25,7 @@ fun <!UNDERSCORE_IS_RESERVED!>__<!>(<!UNDERSCORE_IS_RESERVED!>___<!>: Int, y: <!
|
||||
}
|
||||
|
||||
|
||||
class A1(val <!UNDERSCORE_IS_RESERVED, UNDERSCORE_IS_RESERVED!>_<!>: String)
|
||||
class A1(val <!UNDERSCORE_IS_RESERVED!>_<!>: String)
|
||||
class A2(<!UNDERSCORE_IS_RESERVED!>_<!>: String) {
|
||||
class B {
|
||||
typealias <!UNDERSCORE_IS_RESERVED!>_<!> = CharSequence
|
||||
@@ -48,3 +48,13 @@ val something2 = doIt { _ -> 1 }
|
||||
var p: Int?
|
||||
get() = null
|
||||
set(_) {}
|
||||
|
||||
object `____` {
|
||||
object Nested {
|
||||
fun method() {}
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>____<!>.Nested.method()
|
||||
}
|
||||
|
||||
@@ -48,3 +48,13 @@ val something2 = doIt { _ -> 1 }
|
||||
var p: Int?
|
||||
get() = null
|
||||
set(_) {}
|
||||
|
||||
object `____` {
|
||||
object Nested {
|
||||
fun method() {}
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
<!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>____<!>.Nested.method()
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ public val something2: kotlin.Any?
|
||||
public fun __(/*0*/ ___: kotlin.Int, /*1*/ y: _<kotlin.Int>?): kotlin.Int
|
||||
public fun doIt(/*0*/ f: (kotlin.Any?) -> kotlin.Any?): kotlin.Any?
|
||||
public fun oneUnderscore(/*0*/ <anonymous parameter 0>: kotlin.Int): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public final class A1 {
|
||||
public constructor A1(/*0*/ _: kotlin.String)
|
||||
@@ -53,3 +54,18 @@ public final class _</*0*/ ________> {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object ____ {
|
||||
private constructor ____()
|
||||
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
|
||||
|
||||
public object Nested {
|
||||
private constructor Nested()
|
||||
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 method(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package test
|
||||
|
||||
annotation class `__`(val value: String)
|
||||
|
||||
@__("") class TestAnn
|
||||
@`__`("") class TestAnn2
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
package test
|
||||
|
||||
annotation class `__`(val value: String)
|
||||
|
||||
+2
-2
@@ -2003,11 +2003,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val actualType: KtType
|
||||
}
|
||||
|
||||
abstract class UnderscoreIsReserved : KtFirDiagnostic<KtElement>() {
|
||||
abstract class UnderscoreIsReserved : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = UnderscoreIsReserved::class
|
||||
}
|
||||
|
||||
abstract class UnderscoreUsageWithoutBackticks : KtFirDiagnostic<KtElement>() {
|
||||
abstract class UnderscoreUsageWithoutBackticks : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = UnderscoreUsageWithoutBackticks::class
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -3228,14 +3228,14 @@ internal class DelegateSpecialFunctionReturnTypeMismatchImpl(
|
||||
internal class UnderscoreIsReservedImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.UnderscoreIsReserved(), KtAbstractFirDiagnostic<KtElement> {
|
||||
) : KtFirDiagnostic.UnderscoreIsReserved(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class UnderscoreUsageWithoutBackticksImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.UnderscoreUsageWithoutBackticks(), KtAbstractFirDiagnostic<KtElement> {
|
||||
) : KtFirDiagnostic.UnderscoreUsageWithoutBackticks(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user