clang-format: IncludeIsMainRegex не работает

У меня проблема с поиском основного включения для моих исходных файлов. Но пошагово.

Файл z.h

#include "test"
#include "azd"
#include <vector> 
#include <boost/something>
#include <map>

Файл z.C

#include "test"
#include "azd"
#include <vector>
#include <boost/something>
#include <map>
#include "z.h"

Файл (часть) .clang-формата, расположенный вместе с z.h и z.C

BasedOnStyle: LLVM
Language: Cpp
IncludeIsMainRegex: '(_test)?$'
IncludeCategories:
- Regex:    '^(<boost)'
  Priority: 3
- Regex:    '^<'
  Priority: 4
- Regex:    '.*'
  Priority: 1

Теперь тестирование:

$ clang-format z.h

#include "azd"
#include "test"
#include <boost/something>
#include <map>
#include <vector>

Здесь все выглядит отлично, включает отсортировано как положено, но

$ clang-format z.C

#include "azd"
#include "test"
#include "z.h"
#include <boost/something>
#include <map>
#include <vector>

Здесь "a.z" находится посередине, хотя он должен быть обнаружен '(_test)? $' Как main include. Самое смешное, что когда я переименовываю z.C -> z.cc, а затем:

$ clang-format z.cc

#include "z.h"
#include "azd"
#include "test"
#include <boost/something>
#include <map>
#include <vector>

работает нормально ...

Кажется, что clang-format не распознает файлы * .C как язык C ++. Я работаю над проектом C ++, где у меня нет возможности переименовать все файлы * .C в * .cc, поэтому, пожалуйста, может кто-нибудь сказать мне, как заставить clang-format использовать форматирование стиля C ++ для файлов * .C? Или решить эту проблему с поиском основного включения другим подходом?

И второй вопрос / вопрос. Иногда мы разделяем объявления и определения шаблонов на файлы template.h и templateImpl.h. Как заставить clang-format обрабатывать templateImpl.h как источник и помещать #include "template.h" в качестве основного include?

С Уважением


person Darek    schedule 03.08.2017    source источник


Ответы (1)


Похоже, единственное, что не работает в вашем случае, - это опция IncludeIsMainRegex, когда исходный файл имеет расширение *.C.

Если я не ошибаюсь, то сейчас эта опция работает только с исходными файлами, имеющими *.c, *.cc, *.cpp, *.c++, *.cxx расширения.

Мои предположения основаны на этом фрагменте кода из clang (v7.0.0), файл clang/lib/Tooling/Inclusions/HeaderIncludes.cpp:

IncludeCategoryManager::IncludeCategoryManager(const IncludeStyle &Style,
                                               StringRef FileName)
    : Style(Style), FileName(FileName) {
  FileStem = llvm::sys::path::stem(FileName);
  for (const auto &Category : Style.IncludeCategories)
    CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
  IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
               FileName.endswith(".cpp") || FileName.endswith(".c++") ||
               FileName.endswith(".cxx") || FileName.endswith(".m") ||
               FileName.endswith(".mm");
}

int IncludeCategoryManager::getIncludePriority(StringRef IncludeName,
                                               bool CheckMainHeader) const {
  int Ret = INT_MAX;
  for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
    if (CategoryRegexs[i].match(IncludeName)) {
      Ret = Style.IncludeCategories[i].Priority;
      break;
    }
  if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
    Ret = 0;
  return Ret;
}

bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
  if (!IncludeName.startswith("\""))
    return false;
  StringRef HeaderStem =
      llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
  if (FileStem.startswith(HeaderStem) ||
      FileStem.startswith_lower(HeaderStem)) {
    llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
                                 llvm::Regex::IgnoreCase);
    if (MainIncludeRegex.match(FileStem))
      return true;
  }
  return false;
}
person Kostiantyn Ponomarenko    schedule 03.12.2018