Dando continuidade a nossa série de artigos, hoje vamos conhecer o matador de bugs, o PMD. Apesar de parecer uma sigla, nem os criadores sabem o que PMD significa. Atualmente em sua versão 5.4.1, ele possui regras que denunciam desde try/catches vazios, até código copiado.
Como o Gradle possui nativamente um plugin do PMD, sua integração é tão simples quanto as outras ferramentas que já vimos. Primeiramente, vamos aplicar o plugin no nosso arquivo build.gradle:
apply plugin: 'pmd'
Da mesma forma que fizemos com as outras ferramentas, uma recomendação é adicionarmos a task que vamos criar à task check:
check.dependsOn 'checkstyle', 'findbugs', 'pmd'
O próximo passo é criar a nossa task. Ela é muito semelhante àquela que criamos para o FindBugs, com a diferença de que as propriedades que utilizamos para configurar as regras de validação se chamam ruleSets e ruleSetFiles. Assim como o FindBugs, com o PMD também temos a possibilidade de gerar o relatório tanto em formato XML quanto HTML.
A task completa fica assim:
task pmd(type: Pmd) { ignoreFailures = false ruleSetFiles = files("${project.rootDir}/config/pmd-ruleset.xml") ruleSets = [] source 'src' include '**/*.java' exclude '**/gen/**' reports { xml.enabled = false html.enabled = true html { destination "$project.buildDir/reports/findbugs/findbugs.html" } } }
O arquivo de configuração pmd-ruleset.xml contém as regras que serão aplicadas ao processo de validação dos nossos arquivos. Um exemplo:
?xml version="1.0"?> <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Android Application Rules" xmlns="http://pmd.sf.net/ruleset/1.0.0" xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"> <exclude-pattern>.*/R.java</exclude-pattern> <exclude-pattern>.*/gen/.*</exclude-pattern> <rule ref="rulesets/java/android.xml" /> </ruleset>
Todas as regras disponíveis para o PMD podem ser encontradas aqui. E como o próprio pessoal do PMD diz, nenhuma regra é escrita na pedra, é possível remover determinadas verificações de um ruleset. No contexto do Android, um caso onde isso é necessário é quando adicionamos a regra de Import Statements e estamos utilizando o Espresso, cujo design visa a fluência na leitura dos testes escritos. Esse design muitas vezes acaba gerando um grande número de imports estáticos, o que entra em conflito com a regra TooManyStaticImports do PMD. Caso haja a necessidade de remover alguma regra de um ruleset, podemos fazer isso no arquivo de configuração desta forma:
<?xml version="1.0"?> <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Android Application Rules" xmlns="http://pmd.sf.net/ruleset/1.0.0" xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"> <exclude-pattern>.*/R.java</exclude-pattern> <exclude-pattern>.*/gen/.*</exclude-pattern> <rule ref="rulesets/java/android.xml" /> <rule ref="rulesets/java/imports.xml"> <exclude name="TooManyStaticImports" /> </rule> </ruleset>
Executando a task pmd em um terminal (ou utilizando o menu Gradle dentro do Android Studio), podemos ter uma análise de código baseada nas regras que configuramos.
Pegando como exemplo o ruleset Android que adicionamos à nossa configuração, podemos simular o erro comum de utilizar a localização da memória externa hardcoded como /sdcard. Assim, temos como resultado o seguinte relatório:
O link no relatório leva até a descrição detalhada do problema no próprio site do PMD.
E é isso! Ficou alguma dúvida ou tem alguma contribuição? Deixe seu comentário abaixo.
Na próxima e última parte dessa série, veremos como realizar um ajuste fino da execução do Lint para melhorar a qualidade do nosso aplicativo e evitar que problemas conhecidos e más práticas acabem afetando o desempenho em produção.
Até lá!
***
Este post foi originalmente publicado no Medium e no blog pessoal do autor.