[FIR] Implement RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER
Split underscore checkers
This commit is contained in:
+1
@@ -1070,6 +1070,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
|
|
||||||
val UNDERSCORE_IS_RESERVED by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
val UNDERSCORE_IS_RESERVED by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error<PsiElement>(PositioningStrategy.NAME_IDENTIFIER)
|
||||||
|
val RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER by warning<KtNameReferenceExpression>()
|
||||||
val INVALID_CHARACTERS by error<KtNamedDeclaration>(PositioningStrategy.NAME_IDENTIFIER) {
|
val INVALID_CHARACTERS by error<KtNamedDeclaration>(PositioningStrategy.NAME_IDENTIFIER) {
|
||||||
parameter<String>("message")
|
parameter<String>("message")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.psi.KtFunction
|
|||||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -556,6 +557,7 @@ object FirErrors {
|
|||||||
val DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH by error3<KtExpression, String, ConeKotlinType, ConeKotlinType>()
|
val DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH by error3<KtExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||||
val UNDERSCORE_IS_RESERVED by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
val UNDERSCORE_IS_RESERVED by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||||
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
val UNDERSCORE_USAGE_WITHOUT_BACKTICKS by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||||
|
val RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER by warning0<KtNameReferenceExpression>()
|
||||||
val INVALID_CHARACTERS by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
val INVALID_CHARACTERS by error1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||||
val DANGEROUS_CHARACTERS by warning1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
val DANGEROUS_CHARACTERS by warning1<KtNamedDeclaration, String>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||||
val EQUALITY_NOT_APPLICABLE by error3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
val EQUALITY_NOT_APPLICABLE by error3<KtBinaryExpression, String, ConeKotlinType, ConeKotlinType>()
|
||||||
|
|||||||
-1
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnonymousFunctionParametersChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirAnonymousFunctionParametersChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirReservedUnderscoreDeclarationChecker
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirAnonymousFunctionSyntaxChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirAnonymousFunctionSyntaxChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDelegationInInterfaceSyntaxChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirDelegationInInterfaceSyntaxChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirFunctionTypeParametersSyntaxChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirFunctionTypeParametersSyntaxChecker
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
|
|
||||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirReservedUnderscoreExpressionChecker,
|
FirUnderscoreChecker,
|
||||||
FirExpressionAnnotationChecker,
|
FirExpressionAnnotationChecker,
|
||||||
FirDeprecationChecker
|
FirDeprecationChecker
|
||||||
)
|
)
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
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.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
|
||||||
|
fun checkUnderscoreDiagnostics(
|
||||||
|
source: FirSourceElement?,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
isExpression: Boolean
|
||||||
|
) {
|
||||||
|
if (source != null && source.kind !is FirFakeSourceElementKind) {
|
||||||
|
with(SourceNavigator.forSource(source)) {
|
||||||
|
if (source.getRawIdentifier()?.isUnderscore == true) {
|
||||||
|
reporter.reportOn(
|
||||||
|
source,
|
||||||
|
if (isExpression) FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS else FirErrors.UNDERSCORE_IS_RESERVED,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val CharSequence.isUnderscore: Boolean
|
||||||
|
get() = all { it == '_' }
|
||||||
+68
-6
@@ -6,15 +6,22 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
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.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.getAncestors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.getAncestors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.nameIdentifier
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
|
||||||
|
import org.jetbrains.kotlin.psi.stubs.elements.KtTypeProjectionElementType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to answer source-related questions in generic fashion.
|
* Service to answer source-related questions in generic fashion.
|
||||||
@@ -26,17 +33,27 @@ interface SourceNavigator {
|
|||||||
|
|
||||||
fun FirTypeRef.isInTypeConstraint(): Boolean
|
fun FirTypeRef.isInTypeConstraint(): Boolean
|
||||||
|
|
||||||
|
fun FirSourceElement.getRawIdentifier(): String?
|
||||||
|
|
||||||
|
fun FirDeclaration.getRawName(): String?
|
||||||
|
|
||||||
|
fun FirValueParameterSymbol.isCatchElementParameter(): Boolean
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val lightTreeInstance = LightTreeSourceNavigator()
|
private val lightTreeInstance = LightTreeSourceNavigator()
|
||||||
|
|
||||||
fun forElement(e: FirElement): SourceNavigator = when (e.source) {
|
fun forElement(e: FirElement): SourceNavigator = forSource(e.source)
|
||||||
|
|
||||||
|
fun forSource(e: FirSourceElement?): SourceNavigator = when (e) {
|
||||||
is FirLightSourceElement -> lightTreeInstance
|
is FirLightSourceElement -> lightTreeInstance
|
||||||
is FirPsiSourceElement -> PsiSourceNavigator
|
is FirPsiSourceElement -> PsiSourceNavigator
|
||||||
null -> lightTreeInstance //shouldn't matter
|
null -> lightTreeInstance //shouldn't matter
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <R> FirElement.withNavigator(block: SourceNavigator.() -> R): R = with(forElement(this), block)
|
inline fun <R> FirElement.withNavigator(block: SourceNavigator.() -> R): R = with(forSource(this.source), block)
|
||||||
|
|
||||||
|
inline fun <R> FirSourceElement.withNavigator(block: SourceNavigator.() -> R): R = with(forSource(this), block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,16 +72,61 @@ open class LightTreeSourceNavigator : SourceNavigator {
|
|||||||
.find { it.tokenType == KtNodeTypes.TYPE_CONSTRAINT || it.tokenType == KtNodeTypes.TYPE_PARAMETER }
|
.find { it.tokenType == KtNodeTypes.TYPE_CONSTRAINT || it.tokenType == KtNodeTypes.TYPE_PARAMETER }
|
||||||
?.tokenType == KtNodeTypes.TYPE_CONSTRAINT
|
?.tokenType == KtNodeTypes.TYPE_CONSTRAINT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun FirSourceElement.getRawIdentifier(): String? {
|
||||||
|
val tokenType = elementType
|
||||||
|
return if (tokenType is KtNameReferenceExpressionElementType || tokenType == KtTokens.IDENTIFIER) {
|
||||||
|
lighterASTNode.toString()
|
||||||
|
} else if (tokenType is KtTypeProjectionElementType) {
|
||||||
|
lighterASTNode.getChildren(treeStructure).last().toString()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirDeclaration.getRawName(): String? {
|
||||||
|
return source?.let { it.treeStructure.nameIdentifier(it.lighterASTNode)?.toString() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||||
|
val localSource = source ?: return false
|
||||||
|
var parent = localSource.treeStructure.getParent(localSource.lighterASTNode)
|
||||||
|
parent?.let { parent = localSource.treeStructure.getParent(it) }
|
||||||
|
return parent?.tokenType == KtNodeTypes.CATCH
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//by default psi tree can reuse light tree manipulations
|
//by default psi tree can reuse light tree manipulations
|
||||||
object PsiSourceNavigator : LightTreeSourceNavigator() {
|
object PsiSourceNavigator : LightTreeSourceNavigator() {
|
||||||
|
|
||||||
//Swallows incorrect casts!!!
|
//Swallows incorrect casts!!!
|
||||||
private inline fun <reified P : PsiElement> FirElement.psi(): P? {
|
private inline fun <reified P : PsiElement> FirElement.psi(): P? = source?.psi()
|
||||||
val psi = (source as? FirPsiSourceElement)?.psi
|
|
||||||
|
private inline fun <reified P : PsiElement> FirSourceElement.psi(): P? {
|
||||||
|
val psi = (this as? FirPsiSourceElement)?.psi
|
||||||
return psi as? P
|
return psi as? P
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun FirTypeRef.isInConstructorCallee(): Boolean = psi<KtTypeReference>()?.parent is KtConstructorCalleeExpression
|
override fun FirTypeRef.isInConstructorCallee(): Boolean = psi<KtTypeReference>()?.parent is KtConstructorCalleeExpression
|
||||||
|
|
||||||
|
override fun FirSourceElement.getRawIdentifier(): String? {
|
||||||
|
val psi = psi<PsiElement>()
|
||||||
|
return 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirDeclaration.getRawName(): String? {
|
||||||
|
return (this.psi() as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirValueParameterSymbol.isCatchElementParameter(): Boolean {
|
||||||
|
return source?.psi<PsiElement>()?.parent?.parent is KtCatchClause
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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 org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkUnderscoreDiagnostics
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.isUnderscore
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
|
||||||
|
|
||||||
|
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
||||||
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
checkUnderscoreDiagnostics(import.aliasSource, context, reporter, isExpression = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportIfUnderscore(
|
||||||
|
declaration: FirDeclaration,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
isSingleUnderscoreAllowed: Boolean = false
|
||||||
|
) {
|
||||||
|
val declarationSource = declaration.source
|
||||||
|
if (declarationSource != null && declarationSource.kind !is FirFakeSourceElementKind) {
|
||||||
|
with(SourceNavigator.forElement(declaration)) {
|
||||||
|
val rawName = declaration.getRawName()
|
||||||
|
if (rawName?.isUnderscore == true && !(isSingleUnderscoreAllowed && rawName == "_")) {
|
||||||
|
reporter.reportOn(
|
||||||
|
declarationSource,
|
||||||
|
FirErrors.UNDERSCORE_IS_RESERVED,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val returnOrReceiverTypeRef = when (declaration) {
|
||||||
|
is FirValueParameter -> declaration.returnTypeRef
|
||||||
|
is FirFunction -> declaration.receiverTypeRef
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnOrReceiverTypeRef is FirResolvedTypeRef) {
|
||||||
|
val delegatedTypeRef = returnOrReceiverTypeRef.delegatedTypeRef
|
||||||
|
if (delegatedTypeRef is FirUserTypeRef) {
|
||||||
|
for (qualifierPart in delegatedTypeRef.qualifier) {
|
||||||
|
checkUnderscoreDiagnostics(qualifierPart.source, context, reporter, isExpression = true)
|
||||||
|
|
||||||
|
for (typeArgument in qualifierPart.typeArgumentList.typeArguments) {
|
||||||
|
checkUnderscoreDiagnostics(typeArgument.source, context, reporter, isExpression = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-171
@@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 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.expression
|
|
||||||
|
|
||||||
import com.intellij.psi.PsiNameIdentifierOwner
|
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
|
||||||
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.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) {
|
|
||||||
when (expression) {
|
|
||||||
is FirResolvable -> {
|
|
||||||
reportIfUnderscore(expression.calleeReference.source, context, reporter, isExpression = true)
|
|
||||||
}
|
|
||||||
is FirResolvedQualifier -> {
|
|
||||||
for (reservedUnderscoreDiagnostic in expression.nonFatalDiagnostics.filterIsInstance<ConeUnderscoreUsageWithoutBackticks>()) {
|
|
||||||
reporter.reportOn(reservedUnderscoreDiagnostic.source, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object FirReservedUnderscoreDeclarationChecker : FirBasicDeclarationChecker() {
|
|
||||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
|
||||||
if (
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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.aliasSource, context, reporter, isExpression = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportIfUnderscore(
|
|
||||||
declaration: FirDeclaration,
|
|
||||||
context: CheckerContext,
|
|
||||||
reporter: DiagnosticReporter,
|
|
||||||
isSingleUnderscoreAllowed: Boolean = false
|
|
||||||
) {
|
|
||||||
val declarationSource = declaration.source
|
|
||||||
val rawName = when (declarationSource) {
|
|
||||||
is FirPsiSourceElement ->
|
|
||||||
(declarationSource.psi as? PsiNameIdentifierOwner)?.nameIdentifier?.text
|
|
||||||
is FirLightSourceElement ->
|
|
||||||
declarationSource.treeStructure.nameIdentifier(declarationSource.lighterASTNode)?.toString()
|
|
||||||
else ->
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
reportIfUnderscore(rawName, declarationSource, context, reporter, isSingleUnderscoreAllowed)
|
|
||||||
|
|
||||||
val returnOrReceiverTypeRef = when (declaration) {
|
|
||||||
is FirValueParameter -> declaration.returnTypeRef
|
|
||||||
is FirFunction -> declaration.receiverTypeRef
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (returnOrReceiverTypeRef is FirResolvedTypeRef) {
|
|
||||||
val delegatedTypeRef = returnOrReceiverTypeRef.delegatedTypeRef
|
|
||||||
if (delegatedTypeRef is FirUserTypeRef) {
|
|
||||||
for (qualifierPart in delegatedTypeRef.qualifier) {
|
|
||||||
reportIfUnderscore(qualifierPart.source, context, reporter, isExpression = true)
|
|
||||||
|
|
||||||
for (typeArgument in qualifierPart.typeArgumentList.typeArguments) {
|
|
||||||
reportIfUnderscore(typeArgument.source, context, reporter, isExpression = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportIfUnderscore(
|
|
||||||
source: FirSourceElement?,
|
|
||||||
context: CheckerContext,
|
|
||||||
reporter: DiagnosticReporter,
|
|
||||||
isExpression: Boolean
|
|
||||||
) {
|
|
||||||
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 (rawName.isUnderscore && source.kind !is FirFakeSourceElementKind) {
|
|
||||||
reporter.reportOn(
|
|
||||||
source,
|
|
||||||
FirErrors.UNDERSCORE_IS_RESERVED,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val CharSequence.isUnderscore: Boolean
|
|
||||||
get() = all { it == '_' }
|
|
||||||
|
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkUnderscoreDiagnostics
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreUsageWithoutBackticks
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.SourceNavigator
|
||||||
|
|
||||||
|
object FirUnderscoreChecker : FirBasicExpressionChecker() {
|
||||||
|
private val singleUnderscore: Name = Name.identifier("_")
|
||||||
|
|
||||||
|
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
when (expression) {
|
||||||
|
is FirResolvable -> {
|
||||||
|
checkUnderscoreDiagnostics(expression.calleeReference.source, context, reporter, true)
|
||||||
|
checkResolvedToUnderscoreNamedCatchParameter(expression, context, reporter)
|
||||||
|
}
|
||||||
|
is FirResolvedQualifier -> {
|
||||||
|
for (reservedUnderscoreDiagnostic in expression.nonFatalDiagnostics.filterIsInstance<ConeUnderscoreUsageWithoutBackticks>()) {
|
||||||
|
reporter.reportOn(reservedUnderscoreDiagnostic.source, FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkResolvedToUnderscoreNamedCatchParameter(
|
||||||
|
expression: FirResolvable,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
val calleeReference = expression.calleeReference
|
||||||
|
val symbol = calleeReference.toResolvedCallableSymbol()
|
||||||
|
with(SourceNavigator.forElement(expression)) {
|
||||||
|
if (symbol is FirValueParameterSymbol && symbol.isCatchElementParameter() && symbol.name == singleUnderscore) {
|
||||||
|
reporter.reportOn(
|
||||||
|
calleeReference.source,
|
||||||
|
FirErrors.RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -340,6 +340,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESERVED_MEMBER_INSIDE_INLINE_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESOLUTION_TO_CLASSIFIER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESOLUTION_TO_CLASSIFIER
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESULT_TYPE_MISMATCH
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RESULT_TYPE_MISMATCH
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_FOR_BUILT_IN_SUSPEND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_FOR_BUILT_IN_SUSPEND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY
|
||||||
@@ -1400,6 +1401,10 @@ class FirDefaultErrorMessages {
|
|||||||
UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
|
UNDERSCORE_USAGE_WITHOUT_BACKTICKS,
|
||||||
"Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
"Names _, __, ___, ... can be used only in back-ticks (`_`, `__`, `___`, ...)"
|
||||||
)
|
)
|
||||||
|
map.put(
|
||||||
|
RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER,
|
||||||
|
"Referencing to an underscore-named parameter is deprecated. It will be an error in a future release."
|
||||||
|
)
|
||||||
map.put(
|
map.put(
|
||||||
INVALID_CHARACTERS,
|
INVALID_CHARACTERS,
|
||||||
"Name {0}",
|
"Name {0}",
|
||||||
|
|||||||
@@ -838,12 +838,17 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val NAME_IDENTIFIER: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
val NAME_IDENTIFIER: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
private fun KtTypeElement.getReferencedTypeExpression(): KtElement? {
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
return when (this) {
|
if (element is PsiNameIdentifierOwner) {
|
||||||
is KtUserType -> referenceExpression
|
val nameIdentifier = element.nameIdentifier
|
||||||
is KtNullableType -> innerType?.getReferencedTypeExpression()
|
if (nameIdentifier != null) {
|
||||||
is KtDefinitelyNotNullType -> innerType?.getReferencedTypeExpression()
|
return super.mark(nameIdentifier)
|
||||||
else -> null
|
}
|
||||||
|
} else if (element is KtLabelReferenceExpression) {
|
||||||
|
return super.mark(element.getReferencedNameElement())
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT.mark(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fun foo() {
|
|||||||
try {
|
try {
|
||||||
TODO()
|
TODO()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
`_`.stackTrace
|
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>.stackTrace
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
TODO()
|
TODO()
|
||||||
@@ -17,20 +17,20 @@ fun foo() {
|
|||||||
val x4 = { _: Int ->
|
val x4 = { _: Int ->
|
||||||
`_`
|
`_`
|
||||||
}
|
}
|
||||||
`_`
|
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>
|
||||||
}
|
}
|
||||||
`_`
|
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>
|
||||||
10
|
10
|
||||||
}
|
}
|
||||||
fun bar(x: Exception = `_`) {}
|
fun bar(x: Exception = <!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>) {}
|
||||||
class Bar(`_`: Exception = <!UNINITIALIZED_PARAMETER!>`_`<!>) {
|
class Bar(`_`: Exception = <!UNINITIALIZED_PARAMETER!>`_`<!>) {
|
||||||
inner class Bar2(x: Exception = `_`) { }
|
inner class Bar2(x: Exception = <!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
`_`.stackTrace
|
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>.stackTrace
|
||||||
val y1 = <!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>_<!>
|
val y1 = <!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER, UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>_<!>
|
||||||
val y2 = (`_`)
|
val y2 = (<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
TODO()
|
TODO()
|
||||||
@@ -38,7 +38,7 @@ fun foo() {
|
|||||||
try {
|
try {
|
||||||
TODO()
|
TODO()
|
||||||
} catch (x: Exception) {
|
} catch (x: Exception) {
|
||||||
`_`.stackTrace
|
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>.stackTrace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val boo1 = { `_`: Exception ->
|
val boo1 = { `_`: Exception ->
|
||||||
|
|||||||
+7
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.psi.KtFunction
|
|||||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -2876,6 +2877,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER) { firDiagnostic ->
|
||||||
|
ResolvedToUnderscoreNamedCatchParameterImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INVALID_CHARACTERS) { firDiagnostic ->
|
add(FirErrors.INVALID_CHARACTERS) { firDiagnostic ->
|
||||||
InvalidCharactersImpl(
|
InvalidCharactersImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+5
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.psi.KtFunction
|
|||||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -2011,6 +2012,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = UnderscoreUsageWithoutBackticks::class
|
override val diagnosticClass get() = UnderscoreUsageWithoutBackticks::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ResolvedToUnderscoreNamedCatchParameter : KtFirDiagnostic<KtNameReferenceExpression>() {
|
||||||
|
override val diagnosticClass get() = ResolvedToUnderscoreNamedCatchParameter::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class InvalidCharacters : KtFirDiagnostic<KtNamedDeclaration>() {
|
abstract class InvalidCharacters : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||||
override val diagnosticClass get() = InvalidCharacters::class
|
override val diagnosticClass get() = InvalidCharacters::class
|
||||||
abstract val message: String
|
abstract val message: String
|
||||||
|
|||||||
+8
@@ -53,6 +53,7 @@ import org.jetbrains.kotlin.psi.KtFunction
|
|||||||
import org.jetbrains.kotlin.psi.KtIfExpression
|
import org.jetbrains.kotlin.psi.KtIfExpression
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
||||||
|
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
@@ -3239,6 +3240,13 @@ internal class UnderscoreUsageWithoutBackticksImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ResolvedToUnderscoreNamedCatchParameterImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ResolvedToUnderscoreNamedCatchParameter(), KtAbstractFirDiagnostic<KtNameReferenceExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class InvalidCharactersImpl(
|
internal class InvalidCharactersImpl(
|
||||||
override val message: String,
|
override val message: String,
|
||||||
firDiagnostic: FirPsiDiagnostic,
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
|||||||
Reference in New Issue
Block a user