Entrou no artigo achando que ia aprender algum hack para parar de trabalhar? Achou errado!
Como eu parei de trabalhar e meu gestor ainda não sabe disso. Ou não sabia. | ||
Entrou no artigo achando que ia aprender algum hack para parar de trabalhar? Achou errado! | ||
Mas posso te falar que codificar detectores e regras de Lint vão te ajudar a reduzir as dores de cabeças com problemas em code base extensas. Além disso, você pode terceirizar o processo de tech migration. Ou garantir que ninguém vá ferir padrões arquiteturais adotados pelo time. Ou garantir a sua sexta... | ||
“Lint?” | ||
Tá, muito de vocês devem estar pensando: | ||
É o troço que pinta meu xml de amarelo ou que coloca cobrinha vermelha no meio do meu código. | ||
Mas pera lá, Lint não é só isso. Na real, a ferramenta foi entregue com o compilador C e tinha como função ir além da análise estática que o compilador realizava. Bom, já o nosso lint foi nomeado em honra a essa nobre ferramenta, por ter salvo a sexta de inúmeros desenvolvedores. | ||
Porém, para entendermos como funciona essa análise, vamos explorar um conjunto de definições, a fim de termos uma linguagem única quando se trata de lint. | ||
Conceitos | ||
Bom, na seção anterior, falamos que essa ferramenta tem como finalidade executar uma análise estática do seu código. Mas o que é isso? Simples, ele tem como fim verificar um dado escopo a fim de encontrar problemas. Cada um desses problemas é chamado de Issue. | ||
O responsável por verificar um dado escopo é o Detector, além disso, ele também é responsável por reportar os incidentes. Incidentes são instâncias de uma Issue. | ||
Escopo, problema, instância, detector e incidentes. Todos os conceitos foram definidos, agora, iremos nos aprofundarmos em cada um deles, mas não na ordem apresentada acima. | ||
Issue | ||
Classe responsável por modelar algo que vai tirar a sua short-friday. Nela vamos ter metadados para realizarmos uma análise dos possíveis problemas que iremos encontrar no código e, a partir daí, tomar uma ação. | ||
Criando uma Issue | ||
Por convenção, uma Issue é declarada no Companion Object de seu Detector, dessa forma, podemos ter uma visão mais clara da responsabilidade desse objeto. Além disso, também, é uma boa prática adicionar nome aos argumentos da função | ||
Tendo isso em mente, vamos definir o nosso primeiro BO: | ||
Adicionar texto alternativo | ||
Você pode ver que há uma série de atributos que o método create pede. Bora dar uma olhada em cada um deles, prometo que vai ser rápido. | ||
| ||
Com o nosso problema modelado em uma Issue, podemos nos concentrar na construção de nosso Detector. | ||
Criando um Detector | ||
Lembra de quando nós éramos pequenos e passava Hércules no SBT? Então, tá lembrado daqueles 12 trabalhos que o Hércules teve de fazer? Então, a tarefa de codificar o Detector é semelhante àquilo.. | ||
Mas para facilitar nossa vida, o Lint faz a busca por problemas de forma ordenada: | ||
| ||
Além dessa busca ordenada, há duas chamadas que possibilitam o setup, teardown ou report: | ||
Na real, tem uma cacetada de função que o Detector te fornece para facilitar sua vida na hora de descobrir um problema. Você pode conferir todas acessando o link. | ||
Bora botar tudo isso daqui em prática? | ||
No exemplo anterior, utilizei um ResourceXmlDetector para facilitar a minha vida. Essa classe nada mais é que um Detector especializado para achar bucha em XML. Com ele, vamos ter acessos aos hooks: | ||
1. getApplicableAttributes: Lista de atributos que vão ser analisados; | ||
2. appliesTo: Indica se o Folder deve ser analisado; | ||
3. visitAttribute : Te fornece o contexto do documento sendo analisado e o nó a ser examinado. | ||
Mas como eu testo? | ||
Dependências | ||
Para verificarmos uma regra customizada de lint, devemos adicionar em nosso dependencies as seguintes dependências | ||
LintDetectorTest | ||
Para facilitar a escrita de um teste lint, a plataforma nos provê uma classe que provê alguns métodos para validar um Detector. A classe, em questão, é a LintDetectortask, a qual requer duas coisas: | ||
| ||
Teste | ||
Os passos para se criar um teste lint são: | ||
| ||
Provendo um arquivo de test | ||
Assim como em outros testes unitários, temos a utilização de mocks nesse tipo de teste. No caso de testes para verificação de uma regra lint, utilizamos o TestFile. Para prover esse arquivo basta: | ||
Do trecho de código acima, podemos ver que a função xml possuí dois parâmetros: | ||
| ||
Provendo configurações adicionais | ||
Podemos prover algumas configurações adicionais para nosso teste. Como, por exemplo, permitir que nossa execução não precise de um SDK instalado ou forçar que ele seja executado em um SDK específico. | ||
Você pode conferir a lista de configurações adicionais logo abaixo e para maiores detalhes, basta verificar o seu contrato: | ||
| ||
Bora ver como ficou? | ||
Chega de teoria! | ||
Bora colocar nossa mão na massa e realizar um teste. Para isso, imagine que escrevemos um Detector que busca se há ou não valores de dimens hardcoded em nosso código xml, o XmlHardcodedDimensDetector. | ||
E agora , José? | ||
Tá, o artigo era só isso. Conseguimos salvar sua sexta-feira. | ||
Brincadeiras a parte, a gente conseguiu ver como funciona o mundo por trás do Lint. Agora cabe a você e ao seu time implementarem regras que façam sentido ao seu contexto! Ah, não esquece de publicar elas no git para que a comunidade possa utilizá-las. | ||
É claro que o exemplo utilizado é bem simples e não utiliza dos conceitos de UAST e PSI, má isso daqui é tipo prova. Você estuda X e cai Y. Porém, se você tem interesse em escrever algumas regras para Kotlin/Java, fideliza o like aqui no artigo. | ||
Bibliografia | ||
|