Android

2 fev, 2016

Integrando ferramentas de análise de código em Android – Parte 03

Publicidade

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:

11 (1)

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.