[FIR] Add redundant single string expression template checker

This commit is contained in:
vldf
2020-07-27 14:49:22 +03:00
committed by Mikhail Glukhikh
parent 95e0ba3d5c
commit b10defdbab
6 changed files with 100 additions and 1 deletions
@@ -0,0 +1,11 @@
val x = "Hello"
val y = "$<!REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE!>x<!>"
val z = "${y.hashCode()}"
fun toString(x: String) = "IC$x"
data class ProductGroup(val short_name: String, val parent: ProductGroup?) {
val name: String = if (parent == null) short_name else "${parent.name} $short_name"
}
@@ -0,0 +1,39 @@
FILE: RedundantSingleExpressionStringTemplateChecker.kt
public final val x: R|kotlin/String| = String(Hello)
public get(): R|kotlin/String|
public final val y: R|kotlin/String| = R|/x|.R|kotlin/Any.toString|()
public get(): R|kotlin/String|
public final val z: R|kotlin/String| = R|/y|.R|kotlin/Any.hashCode|().R|kotlin/Any.toString|()
public get(): R|kotlin/String|
public final fun toString(x: R|kotlin/String|): R|kotlin/String| {
^toString <strcat>(String(IC), R|<local>/x|.R|kotlin/Any.toString|())
}
public final data class ProductGroup : R|kotlin/Any| {
public constructor(short_name: R|kotlin/String|, parent: R|ProductGroup?|): R|ProductGroup| {
super<R|kotlin/Any|>()
}
public final val short_name: R|kotlin/String| = R|<local>/short_name|
public get(): R|kotlin/String|
public final val parent: R|ProductGroup?| = R|<local>/parent|
public get(): R|ProductGroup?|
public final val name: R|kotlin/String| = when () {
==(R|<local>/parent|, Null(null)) -> {
R|<local>/short_name|
}
else -> {
<strcat>(R|<local>/parent|.R|/ProductGroup.name|.R|kotlin/Any.toString|(), String( ), R|<local>/short_name|.R|kotlin/Any.toString|())
}
}
public get(): R|kotlin/String|
public final fun component1(): R|kotlin/String|
public final fun component2(): R|ProductGroup?|
public final fun copy(short_name: R|kotlin/String| = this@R|/ProductGroup|.R|/ProductGroup.short_name|, parent: R|ProductGroup?| = this@R|/ProductGroup|.R|/ProductGroup.parent|): R|ProductGroup|
}
@@ -48,6 +48,11 @@ public class ExtendedFirDiagnosticsTestGenerated extends AbstractExtendedFirDiag
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt"); runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt");
} }
@TestMetadata("RedundantSingleExpressionStringTemplateChecker.kt")
public void testRedundantSingleExpressionStringTemplateChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantSingleExpressionStringTemplateChecker.kt");
}
@TestMetadata("RedundantVisibilityModifierChecker.kt") @TestMetadata("RedundantVisibilityModifierChecker.kt")
public void testRedundantVisibilityModifierChecker() throws Exception { public void testRedundantVisibilityModifierChecker() throws Exception {
runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantVisibilityModifierChecker.kt"); runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantVisibilityModifierChecker.kt");
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.analysis.checkers.extended.ArrayEqualityCanBeReplacedWithEquals import org.jetbrains.kotlin.fir.analysis.checkers.extended.ArrayEqualityCanBeReplacedWithEquals
import org.jetbrains.kotlin.fir.analysis.checkers.extended.CanBeReplacedWithOperatorAssignmentChecker import org.jetbrains.kotlin.fir.analysis.checkers.extended.CanBeReplacedWithOperatorAssignmentChecker
import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantSingleExpressionStringTemplateChecker
object ExtendedExpressionCheckers : ExpressionCheckers() { object ExtendedExpressionCheckers : ExpressionCheckers() {
override val expressionCheckers: List<FirBasicExpresionChecker> = listOf( override val expressionCheckers: List<FirBasicExpresionChecker> = listOf(
ArrayEqualityCanBeReplacedWithEquals ArrayEqualityCanBeReplacedWithEquals,
RedundantSingleExpressionStringTemplateChecker
) )
override val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = listOf( override val variableAssignmentCheckers: List<FirVariableAssignmentChecker> = listOf(
CanBeReplacedWithOperatorAssignmentChecker CanBeReplacedWithOperatorAssignmentChecker
@@ -0,0 +1,39 @@
/*
* 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.extended
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpresionChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
object RedundantSingleExpressionStringTemplateChecker : FirBasicExpresionChecker() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
if (expression.source?.kind != FirFakeSourceElementKind.GeneratedToStringCallOnTemplateEntry) return
if (expression !is FirFunctionCall) return
if (
expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String
&& expression.psi?.findStringParent()?.children?.size == 1 // there is no more children in original string template
) {
reporter.report(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE)
}
}
private fun PsiElement.findStringParent(): KtStringTemplateExpression? {
if (this is KtStringTemplateExpression) return this
return if (this.parent != null) this.parent.findStringParent()
else null
}
}
@@ -89,7 +89,10 @@ object FirErrors {
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, PsiElement>() val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>() val REDUNDANT_RETURN_UNIT_TYPE by warning0<FirSourceElement, PsiTypeElement>()
val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>() val REDUNDANT_EXPLICIT_TYPE by warning0<FirSourceElement, PsiElement>()
val REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE by warning0<FirSourceElement, PsiElement>()
val CAN_BE_VAL by warning0<FirSourceElement, PsiElement>() val CAN_BE_VAL by warning0<FirSourceElement, PsiElement>()
val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, PsiElement>() val CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT by warning0<FirSourceElement, PsiElement>()
val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, PsiElement>() val ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS by warning0<FirSourceElement, PsiElement>()
} }