/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.fenix.detektrules.perf 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.KtCallExpression import org.jetbrains.kotlin.psi.KtImportDirective private const val VIOLATION_MSG = "Please use `components.strictMode.resetAfter` instead because it has " + "performance improvements and additional code to monitor for performance regressions." /** * A check to prevent us from working around mechanisms we implemented to prevent suppressing StrictMode. */ class MozillaStrictModeSuppression(config: Config) : Rule(config) { override val issue = Issue( "MozillaStrictModeSuppression", Severity.Performance, "Prevents us from working around mechanisms we implemented to prevent suppressing StrictMode", Debt.TEN_MINS, ) override fun visitImportDirective(importDirective: KtImportDirective) { super.visitImportDirective(importDirective) reportIfImportAcResetAfter(importDirective) } override fun visitCallExpression(expression: KtCallExpression) { super.visitCallExpression(expression) reportIfCallStrictModeSetPolicy(expression) } private fun reportIfImportAcResetAfter(importDirective: KtImportDirective) { if (importDirective.importPath?.toString() == "mozilla.components.support.ktx.android.os.resetAfter") { report(CodeSmell(issue, Entity.from(importDirective), VIOLATION_MSG)) } } private fun reportIfCallStrictModeSetPolicy(expression: KtCallExpression) { // There is probably a more correct way of doing this but this API is not well documented // so it's not worth our time, I think. val receiver = expression.parent?.firstChild?.node?.chars val calledMethod = expression.calleeExpression?.firstChild?.node?.chars // This won't catch if setVmPolicy is imported directly. However, this is unlikely so let's // not handle it now. Maybe we can add it when we add tests for this file. if (receiver == "StrictMode") { val violationMsg = when (calledMethod) { "setThreadPolicy" -> VIOLATION_MSG "setVmPolicy" -> "NOT YET IMPLEMENTED: please consult the perf team about implementing" + "`StrictModeManager.resetAfter`: we want to understand the performance implications " + "of suppressing setVmPolicy before allowing it." else -> null } violationMsg?.let { msg -> report(CodeSmell(issue, Entity.from(expression), msg)) } } } }