Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Kotlin Static Analysis - Kotlin Everywhere 2019
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Matheus Cassiano Candido
October 05, 2019
Programming
0
120
Kotlin Static Analysis - Kotlin Everywhere 2019
Slides for my Kotlin Everywhere talk.
Matheus Cassiano Candido
October 05, 2019
Tweet
Share
More Decks by Matheus Cassiano Candido
See All by Matheus Cassiano Candido
JUnit rules and test parameterization
mcassiano
0
130
unraveling custom drawing
mcassiano
0
86
The Basis of Android Threading: Loopers and Handlers
mcassiano
1
130
Hackeando sua próxima entrevista: dicas para conseguir seu próximo estágio ou emprego
mcassiano
1
95
text spans: what, why and how?
mcassiano
0
690
Navigation patterns on Android and something new
mcassiano
3
400
Como conseguir o estágio (ou emprego) dos sonhos
mcassiano
0
50
Databinding e padrão MVVM
mcassiano
1
27
Desenvolvimento móvel: práticas de sucesso
mcassiano
0
31
Other Decks in Programming
See All in Programming
「ブロックテーマでは再現できない」は本当か?
inc2734
0
1k
SourceGeneratorのススメ
htkym
0
200
CSC307 Lecture 03
javiergs
PRO
1
490
Honoを使ったリモートMCPサーバでAIツールとの連携を加速させる!
tosuri13
1
180
並行開発のためのコードレビュー
miyukiw
0
880
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
220
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
380
2026年 エンジニアリング自己学習法
yumechi
0
140
KIKI_MBSD Cybersecurity Challenges 2025
ikema
0
1.3k
組織で育むオブザーバビリティ
ryota_hnk
0
180
なるべく楽してバックエンドに型をつけたい!(楽とは言ってない)
hibiki_cube
0
140
OCaml 5でモダンな並列プログラミングを Enjoyしよう!
haochenx
0
140
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
37
7.1k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
0
260
How to make the Groovebox
asonas
2
1.9k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Being A Developer After 40
akosma
91
590k
Navigating Weather and Climate Data
rabernat
0
110
How STYLIGHT went responsive
nonsquared
100
6k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.2k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.2k
Into the Great Unknown - MozCon
thekraken
40
2.3k
Leo the Paperboy
mayatellez
4
1.4k
Transcript
Mantendo código Kotlin seguro: de ponta a ponta Matheus C.
Candido Mobile Software Engineer @ Uber
Agenda 01 Análise estática 02 Ferramentas 03 Arquitetura 04 Customização
05 Automação
Análise estática Static program analysis is the analysis of computer
software that is performed without actually executing programs
Ktlint Simples, drop-in
Ktlint Simples, drop-in Zero configuração
Ktlint Simples, drop-in Zero configuração Code styling*
Ktlint Simples, drop-in Zero configuração Code styling* Formatador
Ktlint Simples, drop-in Zero configuração Code styling* Formatador Baseado no
Kotlin Style Guide, mas suporta Android Style Guide
Detekt Foco no detalhe
Detekt Foco no detalhe Totalmente configurável
Detekt Foco no detalhe Totalmente configurável Code styling
Detekt Foco no detalhe Totalmente configurável Code styling Performance
Detekt Foco no detalhe Totalmente configurável Code styling Performance Tratamento
de exceções
Android Lint Java, Kotlin e Resources
Android Lint Java, Kotlin e Resources Regras especiais para Android
Android Lint Java, Kotlin e Resources Regras especiais para Android
Super extensível
Android Lint Java, Kotlin e Resources Regras especiais para Android
Super extensível Performance
Android Lint Java, Kotlin e Resources Regras especiais para Android
Super extensível Performance Análise de recursos duplicados/não utilizados
Android Lint Java, Kotlin e Resources Regras especiais para Android
Super extensível Performance Análise de recursos duplicados/não utilizados Funciona para projetos não-Android
Warning vs. Errors
Baseline
Ignorando issues conhecidos @SuppressLint("NewApi") @Suppress("NewApi")
Arquitetura
Arquitetura
None
Arquitetura
Criando novas regras
Issue registry @AutoService(IssueRegistry::class) class Registry() :fIssueRegistry() {f override val issues:
List<Issue> = listOf(GetDrawableDetector.ISSUE) override val api: Int = CURRENT_API }f
Issue registry @AutoService(IssueRegistry::class) class Registry() :fIssueRegistry() {f override val issues:
List<Issue> = listOf(GetDrawableDetector.ISSUE) override val api: Int = CURRENT_API }f
Issue registry @AutoService(IssueRegistry::class) class Registry() :fIssueRegistry() {f override val issues:
List<Issue> = listOf(GetDrawableDetector.ISSUE) override val api: Int = CURRENT_API }f
Criando um detector /** *fDetector to check for usages of
`ResourcesCompat.getDrawable` or `ContextCompat.getDrawable`. */ class GetDrawableDetector :fDetector(), SourceCodeScanner {f companion object {f val ISSUE =fIssue.create(f id =fISSUE_ID, briefDescription =fBRIEF_DESCRIPTION, explanation =fLINT_ERROR_MESSAGE, category =fCategory.CORRECTNESS,
Descrição da Issue val ISSUE =fIssue.create(f id =fISSUE_ID, briefDescription =fBRIEF_DESCRIPTION,
explanation =fLINT_ERROR_MESSAGE, category =fCategory.CORRECTNESS, priority =f6, severity =fSeverity.ERROR, implementation =fcreate<GetDrawableDetector>()) }f override fun getApplicableMethodNames() = listOf("getDrawable") override fun visitMethodCall(f context:fJavaContext,
Descrição da Issue val ISSUE =fIssue.create(f id =fISSUE_ID, briefDescription =fBRIEF_DESCRIPTION,
explanation =fLINT_ERROR_MESSAGE, category =fCategory.CORRECTNESS, priority =f6, severity =fSeverity.ERROR, implementation =fcreate<GetDrawableDetector>()) }f override fun getApplicableMethodNames() = listOf("getDrawable") override fun visitMethodCall(f context:fJavaContext,
Descrição da Issue val ISSUE =fIssue.create(f id =fISSUE_ID, briefDescription =fBRIEF_DESCRIPTION,
explanation =fLINT_ERROR_MESSAGE, category =fCategory.CORRECTNESS, priority =f6, severity =fSeverity.ERROR, implementation =fcreate<GetDrawableDetector>()) }f override fun getApplicableMethodNames() = listOf("getDrawable") override fun visitMethodCall(f context:fJavaContext,
Descrição da Issue val ISSUE =fIssue.create(f id =fISSUE_ID, briefDescription =fBRIEF_DESCRIPTION,
explanation =fLINT_ERROR_MESSAGE, category =fCategory.CORRECTNESS, priority =f6, severity =fSeverity.ERROR, implementation =fcreate<GetDrawableDetector>()) }f override fun getApplicableMethodNames() =f listOf("getDrawable") override fun visitMethodCall(f context:fJavaContext,
Filtrando a entrada overrideffunfgetApplicableMethodNames() =f listOf("getDrawable")f override fun visitMethodCall(f context:fJavaContext,
node:fUCallExpression, method:fPsiMethod ){f iff(! getApplicableMethodNames().contains(node.methodName))freturn if (node.methodName == "getDrawable" && isBlacklisted(context.evaluator, node)) {f context.report(ISSUE, context.getLocation(node),
Detectando os problemas override fun visitMethodCall(f context:fJavaContext, node:fUCallExpression, method:fPsiMethod ){f
iff(! getApplicableMethodNames().contains(node.methodName))freturn if (node.methodName == "getDrawable" && isBlacklisted(context.evaluator, node)) {f context.report(ISSUE, context.getLocation(node), LINT_ERROR_MESSAGE) }f
Detectando os problemas iff(! getApplicableMethodNames().contains(node.methodName))freturn if (node.methodName == "getDrawable" &&
isBlacklisted(context.evaluator, node)) {f context.report(ISSUE, context.getLocation(node), LINT_ERROR_MESSAGE) }f }f private fun isBlacklisted():fBoolean {f return evaluator.isMemberInClass(node.resolve(), "androidx.core.content.ContextCompat") ||f
Detectando os problemas iff(! getApplicableMethodNames().contains(node.methodName))freturn if (node.methodName == "getDrawable" &&
isBlacklisted(context.evaluator, node)) {f context.report(ISSUE, context.getLocation(node), LINT_ERROR_MESSAGE) }f }f private fun isBlacklisted():fBoolean {f return evaluator.isMemberInClass(node.resolve(), "androidx.core.content.ContextCompat") ||f
Detectando os problemas context.report(ISSUE, context.getLocation(node), LINT_ERROR_MESSAGE) }f }f private fun
isBlacklisted():fBoolean {f return evaluator.isMemberInClass(node.resolve(),f "androidx.core.content.ContextCompat") ||f evaluator.isMemberInClass(node.resolve(), "androidx.core.content.res.ResourcesCompat")f }f }f
Usando a nova regra // no build.gradle dos outros projetos
dependencies {f lintChecks project(":meu_detector") }f
Usando a nova regra // no build.gradle dos outros projetos
dependencies {f lintChecks project(":meu_detector") }f
Relatórios
Relatórios
Relatórios
Evolução do código
None
Automação
Automação https://bit.cassiano.me/sa-automation
Automação https://bit.cassiano.me/sa-automation
Automação https://bit.cassiano.me/sa-comment-machine
Automação https://bit.cassiano.me/sa-git-hooks
Automação https://bit.cassiano.me/sa-git-hooks
Resumo Combine as ferramentas e aproveite o melhor de cada
uma
Resumo Combine as ferramentas e aproveite o melhor de cada
uma Aplique as regras que façam sentido para seu contexto
Resumo Combine as ferramentas e aproveite o melhor de cada
uma Aplique as regras que façam sentido para seu contexto Automatize a formatação dos arquivos e partes do code review
https://bit.cassiano.me/sa-kotlin-conf-17-talk
https://bit.cassiano.me/sa-kotlin-conf-18-talk
…perguntas?