Интеграция внешнего инструмента проверки кода в Eclipse CDT

Выполнение анализаторов кода C/C++ в составе Eclipse-плагина Codan

Codan ― это встроенная в Eclipse CDT (C/C++ Development Tooling) система анализа кода для проектов C/C++. Она предоставляет собой инфраструктуру для выполнения статического анализа кода и поставляется с готовыми к применению модулями выявления проблем (problem checkers). В новой версии Eclipse Juno Codan дополнен возможностью для разработчиков автоматически выполнять внешние инструменты анализа кода. Автор объясняет, почему это хорошая новость для пользователей Eclipse CDT, и показывает, как, написав небольшой код Java™ и немного XML, быстро интегрировать в среду разработки Eclipse C/C++ свой любимый инструмент анализа кода.

Алекс Руис, технический консультант, Oracle

Alex RuizАлекс Руис любит читать материалы, связанные с разработкой на Java, тестированием, объектно-ориентированным программированием, аспектно-ориентированным программированием и параллельными вычислениями. Программирование - это его первая любовь. Алекс является создателем FEST - инновационной Java-библиотеки, призванной облегчить тестирование приложений на основе Swing и JavaFX и тестирование в целом. Он работает программистом в подразделении Oracle, занимающемся инструментами разработки ПО. До работы в Oracle Alex работал консультантом в ThoughtWorks. Посетите блог Алекса.



18.03.2013

Codan ― это система анализа кода, которая проверяет код в проектах C/C++. С 2011 года Codan входит в пакет Eclipse CDT (C/C++ Development Tooling). Он не только обеспечивает инфраструктуру, необходимую для статического анализа кода, но и содержит полезные, готовые к применению модули выявления проблем (см. раздел Ресурсы).

В июне 2012 года вышла версия Eclipse Juno с обновленным Codan, который теперь предоставляет разработчикам возможность автоматически выполнять из Eclipse внешние инструменты анализа кода. Это очень полезное усовершенствование для C/C++-программистов, использующих Eclipse CDT. Сколь ни хороши были прежние модули выявления проблем, для того чтобы Codan мог соперничать с современными внешними анализаторами кода, необходимы многие другие. Теперь в Codan легко интегрировать готовые внешние инструменты, такие как Cppcheck и clang_check.

Сопутствующие руководства developerWorks

Подробнее о разработке приложений с применением Eclipse CDT:

Интеграция внешних анализаторов кода в Eclipse CDT позволяет быстрее и лучше проверять код. Она обещает значительно повысить и общую производительность труда разработчиков. Внешние анализаторы кода теперь можно настраивать прямо на страницах свойств Codan. После интеграции с Codan инструменты вызываются автоматически, и результаты их работы отображаются в виде маркеров редактора.

В этой статье показано, как написать Java-код с некоторым вкраплением XML для интеграции своих любимых аналитических инструментов в среду разработки Eclipse C/C++. Пример основан на интеграции в Codan инструмента Cppcheck, но тот же процесс должен быть применим и к любому другому инструменту.

Установка Eclipse Juno и CDT

Для того чтобы выполнить примеры из этой статьи, нужно установить Eclipse Juno и CDT. Если среда Eclipse еще не установлена, можно сразу установить версию с CDT. Для этого просто выберите Eclipse IDE for C/C++ Developers (Eclipse IDE для C/C++-разработчиков) на странице загрузки Eclipse.

Если уже установлена среда Eclipse без CDT, обновите ее. Для этого:

  1. В Eclipse выберите меню Help > Install New Software....
  2. В диалоговом окне Install выберите из раскрывающегося списка Juno.
  3. В категории Programming Languages (Языки программирования) выберите C/C++ Development Tools SDK.
Рисунок 1. Установка CDT
Установка CDT

В дополнение к CDT понадобятся стандартные инструменты разработки GNU C/C++ для компиляции, сборки и отладки кода. Инструкции по установке этих инструментов приведены в разделе Ресурсы.

Запуск Codan

Большинство анализаторов кода Codan включено по умолчанию. Их можно настраивать индивидуально на уровне рабочей области или проекта, соответственно используя страницы Eclipse Preferences или Project Property.

На странице Codan Preferences, показанной на рисунке 2, видны все доступные анализаторы кода и проблемы, выявляемые каждым из них.

Рисунок 2. Анализаторы кода на странице свойств Codan
Анализаторы кода на странице свойств Codan.

На этой странице можно включать и отключать анализаторы или изменять степень серьезности проблем. Если нужно настроить другие свойства для отдельных проблем, выберите проблему и нажмите кнопку Customize Selected.... Рисунок 3 иллюстрирует параметры конфигурации для проблемы Name convention for function (Соглашение об именах функций).

Рисунок 3. Настройка параметров проблемы
Настройка параметров проблемы

Третья вкладка на рисунке 3 позволяет указать, как следует запускать анализатор проблемы.

  • Run as you type: когда пользователь вносит изменения в файл в редакторе CDT.
  • Run on file open: при открытии файла в редакторе CDT.
  • Run on file save: при сохранении изменений в редакторе CDT.
  • Run on incremental build: при запуске инкрементной сборки (обычно, когда файл сохранен, и включен параметр уровня проекта Build Automatically [собрать автоматически]). Если этот параметр включен вместе с параметром Run on file save, то проверка кода будет осуществляться дважды.
  • Run on full build: при выпуске полной сборки (например, при очистке проекта).
  • Run on demand: когда пользователь вручную запускает проверку кода посредством пункта контекстного меню Run C/C++ Code Analysis (запуск анализа кода C/C++).

Проверка кода с помощью Codan

Чтобы продемонстрировать Codan в работе, создадим C++-проект с небольшим файлом C++. В этом файле я присвою переменную самой себе. Codan содержит анализатор кода Assignment to itself (автоприсвоение), который включен по умолчанию с уровнем серьезности error. Он настроен на работу по мере набора текста, так что сообщение об ошибке появится немедленно.

Рисунок 4. Codan проверяет код
Выполнение проверки кода.

На рисунке 4 видно, что Codan обнаружил ошибку автоприсвоения и сообщил о ней, прежде чем я успел сохранить файл. Идеально!

Подробнее об использовании Codan можно узнать на странице проекта (см. раздел Ресурсы).

Интеграция Cppcheck в Eclipse CDT

Чтобы интегрировать в Codan внешний анализатор кода, нужно написать специальный модуль проверки, который будет извлекать этот инструмент. Модуль проверки ― это реализация интерфейса Codan IChecker, которая выполняет проверку кода для заданного ресурса IResource (обычно IFile).

Чтобы продемонстрировать, как легко создать модуль проверки на основе внешнего инструмента, мы напишем программу, которая вызывает популярный инструмент Cppcheck (см. раздел Ресурсы). Вот что мы сделаем:

  • создадим проект Eclipse-плагина и добавим в качестве зависимости Codan;
  • Напишем анализатор ошибок (error parser) для анализа выходных данных Cppcheck и создания при необходимости маркеров редактора;
  • напишем анализатор кода, который представляет собой класс, вызывающий Cppcheck.

Шаг 1. Создание проекта Eclipse-плагина

Начинаем написание модуля проверки Codan с создания нового проекта Eclipse-плагина.

  1. Выберите из меню File > New > Project....
  2. В категории Plug-in Development выберите Plug-in Project.
  3. Введите имя проекта (у меня ― CppcheckChecker) и нажмите кнопку Next.
  4. Примите значения по умолчанию и нажмите кнопку Finish.
Рисунок 5. Создание проекта плагина
Скриншот процесса создания проекта.

Сразу после создания нового проекта плагина Eclipse автоматически откроет файл MANIFEST.MF. Это файл, куда мы добавим зависимости Codan.

В редакторе выберите вкладку Dependencies и добавьте в список необходимых плагинов следующие записи:

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

Eclipse-плагины

Я не буду во всех подробностях описывать в этой статье процесс написания Eclipse-плагинов, потому что она посвящена не Eclipse. Ссылка на введение в написание Eclipse-плагинов приведена в разделе Ресурсы.

Шаг 2. Создание анализатора ошибок

Для создания маркеров редактора по выходным данным Cppcheck нам понадобится анализатор ошибок, поэтому на следующем шаге мы дополним инструментарий Eclipse C/C++ новым плагином. Для этой цели воспользуемся кодом Java, потому что Eclipse представляет собой Java-приложение.

Сначала создадим класс CppcheckErrorParser, реализующий метод org.eclipse.cdt.core.IErrorParser. Начнем с поиска шаблона, который Cppcheck использует при сообщении о проблемах кода. Анализатор ошибок будет использовать этот шаблон для определения строки вывода, которая представляет собой сообщение о проблеме, с последующим извлечением из нее информации, необходимой для создания маркера редактора.

Листинг 1. Шаблон для анализа выхода Cppcheck
  // пример строки для разбора:
  //
  // [/src/HelloWorld.cpp:19]: (style) The scope of the variable 'i' can be reduced
  // ----------1--------- -2    --3--  ------------------4-------------------------
  //
  // группы:
  // 1: путь и имя файла
  // 2: строка, в которой обнаружена проблема
  // 3: серьезность проблемы
  // 4: описание проблемы
  private static Pattern pattern = 
      Pattern.compile("\\[(.*):(\\d+)\\]:\\s*\\((.*)\\)\\s*(.*)");

Листинг 2 показывает, как анализатор ошибок использует шаблон для извлечения пути и имени проверяемого файла, а также местонахождения, описания и степени серьезности обнаруженной ошибки. По этой информации анализатор ошибок создает новый маркер ProblemMarkerInfo и передает его классу ErrorParserManager. ErrorParserManager — это класс, ответственный за создание маркеров редактора.

Листинг 2. Обработка вывода 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;
  }
}

Преобразование степени серьезности проблемы

Cppcheck использует свои собственные степени серьезности проблемы, которые могут не совпадать с теми, которые используются маркерами редактора. Например, степень серьезности Cppcheck style не имеет аналога в Eclipse. Чтобы решить эту проблему, нужно выполнить преобразование между двумя наборами значений степени серьезности проблем. Метод findSeverityCode являет собой простой способ такого преобразования (см. Листинг 3).

Листинг 3. Преобразование степени серьезности проблемы
  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;
  }

Теперь любая проблема со степенью серьезности style, о которой сообщает Cppcheck, будет отображаться в Eclipse с указанием степени серьезности SEVERITY_INFO. Это преобразование определяет только значения по умолчанию для степени серьезности проблем. Позже вы увидите, что такое преобразование можно настроить на странице свойств Codan.

Чтобы Codan распознал CppcheckErrorParser, его необходимо зарегистрировать в файле plugin.xml, используя точку расширения org.eclipse.cdt.core.ErrorParser (см. Листинг 4).

Листинг 4. Регистрация анализатора ошибок
  <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>

В листинге 4 видно, что точка расширения ErrorParser первоначально предназначалась для регистрации анализаторов для инструментов сборки CDT. Это относится не только к Codan. Чтобы указать, что CppcheckErrorParser следует использовать только с Codan, добавим контекст codan.

Шаг 3. Создание анализатора кода

AbstractExternalToolBasedChecker ― это суперкласс для любых внешних анализаторов кода Codan на основе внешних инструментов. Он обеспечивает большую часть инфраструктуры, необходимой для вызова внешнего инструмента анализа кода. Так как мы интегрируем Cppcheck, назовем этот класс CppcheckChecker.

Первое, что нужно сделать, это указать значения по умолчанию для информации, связанной с внешним инструментом, которая будет отображаться на странице свойств Codan.

Эта информация, которую нужно передать конструктору анализатора, содержит следующие компоненты:

  • имя внешнего инструмента анализа кода, в данном случае Cppcheck;
  • имя исполняемого файла инструмента ― cppcheck. Нам не нужно указывать путь к исполняемому файлу, потому что мы предполагаем, что он присутствует в системной переменной PATH;
  • аргументы для передачи в исполняемый файл, содержащиеся в одной строке. Мы указываем --enable=all, чтобы разрешить все проверки Cppcheck.
Листинг 5. Информация Cppcheck по умолчанию
  public CppCheckChecker() {
    super(new ConfigurationSettings("Cppcheck", new File("cppcheck"), "--enable=all"));
  }

Обратите внимание, что страница свойств Codan позволяет изменить как путь к исполняемому файлу, так и передаваемые аргументы.

Сопоставление серьезности проблемы с идентификаторами проблем

Далее, мы хотим указать идентификаторы анализаторов ошибок, которые будем использовать, как показано в листинге 6. Идентификаторы должны совпадать с теми, которые используются в файле plugin.xml.

Листинг 6. Указание используемых идентификаторов анализаторов ошибок
  @Override
  protected String[] getParserIDs() {
    return new String[] { "com.dw.cdt.checkers.CppcheckErrorParser" };
  }

Еще в листинге 2 мы создали метод ProblemMarkerInfo и передали его в ErrorParserManager для создания маркеров редактора. ErrorParserManager делегирует создание маркеров редактора нашему вновь созданному анализатору.

Для того чтобы анализатор создал маркер редактора, нужно переопределить метод addMarker(ProblemMarkerInfo) (задача которого заключается в том, чтобы искать несоответствия другого типа). Анализаторы Codan не могут создавать маркеры редактора непосредственно из ProblemMarkerInfo. Им нужен свой собственный механизм, использующий идентификаторы проблем для выяснения степени серьезности созданного маркера редактора.

Идентификатор проблемы — это уникальный идентификатор, который Codan использует для указания проблемы, выявленной модулем проверки кода. Все проблемы кода отображаются на странице свойств Codan (см. Рисунок 2).

Листинг 7. Создание маркеров ошибок
  @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);
  }

Чтобы найти идентификатор проблемы со степенью серьезности ProblemMarkerInfo, нужно сопоставить степени серьезности и идентификаторы проблем. Листинг 8 демонстрирует, как реализовать такое сопоставление.

Листинг 8. Сопоставление степеней серьезности проблем с их идентификаторами
  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");
  }

Анализаторы кода, использующие внешний инструмент анализа, должны указать, какие из их идентификаторов проблем считаются «справочными». Справочный идентификатор проблемы используется для получения справочных значений анализатора (таких как имя внешнего инструмента, см. Листинг 5). Не важно, какой именно идентификатор проблемы будет справочным, потому что у всех проблем одни и те же свойства.

Листинг 9. Указание справочного идентификатора проблемы
  @Override
  protected String getReferenceProblemId() {
    return ERROR_PROBLEM_ID;
  }

Константа ERROR_PROBLEM_ID определена в листинге 8.

Регистрация модуля проверки

Для того чтобы модуль проверки и все проблемы, которые он выявляет, присутствовали на странице свойств Codan (и, следовательно, были доступны для пользователя), его нужно зарегистрировать в файле Codan plugin.xml.

Нам не известны все проблемы, которые может выявить Cppcheck, и мы не можем предотвратить добавление или удаление анализаторов в будущих версиях Cppcheck, поэтому мы не сможем зарегистрировать каждую конкретную проблему. Вместо этого сгруппируем проблемы по степени серьезности и будем рассматривать каждую группу как отдельную проблему. Листинг 10 регистрирует группы errors (ошибки), warnings (предупреждения) и style violations (нарушения стиля) как три отдельных проблемы.

Листинг 10. Регистрация модуля проверки и сообщений о проблемах
  <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>

Мы указали имя модуля проверки, которое будет отображаться пользователям в элементе category. Идентификаторы проблем должны быть такими же, что и те, что используются в анализаторе (см. Листинг 8).

В файле plugin.xml мы указываем следующие сведения обо всех трех проблемах:

  • они разрешены по умолчанию;
  • они имеют степени серьезности по умолчанию соответственно Error, Warning и Info;
  • их шаблон сообщения: {0}, что заставляет Codan использовать описание проблемы, переданное из Cppcheck.

Использование Cppcheck в Codan

Теперь CppcheckChecker виден на странице свойств Codan, как показано на рисунке 6.

Рисунок 6. Cppcheck отображается на странице свойств Codan
Cppcheck отображается на странице свойств Codan

На рисунке 7 показаны параметры настройки процесса уведомления Cppcheck об ошибках кода.

Рисунок 7. Настройка процесса сообщения Cppcheck об ошибках
Настройки Cppcheck

На рисунке 8 видно, как Cppcheck сообщает о проблемах кода. Обратите внимание, что Cppcheck вызывается автоматически после сохранения файла.

Рисунок 8. Отчет Cppcheck
Скриншот отчета Cppcheck

Недостатки интеграции

Один недостаток интеграции Codan с внешними инструментами анализа кода состоит, что анализаторы на основе внешнего инструмента не могут работать, пока пользователь набирает текст. Потому что внешний инструмент не видит изменений в несохраненном файле. Поэтому внешний анализатор необходимо запускать, когда файл открыт и сохранен.

Однако это ограничение перевешиваются преимуществами использования зрелого инструмента анализа кода. К тому же интегрировать внешний инструмент с Codan намного проще, чем создать обычный анализатор, что потребовало бы глубокого знания языков C или C++ и реализации AST для CDT. Между тем мы смогли написать CppcheckChecker, содержащий всего около 100 строк простого Java-кода (в двух классах) и 30 строк XML.

Заключение

До выпуска Eclipse Juno написание специального кода проверки для Codan требовало глубокого знания языков C/C++ и CDT-реализации AST. Версия Juno CDT Eclipse решает эту проблему, позволяя разработчикам создавать анализаторы кода Codan, способные делегировать всю тяжелую работу внешнему инструменту анализа кода.

В этой статье мы написали совсем немного кода Java и XML для интеграции Cppcheck с Codan, объединив этот популярный инструмент анализа кода C/C++ со средой анализа кода C/C++-программ, встроенной в Eclipse. Как говорилось выше, продемонстрированный здесь процесс можно применить к любому инструменту анализа кода. Подробности ― в разделе Ресурсы.

Ресурсы

Научиться

Получить продукты и технологии

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java, Open source, XML
ArticleID=861709
ArticleTitle=Интеграция внешнего инструмента проверки кода в Eclipse CDT
publish-date=03182013