tgoop.com/cxx95/61
Create:
Last Update:
Last Update:
#compiler
clang-format: царь-костыль 🩼
Я раньше писал про clang-tidy в этом блоге. Он нужен для проверки кода на качество. У него модульный вид - каждый может написать свою проверку и использовать множество независимых друг от друга проверок. Он работает на уровне AST, то есть код проходит лексический и синтаксический анализ до тулзы.
А clang-format это еще одна тулза, нужная для форматирования исходного кода - чтобы было нужное количество пробелов, отсортированные #include
и прочее. Он работает на уровне токенов, то есть код проходит только лексический анализ до тулзы.
То есть clang-format
очень приблизительно понимает, что перед ним за токен и что нужно сделать. Например, текст
class A: B {ему это видится как последовательность токенов
(kw_class) (identifier) (colon) (identifier) (l_brace)
И clang-format
применяет серию захардкоженных правил поверх этих токенов, с поддержкой разной фигни как стека вложенности для скобок. Никакой модульности нет, то есть все правила написаны прямо в глубине тулзы.Например, в какой-то момент в середине работы вызывается метод WhitespaceManager::generateReplacements, который поправляет пробелы, и в нем внутри метод WhitespaceManager::alignArrayInitializers, чтобы поправить пробелы в массивах.
Совсем без семантики форматировать сложно, поэтому
clang-format
перед форматированием "аннотирует" токены дополнительными данными: сопоставляет каждому Token
структуру FormatToken
.Там есть всякие поля, как bool IsArrayInitializer (то что этот токен - начало array initialization);
или FormatToken *MatchingParen (ссылка на закрывающую скобку).
Работает все при таком подходе очень хреново
Есть куча issue про clang-format, а чинить их значительно сложнее чем issue для
clang-tidy
.Если в
clang-tidy
область потенциальных правок - код отдельной проверки (максимум несколько сотен строк), то в clang-format
это весь clang-format
.Например, очень сложно починить такой пустяк как неработающее форматированое во вложенном внутри скобок array initializer. Дело в том, что форматирование полагается на "аннотацию" токенов, а оно именно такое для вложенных скобок, какое есть. Надо править "аннотатор", но это сложно и есть риск сломать что-то еще.
И так для многих issue - начинаешь разбираться в мелкой проблеме - почему ставится лишний пробел, раскрываешь всю цепочку причин, и получаешь мега-проблему, которую нереально починить.
Поэтому старайтесь делать модульные программы, чтобы уменьшить область потенциальных правок при починке бага