Skip to content

Commit

Permalink
Merge pull request #10 from udaan-com/image-quality-rule
Browse files Browse the repository at this point in the history
APP2-6203 : Added Performance rules: ImageQuality, ImageWidth
  • Loading branch information
rajeshdixitudaan authored Jan 31, 2022
2 parents c437547 + af55d5a commit 93fe7be
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ class SideKtRuleSetProvider : RuleSetProvider {
JerseyMethodParameterDefaultValue(config),
JerseyMainThreadBlockingCall(config),
ResourceOnboardedOnAsec(config),
SQLQuerySniffer(config)
SQLQuerySniffer(config),
ImageQuality(config),
ImageWidth(config)
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.github.thewisenerd.linters.sidekt.rules

import io.github.thewisenerd.linters.sidekt.helpers.Debugger
import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Debt
import io.gitlab.arturbosch.detekt.api.Entity
import io.gitlab.arturbosch.detekt.api.Issue
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.api.Severity
import org.jetbrains.kotlin.psi.KtStringTemplateExpression

class ImageQuality(config: Config) : Rule(config) {

private val cloudinaryRefUrlForQuality = "https://cloudinary.com/documentation/image_optimization#automatic_quality_selection_q_auto."

private val debugStream by lazy {
valueOrNull<String>("debug")?.let {
Debugger.getOutputStreamForDebugger(it)
}
}

override val issue: Issue = Issue(
id = ImageQuality::class.java.simpleName,
severity = Severity.Performance,
description = "Wasteful parameters w_768/q_75 detected.",
debt = Debt.TEN_MINS
)

override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) {
super.visitStringTemplateExpression(expression)
val dbg = Debugger.make(ImageQuality::class.java.simpleName, debugStream)
val text = expression.text
val patternQuality = Regex("https://ud-img.azureedge.net/.*q_75.*")
if(patternQuality.containsMatchIn(text)) {
dbg.i("Wasteful parameters detected q_75 in string $text")
report(
CodeSmell(
issue = issue,
entity = Entity.from(expression),
message = "Wasteful parameters q_75 detected. Use q_auto instead. Refer to $cloudinaryRefUrlForQuality."
)
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.github.thewisenerd.linters.sidekt.rules

import io.github.thewisenerd.linters.sidekt.helpers.Debugger
import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Debt
import io.gitlab.arturbosch.detekt.api.Entity
import io.gitlab.arturbosch.detekt.api.Issue
import io.gitlab.arturbosch.detekt.api.Rule
import io.gitlab.arturbosch.detekt.api.Severity
import org.jetbrains.kotlin.psi.KtStringTemplateExpression

class ImageWidth (config: Config) : Rule(config) {

private val debugStream by lazy {
valueOrNull<String>("debug")?.let {
Debugger.getOutputStreamForDebugger(it)
}
}

override val issue: Issue = Issue(
id = ImageWidth::class.java.simpleName,
severity = Severity.Performance,
description = "Wasteful parameters w_768 detected. Please use precise width as per design/UI to avoid high bandwidth usage.",
debt = Debt.TEN_MINS
)

override fun visitStringTemplateExpression(expression: KtStringTemplateExpression) {
super.visitStringTemplateExpression(expression)
val dbg = Debugger.make(ImageWidth::class.java.simpleName, debugStream)
val text = expression.text
val patternWidth = Regex("https://ud-img.azureedge.net.*w_768.*")
if(patternWidth.containsMatchIn(text)) {
dbg.i("Usage of w_768 detected in string $text")
report(
CodeSmell(
issue = issue,
entity = Entity.from(expression),
message = "Usage of w_768 detected. Please use precise width as per design/UI to avoid high bandwidth usage."
)
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.github.thewisenerd.linters.sidekt

import io.github.thewisenerd.linters.sidekt.rules.ImageQuality
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Finding
import io.gitlab.arturbosch.detekt.api.SourceLocation
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.junit.Test

class ImageQualityTest {
companion object {
private val imageQuality = ImageQuality::class.java.simpleName

private fun ensureImageQualityFindings(
findings: List<Finding>,
requiredFindings: List<SourceLocation>
) = TestUtils.ensureFindings(imageQuality, findings, requiredFindings)
}

private val testConfig = object : Config {
override fun subConfig(key: String): Config = this

@Suppress("UNCHECKED_CAST")
override fun <T : Any> valueOrNull(key: String): T? {
return when (key) {
"active" -> true as? T
"debug" -> "stderr" as? T
else -> null
}
}
}
private val subject = ImageQuality(testConfig)

@Test
fun testImageQuality() {
val code = TestUtils.readFile("ImageQualityChecks.kt")
val findings = subject.compileAndLintWithContext(TestUtils.env, code)
ensureImageQualityFindings(
findings, listOf(
SourceLocation(10, 17),
SourceLocation(17, 17),
SourceLocation(25, 22),
SourceLocation(26, 22),
SourceLocation(27, 22),
SourceLocation(31, 25),
SourceLocation(32, 25)
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.github.thewisenerd.linters.sidekt

import io.github.thewisenerd.linters.sidekt.rules.ImageWidth
import io.gitlab.arturbosch.detekt.api.Config
import io.gitlab.arturbosch.detekt.api.Finding
import io.gitlab.arturbosch.detekt.api.SourceLocation
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.junit.Test

class ImageWidthTest {
companion object {
private val imageWidth = ImageWidth::class.java.simpleName

private fun ensureImageWidthFindings(
findings: List<Finding>,
requiredFindings: List<SourceLocation>
) = TestUtils.ensureFindings(imageWidth, findings, requiredFindings)
}

private val testConfig = object : Config {
override fun subConfig(key: String): Config = this

@Suppress("UNCHECKED_CAST")
override fun <T : Any> valueOrNull(key: String): T? {
return when (key) {
"active" -> true as? T
"debug" -> "stderr" as? T
else -> null
}
}
}
private val subject = ImageWidth(testConfig)

@Test
fun testImageWidth() {
val code = TestUtils.readFile("ImageWidthChecks.kt")
val findings = subject.compileAndLintWithContext(TestUtils.env, code)
ensureImageWidthFindings(
findings, listOf(
SourceLocation(10, 17),
SourceLocation(17, 17),
SourceLocation(26, 22),
SourceLocation(27, 22),
SourceLocation(31, 23),
SourceLocation(32, 23)
)
)
}
}
34 changes: 34 additions & 0 deletions src/test/resources/ImageQualityChecks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

class SomeClass {
fun getTaskActions() = listOf(
mapOf(
"title" to "Some title 1",
"subtitle" to """
1. Subtitle 1,
2. Subtitle 2
""".trimIndent(),
"samplePhotos" to listOf(
"https://ud-img.azureedge.net/w_768,q_75/u/assets/8zze8ghc2rx4pthydu8f.jpg"
)
),
mapOf(
"title" to "Some title 2",
"subtitle" to "Random subtitle",
"samplePhotos" to listOf(
"https://ud-img.azureedge.net/w_768,q_75/u/assets/uifkk3iyok3zpenrvtcq.jpeg"
)
)

)
}

enum class SomeEnum(val title: String, val iconUrl: String) {
ITEM_A("Item A", "https://ud-img.azureedge.net/w_256,q_75/u/assets/px23prq65xdhyx6353h9.png"),
ITEM_B("Item B", "https://ud-img.azureedge.net/w_768,q_75/u/assets/kx23prq65xdhyx635huy.png"),
ITEM_C("Item C", "https://ud-img.azureedge.net/w_768,q_75/u/assets/g0b00bt73jh6rxptzjqe.png"),
ITEM_D("Item D", "https://ud-img.azureedge.net/w_124,q_auto/u/assets/g0b00bt73jh6rxptzjqe.png");
}

const val randomIcon1 = "https://ud-img.azureedge.net/w_768,q_75/u/assets/36eux3optz3wnifaikaq.png"
const val randomIcon2 = "https://ud-img.azureedge.net/w_768,q_75/u/assets/swwofuabve1qdqg7zoeo.png"
const val randomIcon3 = "https://ud-img.azureedge.net/w_360,q_auto/u/assets/swwofuabve1qdqg7zoeo.png"
34 changes: 34 additions & 0 deletions src/test/resources/ImageWidthChecks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

class RandomClass {
fun getTaskActions() = listOf(
mapOf(
"title" to "Some title 1",
"subtitle" to """
1. Subtitle 1,
2. Subtitle 2
""".trimIndent(),
"samplePhotos" to listOf(
"https://ud-img.azureedge.net/w_768,q_75/u/assets/8zze8ghc2rx4pthydu8f.jpg"
)
),
mapOf(
"title" to "Some title 2",
"subtitle" to "Random subtitle",
"samplePhotos" to listOf(
"https://ud-img.azureedge.net/w_768,q_75/u/assets/uifkk3iyok3zpenrvtcq.jpeg"
)
)

)
}

enum class RandomEnum(val title: String, val iconUrl: String) {
ITEM_A("Item A", "https://ud-img.azureedge.net/w_256,q_75/u/assets/px23prq65xdhyx6353h9.png"),
ITEM_B("Item B", "https://ud-img.azureedge.net/w_768,q_75/u/assets/kx23prq65xdhyx635huy.png"),
ITEM_C("Item C", "https://ud-img.azureedge.net/w_768,q_75/u/assets/g0b00bt73jh6rxptzjqe.png"),
ITEM_D("Item D", "https://ud-img.azureedge.net/w_124,q_auto/u/assets/g0b00bt73jh6rxptzjqe.png");
}

const val someIcon1 = "https://ud-img.azureedge.net/w_768,q_75/u/assets/36eux3optz3wnifaikaq.png"
const val someIcon2 = "https://ud-img.azureedge.net/w_768,q_75/u/assets/swwofuabve1qdqg7zoeo.png"
const val someIcon3 = "https://ud-img.azureedge.net/w_360,q_auto/u/assets/swwofuabve1qdqg7zoeo.png"

0 comments on commit 93fe7be

Please sign in to comment.