Integre um Verificador de Código Externo ao Eclipse CDT

Execute as ferramentas de análise de código em C/C++ com o Codan no Eclipse

O Codan é a estrutura de análise de código integrada do Eclipse CDT (C/C++ Development Tooling) para projetos em C/C++. O Codan fornece infraestrutura para realizar análise de código estático e vem com verificadores de problema prontos para usar. Com o release Eclipse Juno, o Codan foi ampliado para permitir que os desenvolvedores executem ferramentas externas de análise de código automaticamente. Alex Ruiz explica por que a atualização é uma boa notícia para usuários do Eclipse CDT e, em seguida, mostra como usar o código Java™ e um pouco de XML para integrar rapidamente o seu verificador de código favorito ao ambiente de desenvolvimento Eclipse C/C++.

Alex Ruiz, Software engineer, Google

Alex RuizAlex Ruiz trabalha na organização Engineering Tools, na Google Inc. Nas horas de lazer, trabalha em projetos de software livre, mantém um blog, escreve artigos técnicos e atua como conferencista internacional. Confira o blog do Alex. As opiniões expressas neste artigo representam o pensamento dele, não o de seu empregador.



17/Set/2012

O Codan é uma estrutura de análise de código que realiza verificações de código em projetos de C/C++. O Codan, que faz parte do conjunto Eclipse CDT (C/C++ Development Tooling) desde 2011, não só fornece toda a infraestrutura necessária para realizar análise de código estático, mas também alguns verificadores de problemas [úteis e fáceis de usar (consulte Recursos).

O Codan foi atualizado com o release Eclipse Juno em junho de 2012, para permitir que os desenvolvedores executem ferramentas externas de análise de código automaticamente. É um avanço interessante para o Eclipse CDT e para desenvolvedores em C/C++. Embora os verificadores de problemas fornecidos anteriormente fossem bons, vários outros eram necessários para dar ao Codan paridade de recursos com as ferramentas externas de análise de código já existentes. Agora o Codan se integra facilmente a ferramentas externas maduras, como o Cppcheck e oclang_check.

Tutoriais relacionados no developerWorks

Mais sobre o desenvolvimento de aplicativos com o Eclipse CDT:

A integração ferramentas externas de análise de código com o Eclipse CDT permite verificações de código melhores e em maior número, comparadas ao que os desenvolvedores conseguiam fazer somente com o Codan. Também deve melhorar bastante a produtividade geral do desenvolvimento. Agora podemos configurar ferramentas externas de análise de código a partir das páginas Preferences do Codan. Uma vez integradas ao Codan, as ferramentas são chamadas automaticamente e suas saídas são exibidas como marcadores de editor.

Neste artigo, mostrarei como usar o código Java e um pouco de XML para integrar rapidamente o seu verificador de código favorito ao ambiente de desenvolvimento Eclipse C/C++. Meu exemplo irá se basear na integração do Cppcheck com o Codan, mas o processo deve ser aplicável à ferramenta da sua escolha.

Instale o Eclipse Juno e o CDT

Será necessário ter o Eclipse Juno e o CDT instalados para seguir os exemplos neste artigo. Se ainda não instalou o Eclipse, é possível instalar uma versão que vem com o CDT pré-instalado. Para fazer isso, basta selecionar Eclipse IDE for C/C++ Developers a partir da página Eclipse downloads .

Se você já tem uma instalação do Eclipse que não inclui o CDT, siga estas instruções para atualizar o ambiente de desenvolvimento:

  1. Dentro do Eclipse, selecione o menu Help > Install New Software....
  2. No diálogo Install, selecione Juno na lista suspensa.
  3. Na categoria Programming Languages, selecione C/C++ Development Tools SDK.
Figura 1. Instalando o CDT
Instalando o CDT

Além do CDT,as ferramentas de desenvolvimento padrão do GNU C/C++ serão necessárias para compilar, construir e depurar o seu código. Consulte Recursos para obter as instruções de instalação dessas ferramentas.

Inicialize o Codan

A maioria das verificações de código do Codan é habilitada por padrão. É possível configurar o Codan individualmente no nível do projeto ou da área de trabalho usando as páginas Preferences ou Project Property do Eclipse, respectivamente.

A partir da página Preferences do Codan, mostrada na Figura 2, é possível ver todos os verificadores de código disponíveis e os problemas de código que cada um relata.

Figura 2. Verificadores de código na página Preferences do Codan
Verificadores de código na página Preferences do Codan

A partir dessa página, é possível habilitar, desabilitar ou alterar a severidade de um problema. Se você quer configurar outras propriedades de problemas individuais, é possível selecionar um problema e clicar no botão Customize Selected... . Figura 3 mostra as opções de configuração referentes ao problema "Name convention for function."

Figura 3. Configurando um problema
Configurando um problema

A terceira guia da Figura 3 permite especificar como se deve lançar uma verificação de problema:

  • Run as you type: quando o usuário altera um arquivo em um editor do CDT.
  • Run on file open: quando o arquivo é aberto em um editor do CDT.
  • Run on file save: quando as mudanças não salvas em um editor do CDT são salvas.
  • Run on incremental build: quando se emite uma construção incremental (geralmente quando o arquivo é salvo a opção no nível do projeto "Build Automatically" está habilitada). Se você habilitar essa opção e "Run on file save" juntas, a verificação de código será executada duas vezes.
  • Run on full build: quando um desenvolvimento integral é emitido (por exemplo, quando um projeto é limpo).
  • Run on demand: quando um usuário aciona manualmente uma verificação de código a partir do item de menu de contexto "Run C/C++ Code Analysis."

Verificações de código com o Codan

Para ser possível ver o Codan em funcionamento, criarei um projeto em C++ com um arquivo curto nessa linguagem. Nesse arquivo, designarei uma variável a ela mesma. O Codan inclui a verificação de código "Assignment to itself," habilitada por padrão com o nível de severidade de "error." É configurada para executar à medida que você digita — portanto, o erro aparecerá imediatamente.

Figura 4. O Codan executando uma verificação de código
O Codan executando uma verificação de código

Na Figura 4, é possível ver que o Codan detectou o erro de designação e o relatou antes que eu salvasse o arquivo. Perfeito!

Para saber mais sobre o uso do Codan, acesse a página inicial do projeto (consulte Recursos).

Integre o Cppcheck ao Eclipse CDT

Para integrar uma ferramenta externa de análise de código ao Codan, é necessário escrever um tipo especial de verificador que mostra como chamar essa ferramenta. O verificador é uma implementação da interface IChecker do Codan, que realiza algum tipo de verificação de código em um determinado IResource (tipicamente um IFile).

Para demonstrar como é fácil criar um verificador baseado em ferramenta externa, criaremos um verificador que chama a conhecida ferramenta Cppcheck (consulte Recursos). Você fará o seguinte:

  • Crie um projeto de plug-in do Eclipse e inclua o Codan como dependência.
  • Crie um analisador de erro para analisar a saída do Cppcheck e criar marcadores de editor, se necessário.
  • Crie o verificador de código, que é a classe responsável por chamar o Cppcheck.

Etapa 1. Crie um projeto de plug-in do Eclipse

Para criar um verificador do Codan, começamos criando um novo projeto de plug-in do Eclipse:

  1. Selecione o menu File > New > Project....
  2. Na categoria Plug-in Development, selecione Plug-in Project.
  3. Insira um nome para o projeto (o meu é "CppcheckChecker") e clique em Next.
  4. Aceite os padrões e clique em Finish.
Figura 5. Criando um projeto de plug-in
Criando um projeto de plug-in

Depois de criar o novo projeto de plug-in, o Eclipse abrirá automaticamente o arquivo MANIFEST.MF . É o arquivo no qual incluiremos as dependências do Codan.

No editor, selecione a guia Dependencies e inclua o seguinte na lista Required Plug-ins:

org.eclipse.cdt.codan.core
org.eclipse.cdt.codan.core.cxx
org.eclipse.cdt.codan.ui
org.eclipse.cdt.codan.ui.cxx
org.eclipse.cdt.core
org.eclipse.cdt.ui
org.eclipse.core.resources
org.eclipse.core.runtime
org.eclipse.ui

Plug-ins do Eclipse

Não abordarei todos os detalhes sobre o processo de escrever um plug-in do Eclipse neste artigo porque o Eclipse não é o foco da discussão. Consulte Recursos para ver uma introdução ao processo de escrever plug-ins do Eclipse.

Etapa 2. Crie um analisador de erro

Precisarmos de um analisador de erro para criar marcadores de editor a partir da saída do Cppcheck; portanto, a próxima etapa é estender o conjunto de ferramentas de C/C++ do Eclipse com um plug-in. Para isso, usaremos o código Java porque o próprio Eclipse é um aplicativo Java.

Primeiro, criaremos uma classe, CppcheckErrorParser, que implementa org.eclipse.cdt.core.IErrorParser. Começamos descobrindo o padrão que o Cppcheck usa ao relatar problemas de código. O analisador de erro usará esse padrão para identificar uma linha da saída que representa um relatório de problemas e, em seguida, extrair dessa saída as informações necessárias para criar um marcador de editor.

Lista 1. Um padrão que corresponde à saída do Cppcheck
  // sample line to parse:
  //
  // [/src/HelloWorld.cpp:19]: (style) The scope of the variable 'i' can be reduced
  // ----------1--------- -2    --3--  ------------------4-------------------------
  //
  // groups:
  // 1: file path and name
  // 2: line where problem was found
  // 3: problem severity
  // 4: problem description
  private static Pattern pattern = 
      Pattern.compile("\\[(.*):(\\d+)\\]:\\s*\\((.*)\\)\\s*(.*)");

Lista 2 mostra como o analisador de erro usa o padrão para extrair o caminho e nome do arquivo que está sendo verificado, bem como a localização, descrição e severidade do erro localizado. Com essas informações, o analisador de erro cria um novo ProblemMarkerInfo e o passa para o ErrorParserManager fornecido. ErrorParserManager é a classe responsável pela criação dos marcadores de editor.

Lista 2. Processando a saída do Cppcheck
  @Override
  public boolean processLine(String line, ErrorParserManager parserManager) {
    Matcher matcher = pattern.matcher(line);
    if (!matcher.matches()) {
      return false;
    }
    IFile fileName = parserManager.findFileName(matcher.group(1));
    if (fileName != null) {
      int lineNumber = Integer.parseInt(matcher.group(2));
      String description = matcher.group(4);
      int severity = findSeverityCode(matcher.group(3));
      ProblemMarkerInfo info = 
          new ProblemMarkerInfo(fileName, lineNumber, description, severity, null);
      parserManager.addProblemMarker(info);
      return true;
    }
    return false;
  }
}

Mapeando as severidades dos problemas

O Cppcheck define as suas próprias severidades de problema, que não são iguais às utilizadas pelos marcadores de editor. Por exemplo: a severidade "style" do Cppcheck não tem uma contraparte no Eclipse. Para superar esse problema, é necessário criar um mapeamento entre os dois tipos de severidade de problema. O método findSeverityCode (mostrado na Lista 3) demonstra uma forma objetiva de implementar esse mapeamento:

Lista 3. Mapeando as severidades dos problemas
  private static Map<String, Integer> SEVERITY_MAPPING = new HashMap<String, Integer>();
  
  static {
    SEVERITY_MAPPING.put("error", IMarkerGenerator.SEVERITY_ERROR_RESOURCE);
    SEVERITY_MAPPING.put("warning", IMarkerGenerator.SEVERITY_WARNING);
    SEVERITY_MAPPING.put("style", IMarkerGenerator.SEVERITY_INFO);
  }
  
  private int findSeverityCode(String text) {
    Integer code = SEVERITY_MAPPING.get(text);
    if (code != null) {
      return code;
    }
    return IMarkerGenerator.SEVERITY_INFO;
  }

Após a criação do mapeamento, qualquer problema relatado pelo Cppcheck com a severidade "style" será exibido no Eclipse usando a severidade SEVERITY_INFO. Esse mapeamento define somente os valores padrão referentes às severidades dos problemas. Como você verá mais adiante, é possível configurar esse mapeamento a partir da página Preferences do Codan.

Para que o CppcheckErrorParser seja reconhecido pelo Codan, ele deve ser registrado no arquivo plugin.xml, usando o ponto de extensão org.eclipse.cdt.core.ErrorParser:

Lista 4. Registrando o analisador de erro
  <extension id="com.developerworks.cdt.checkers" name="Cppcheck error parsers" 
      point="org.eclipse.cdt.core.ErrorParser">
    <errorparser class="cppcheckchecker.CppcheckErrorParser" 
        id="com.dw.cdt.checkers.CppcheckErrorParser"
        name="Cppcheck">
      <context type="codan" />
    </errorparser>
  </extension>

Observe na Lista 4 que a o ponto de extensão ErrorParser foi criado originalmente para registrar analisadores para as ferramentas de construção do CDT. Não é específico para o Codan. Para indicar que o CppcheckErrorParser deve ser usado somente com o Codan, incluímos o contexto "codan."

Etapa 3. Crie o verificador do código

AbstractExternalToolBasedChecker é a superclasse para o verificador de código do Codan baseado em ferramentas externas. Fornece a maior parte da infraestrutura necessária para chamar uma ferramenta externa de análise de código. Já que estamos integrando o Cppcheck, chamaremos essa classe CppcheckChecker.

A primeira coisa que precisamos fazer é especificar os valores padrão para as informações (relacionadas à ferramenta externa) que serão exibidas na página Preferences do Codan.

Essas informações, que devem ser passadas para o construtor do verificador, incluem o seguinte:

  • O nome da ferramenta externa de análise de código — neste caso, Cppcheck.
  • O nome do executável da ferramenta, que é cppcheck. Não é necessário especificar o caminho do executável porque supomos que ele está no PATH do sistema.
  • Os argumentos a serem passados para o executável, que são contidos em uma única String. Especificamos "--enable=all" para habilitar todas as verificações do Cppcheck.
Lista 5. Informações padrão do Cppcheck
  public CppCheckChecker() {
    super(new ConfigurationSettings("Cppcheck", new File("cppcheck"), "--enable=all"));
  }

Observe que a página Preferences do Codan permite modificar o caminho do executável e os argumentos a serem passados.

Mapeando as severidades do problema para os IDs de problema

Em seguida, precisamos especificar os IDs dos analisadores de erro que utilizaremos, mostrados na Listagem 6. Os IDs devem ser os mesmos que foram usados no arquivo plugin.xml.

Lista 6. Especificando os IDs do analisador de erro que devem ser usados
  @Override
  protected String[] getParserIDs() {
    return new String[] { "com.dw.cdt.checkers.CppcheckErrorParser" };
  }

Voltando à Lista 2, criamos um ProblemMarkerInfo e o passamos para o ErrorParserManager que foi dado para criar marcadores de editor. ErrorParserManager delegará a criação de marcadores de editor para o nosso verificador recém-criado.

Para que esse verificador crie um marcador de editor, precisamos substituir o método addMarker(ProblemMarkerInfo) (cuja função é localizar outro tipo de incompatibilidade). Os verificadores do Codan não podem criar os marcadores diretamente a partir de ProblemMarkerInfos. Eles têm o seu próprio mecanismo, que usa IDs de problema para determinar a severidade adequada para o marcador de editor que foi criado.

O problem ID é um ID exclusivo que o Codan usa para identificar problema de código relatado por um verificador de código. Todos os problemas de código são exibidos na página Preferences do Codan (veja a Figura 2).

Lista 7. Criando marcadores de erro
  @Override
  public void addMarker(ProblemMarkerInfo info) {
    String problemId = PROBLEM_IDS.get(info.severity);
    String description = String.format("[cppcheck] %s", info.description);
    reportProblem(problemId, createProblemLocation(info), description);
  }

Para localizar o ID de problema que corresponde à severidade de um ProblemMarkerInfo, precisamos criar um mapeamento entre as severidades e os IDs de problema. Lista 8 mostra como o mapeamento é implementado:

Lista 8. Mapeando as severidades do problema para os IDs de problema
  private static final String ERROR_PROBLEM_ID = 
      "com.dw.cdt.checkers.cppcheck.error";

  private static final Map<Integer, String> PROBLEM_IDS = 
      new HashMap<Integer, String>();

  static {
    PROBLEM_IDS.put(
        IMarkerGenerator.SEVERITY_ERROR_RESOURCE, ERROR_PROBLEM_ID);
    PROBLEM_IDS.put(
        IMarkerGenerator.SEVERITY_WARNING, "com.dw.cdt.checkers.cppcheck.warning");
    PROBLEM_IDS.put(
        IMarkerGenerator.SEVERITY_INFO, "com.dw.cdt.checkers.cppcheck.style");
  }

Os verificadores de código que usam uma ferramenta externa de análise de código precisam indicar qual ID de problema são é considerado como "referência." O ID de problema reference é usado para obter os valores de preferência do verificador (por exemplo, o nome da ferramenta externa, como mostra a Lista 5). Não importa qual ID de problema é a referência, porque todos os problemas compartilharão as preferências.

Lista 9. Especificando o ID de problema de referência
  @Override
  protected String getReferenceProblemId() {
    return ERROR_PROBLEM_ID;
  }

A constante ERROR_PROBLEM_ID é definida na Lista 8.

Registrando o verificador

Para que o verificador de código e todos os problemas que ele relata apareçam na página Preferences do Codan (e, portanto, fiquem acessíveis para o usuário), precisamos registrar o verificador no arquivo plugin.xml do Codan.

Já que não conhecemos todos os problemas que o Cppcheck pode relatar e não podemos impedir o Cppcheck de incluir ou remover verificações de código em versões futuras, não poderemos registrar cada problema individual. Em vez disso, agruparemos os problemas por severidades e trataremos cada grupo como um problema individual. NaLista 10 registramos erros, avisos e violações de estilo como três problemas individuais:

Lista 10. Registrando o verificador e os relatórios de problema
  <extension point="org.eclipse.cdt.codan.core.checkers">
    <category id="cppcheckChecker.category" name="Cppcheck" />
    <checker class="cppcheckchecker.CppcheckChecker" id="cppcheckChecker.cppChecker"
      name="CppcheckChecker">
      <problem id="com.dw.cdt.checkers.cppcheck.error" name="Error" 
        defaultEnabled="true" defaultSeverity="Error" messagePattern="{0}"
        category="cppcheckChecker.category"/>
      <problem id="com.dw.cdt.checkers.cppcheck.warning" name="Warning" 
        defaultEnabled="true" defaultSeverity="Warning" messagePattern="{0}"
        category="cppcheckChecker.category"/>
      <problem id="com.dw.cdt.checkers.cppcheck.style" name="Style" 
        defaultEnabled="true" defaultSeverity="Info" messagePattern="{0}"
        category="cppcheckChecker.category"/>
    </checker>
  </extension>

Especificamos o nome do verificador que será exibido para os usuários no elemento category . Os IDs dos problemas devem ser iguais aos usados no verificador (consulte a Lista 8).

No arquivo plugin.xml, especificamos o seguinte sobre os três problemas:

  • São habilitados por padrão.
  • Têm as severidades padrão "Error," "Warning" e "Info", respectivamente.
  • Têm o padrão de mensagens: "{0}," que força o Codan a usar a descrição do problema da forma que foi relatada pelo Cppcheck.

Usando o Cppcheck no Codan

Agora podemos ver CppcheckChecker na página Preferences do Codan, como mostra a Figura 6:

Figura 6. Cppcheck exibido na página Preferences do Codan
Cppcheck exibido na página Preferences do Codan

Figura 7 mostra opções para configurar como o Cppcheck deve relatar erros de código:

Figura 7. Configure os relatórios de erro do Cppcheck
Configure os relatórios de erro do Cppcheck

Figura 8 mostra como o Cppcheck relata problemas de código. Observe que o Cppcheck foi chamado automaticamente depois que o arquivo foi salvo.

Figura 8. Um relatório do Cppcheck
Um relatório do Cppcheck

Uma desvantagem da integração

Uma limitação da integração do Codan a ferramentas externas de análise de código é que os verificadores baseados nessas ferramentas não podem executar enquanto o usuário digita. Isso ocorre simplesmente porque uma ferramenta externa não vê as mudanças no arquivo que não foram salvas. Portanto, um verificador externo precisa ser executado quando um arquivo é aberto e salvo.

Entretanto, essa limitação é compensada pelos benefícios do uso de uma ferramenta madura de análise de código. Integrar uma ferramenta externa ao Codan também é muito mais fácil e simples que criar um verificador regular — algo que requer um conhecimento profundo da linguagem C ou C++ e da implementação de AST do CDT. Por outro lado, conseguimos escrever o CppcheckChecker com cerca de 100 linhas de código Java simples (contidas em duas classes) e 30 linhas de XML.

Conclusão

Antes do release Eclipse Juno, a criação de verificações de código customizadas para o Codan exigia um bom entendimento das linguagens C/C++ e da implementação de AST do CDT. O release Juno do CDT Eclipse resolve esse problema permitindo que os desenvolvedores criem verificadores de código do Codan, que, em seguida, podem delegar o trabalho pesado para uma ferramentas externa de análise de código.

Neste artigo, usamos um pouco de código Java e XML para integrar o Cppcheck ao Codan, unindo essa ferramenta conhecida de análise de código C/C++ com a estrutura integrada de análise de código para os programas em C/C++ no Eclipse. Conforme eu mencionei anteriormente, você deve ser capaz de aplicar o processo demonstrado neste artigo à sua ferramenta preferida de análise de código. Consulte Recursos para saber mais.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

  • Participe da Comunidade do developerWorks. Entre em contato com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis do dW voltados para desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre
ArticleID=834693
ArticleTitle=Integre um Verificador de Código Externo ao Eclipse CDT
publish-date=09172012