Skip to content

Commit

Permalink
Utility functions and convenience functions consolidated and placed t…
Browse files Browse the repository at this point in the history
…o LintUtils.kt
  • Loading branch information
Alexander Matečný committed Sep 29, 2023
1 parent 4c4fd3e commit ca4a1f7
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.skipParenthesizedExprDown
import org.jetbrains.uast.toUElement
import org.jetbrains.uast.tryResolveNamed
Expand Down Expand Up @@ -75,7 +71,6 @@ class DialogButtonsInContentSlotDetector : Detector(), SourceCodeScanner {
)
}
}

}

private fun PsiElement.findAllBlockExpressionsInHierarchy(): List<UBlockExpression> {
Expand All @@ -87,26 +82,4 @@ class DialogButtonsInContentSlotDetector : Detector(), SourceCodeScanner {

return expressions
}

private fun PsiMethod.getArgument(
node: UCallExpression,
argumentName: String,
): ULambdaExpression? = computeKotlinArgumentMapping(node, this)
.orEmpty()
.filter { (_, parameter) ->
parameter.name == argumentName
}
.keys
.filterIsInstance<ULambdaExpression>()
.firstOrNull()

private fun PsiMethod.isInPackageName(packageName: String): Boolean {
val actual = (containingFile as? PsiJavaFile)?.packageName
return packageName == actual
}

private fun PsiElement.getPackageName(): String? = when (this) {
is PsiMember -> this.containingClass?.qualifiedName?.let { it.substring(0, it.lastIndexOf(".")) }
else -> null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,45 @@

package kiwi.orbit.compose.lint.detectors

import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.toUElement

internal fun PsiMethod.isInPackageName(packageName: String): Boolean {
val actual = (containingFile as? PsiJavaFile)?.packageName
return packageName == actual
}

internal fun PsiElement.getPackageName(): String? = when (this) {
is PsiMember -> this.containingClass?.qualifiedName?.let { it.substring(0, it.lastIndexOf(".")) }
else -> null
}

/**
* Get arguments of a method. Useful for retrieving Compose Lambda expression used as arguments.
*/
internal fun PsiMethod.getArgument(
node: UCallExpression,
argumentName: String,
): ULambdaExpression? = computeKotlinArgumentMapping(node, this)
.orEmpty()
.filter { (_, parameter) ->
parameter.name == argumentName
}
.keys
.filterIsInstance<ULambdaExpression>()
.firstOrNull()

/**
* Returns a list of unreferenced parameters in [this]. If no parameters have been specified, but
* there is an implicit `it` parameter, this will return a list containing an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.USimpleNameReferenceExpression
import org.jetbrains.uast.getContainingUClass
import org.jetbrains.uast.toUElement
import org.jetbrains.uast.tryResolveNamed

Expand All @@ -33,8 +32,7 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
return object : UElementHandler() {
override fun visitCallExpression(node: UCallExpression) {
val name = node.methodName ?: return
val wrapperName = node.resolve()?.containingClass?.qualifiedName ?: return
val packageName = getPackageName(wrapperName)
val packageName = node.resolve()?.getPackageName()?: return
val fqn = "$packageName.$name"
val (preferredName) = METHOD_NAMES.entries.firstOrNull { it.value.contains(fqn) } ?: return

Expand All @@ -44,8 +42,7 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
val parentExpression = node.sourcePsi?.parents?.find { it is KtCallExpression }
val resolved = parentExpression.toUElement()?.tryResolveNamed()
val parentName = resolved?.name
val parentWrapper = resolved.toUElement()?.getContainingUClass()?.qualifiedName ?: ""
val parentPackage = getPackageName(parentWrapper)
val parentPackage = resolved?.getPackageName() ?: ""
val parentFqn = "$parentPackage.$parentName"
if (allowedEntry.value.find { parentFqn.contains(it) } != null) {
return
Expand Down Expand Up @@ -222,9 +219,5 @@ class MaterialDesignInsteadOrbitDesignDetector : Detector(), Detector.UastScanne
"Using $name instead of $preferredName",
)
}

private fun getPackageName(fullyQualifiedName: String): String {
return fullyQualifiedName.substring(0, fullyQualifiedName.lastIndexOf("."))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@ import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNamedElement
import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.skipParenthesizedExprDown
import org.jetbrains.uast.tryResolveNamed

Expand Down Expand Up @@ -51,7 +46,7 @@ class MaterialDialogWithOrbitButtonsDetector : Detector(), SourceCodeScanner {

override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
if (method.isInPackageName(PACKAGE_MATERIAL_ALERT)) {
val confirmButtonArgument = getArgument(node, method, MATERIAL_ALERT_CONFIRM_BUTTON_PARAM)
val confirmButtonArgument = method.getArgument(node, MATERIAL_ALERT_CONFIRM_BUTTON_PARAM)

(confirmButtonArgument?.body as? UBlockExpression)?.let { body ->
val resolvedBodyExpression = body.resolveFirstBodyExpression() ?: return@let
Expand All @@ -77,7 +72,7 @@ class MaterialDialogWithOrbitButtonsDetector : Detector(), SourceCodeScanner {
}
}

val dismissButtonArgument = getArgument(node, method, MATERIAL_ALERT_DISMISS_BUTTON_PARAM)
val dismissButtonArgument = method.getArgument(node, MATERIAL_ALERT_DISMISS_BUTTON_PARAM)

(dismissButtonArgument?.body as? UBlockExpression)?.let { body ->
val resolvedBodyExpression = body.resolveFirstBodyExpression() ?: return@let
Expand Down Expand Up @@ -105,29 +100,6 @@ class MaterialDialogWithOrbitButtonsDetector : Detector(), SourceCodeScanner {
}
}

private fun getArgument(
node: UCallExpression,
method: PsiMethod,
argumentName: String,
): ULambdaExpression? = computeKotlinArgumentMapping(node, method)
.orEmpty()
.filter { (_, parameter) ->
parameter.name == argumentName
}
.keys
.filterIsInstance<ULambdaExpression>()
.firstOrNull()

private fun PsiMethod.isInPackageName(packageName: String): Boolean {
val actual = (containingFile as? PsiJavaFile)?.packageName
return packageName == actual
}

private fun PsiElement.getPackageName(): String? = when (this) {
is PsiMember -> this.containingClass?.qualifiedName?.let { it.substring(0, it.lastIndexOf(".")) }
else -> null
}

private fun UBlockExpression.resolveFirstBodyExpression(): PsiNamedElement? {
return expressions.firstOrNull()?.skipParenthesizedExprDown()?.tryResolveNamed()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiMethod
import java.util.EnumSet
import org.jetbrains.uast.UCallExpression
Expand Down Expand Up @@ -86,9 +85,4 @@ class ScaffoldContentPaddingDetector :
}
}
}

private fun PsiMethod.isInPackageName(packageName: String): Boolean {
val actual = (containingFile as? PsiJavaFile)?.packageName
return packageName == actual
}
}

0 comments on commit ca4a1f7

Please sign in to comment.