Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SONARKT-453 Migrate DuplicateBranchCheck to kotlin-analysis-api #535

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -877,12 +877,15 @@ fun DeclarationDescriptor?.determineType(): KotlinType? =
else -> null
}

fun KtQualifiedExpression?.determineSignature(bindingContext: BindingContext): DeclarationDescriptor? =
when (val selectorExpr = this?.selectorExpression) {
is KtCallExpression -> bindingContext[BindingContext.REFERENCE_TARGET, selectorExpr.getCallNameExpression()]
is KtSimpleNameExpression -> bindingContext[BindingContext.REFERENCE_TARGET, selectorExpr]
fun KtQualifiedExpression?.determineSignature(): KaSymbol? = withKaSession {
when (val selectorExpr = this@determineSignature?.selectorExpression) {
is KtCallExpression ->
selectorExpr.getCallNameExpression()?.mainReference?.resolveToSymbol()
is KtSimpleNameExpression ->
selectorExpr.mainReference.resolveToSymbol()
else -> null
}
}

fun KtAnnotationEntry.annotatedElement(): KtAnnotated {
var annotated = parent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,41 +512,6 @@ private class ApiExtensionsKtDetermineTypeTest : AbstractApiExtensionsKtTest() {
}
}

private class ApiExtensionsKtDetermineSignatureTest : AbstractApiExtensionsKtTest() {
private val bindingContext: BindingContext
private val ktFile: KtFile

init {
val kotlinTree = parse(
"""
package bar

class Foo {
val prop: Int = 0

fun aFun(param: Float): Long {
this.prop
}
}
""".trimIndent()
)
bindingContext = kotlinTree.bindingContext
ktFile = kotlinTree.psiFile
}

@Test
fun `determineSignature of KtQualifiedExpression`() {
val expr = ktFile.findDescendantOfType<KtQualifiedExpression> { it.text == "this.prop" }!!

assertThat(expr.determineSignature(bindingContext)?.fqNameOrNull()?.asString()).isEqualTo("bar.Foo.prop")
}

@Test
fun `determineSignature of a null KtQualifiedExpression`() {
assertThat(null.determineSignature(bindingContext)).isNull()
}
}

private class ApiExtensionsScopeFunctionResolutionTest : AbstractApiExtensionsKtTest() {
private fun generateAst(funContent: String) = """
package bar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ package org.sonarsource.kotlin.checks
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtQualifiedExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.determineSignature
import org.sonarsource.kotlin.api.reporting.SecondaryLocation
import org.sonarsource.kotlin.api.reporting.KotlinTextRanges.textRange
import org.sonarsource.kotlin.api.frontend.KotlinFileContext

@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1871")
class DuplicateBranchCheck : AbstractBranchDuplication() {

Expand All @@ -36,7 +34,7 @@ class DuplicateBranchCheck : AbstractBranchDuplication() {
group.asSequence()
.drop(1)
.filter { spansMultipleLines(it, ctx) }
.filter { it !is KtQualifiedExpression || it.hasSameSignature(original as KtQualifiedExpression, ctx.bindingContext) }
.filter { it !is KtQualifiedExpression || it.hasSameSignature(original as KtQualifiedExpression) }
.forEach { duplicated ->
val originalRange = ctx.textRange(original)
ctx.reportIssue(
Expand All @@ -53,14 +51,13 @@ class DuplicateBranchCheck : AbstractBranchDuplication() {
}
}

private fun KtQualifiedExpression.hasSameSignature(other: KtQualifiedExpression, bindingContext: BindingContext): Boolean =
this.determineSignature(bindingContext) == other.determineSignature(bindingContext)

private fun KtQualifiedExpression.hasSameSignature(other: KtQualifiedExpression): Boolean =
[email protected]() == other.determineSignature()

private fun spansMultipleLines(tree: KtElement, ctx: KotlinFileContext): Boolean {
if (tree is KtBlockExpression) {
val statements = tree.statements
if (statements.isNullOrEmpty()) {
if (statements.isEmpty()) {
return false
}
val firstStatement = statements[0]
Expand Down
Loading