Структурированная диагностика SARIF
Компилятор MSVC можно сделать для вывода диагностика как SARIF (формат обмена статическими результатами анализа). SARIF — это формат на основе JSON, доступный для машинного чтения.
Существует два способа создания ДИАГНОСТИКА компилятора MSVC:
- Передайте переключатель
/experimental:log
в командной строке. Дополнительные сведения см. в документации/experimental:log
. - Запустите
cl.exe
программу и задайтеSARIF_OUTPUT_PIPE
переменную среды для получения блоков SARIF через канал.
Извлечение SARIF через канал
Средства, использующие SARIF из компилятора MSVC во время компиляции, используют канал. Дополнительные сведения о создании каналов Windows см. в документации CreatePipe
.
Чтобы получить SARIF через канал, задайте SARIF_OUTPUT_PIPE
переменную среды в виде целого числа HANDLE
в кодировке UTF-16 для конца записи, а затем запустите cl.exe
. SARIF отправляется по каналу следующим образом:
- Когда доступна новая диагностика, она записывается в этот канал.
- Диагностика записывается в канал один раз, а не как весь объект SARIF.
- Каждая диагностика представлена сообщением JSON-RPC 2.0 типа Notification.
- Сообщение JSON-RPC префиксируется заголовком с формой
Content-Length
Content-Length: <N>
, за которой следует две новые строки, где<N>
длина следующего сообщения JSON-RPC в байтах. - Сообщение JSON-RPC и заголовок кодируются в UTF-8.
- Этот формат JSON-RPC-with-header совместим с vs-streamjsonrpc.
- Имя метода для вызова
OnSarifResult
JSON-RPC. - Вызов имеет один параметр, закодированный по имени с именем
result
параметра. - Значение аргумента — это один
result
объект, указанный стандартом SARIF версии 2.1.
Пример
Ниже приведен пример результата JSON-RPC SARIF, созданного следующим cl.exe
образом:
Content-Length: 334
{"jsonrpc":"2.0","method":"OnSarifResult","params":{"result":{"ruleId":"C1034","level":"fatal","message":{"text":"iostream: no include path set"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"},"region":{"startLine":1,"startColumn":10}}}]}}}{"jsonrpc":"2.0","method":"OnSarifResult","params":{"result":{"ruleId":"C1034","level":"fatal","message":{"text":"iostream: no include path set"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"},"region":{"startLine":1,"startColumn":10}}}]}}}
Данные результатов SARIF
Компилятор выводит SARIF, который может содержать дополнительные сведения для представления вложенной структуры некоторых диагностика. Диагностика (представленная result
объектом SARIF) может содержать "дерево диагностики" дополнительных сведений в своем relatedLocations
поле. Это дерево закодировано с помощью контейнера свойств SARIF следующим образом:
location
Поле объекта properties
может содержать nestingLevel
свойство, значение которого — глубина этого расположения в дереве диагностики. Если в расположении нет nestingLevel
указанного расположения, глубина считается 0
дочерней из корневой диагностики, представленной result
объектом, содержащим его. В противном случае, если значение больше глубины расположения, непосредственно предшествующего этому расположению в relatedLocations
поле, это расположение является дочерним элементом этого расположения. В противном случае это расположение является братом ближайшего предыдущего location
в relatedLocations
поле с той же глубиной.
Пример
Рассмотрим следующий код:
struct dog {};
struct cat {};
void pet(dog);
void pet(cat);
struct lizard {};
int main() {
pet(lizard{});
}
При компиляции этого кода компилятор создает следующий result
объект (physicalLocation
свойства были удалены для краткости):
{
"ruleId": "C2665",
"level": "error",
"message": {
"text": "'pet': no overloaded function could convert all the argument types"
},
"relatedLocations": [
{
"id": 0,
"message": {
"text": "could be 'void pet(cat)'"
}
},
{
"id": 1,
"message": {
"text": "'void pet(cat)': cannot convert argument 1 from 'lizard' to 'cat'"
},
"properties": {
"nestingLevel": 1
}
},
{
"id": 2,
"message": {
"text": "No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called"
},
"properties": {
"nestingLevel": 2
}
},
{
"id": 3,
"message": {
"text": "or 'void pet(dog)'"
}
},
{
"id": 4,
"message": {
"text": "'void pet(dog)': cannot convert argument 1 from 'lizard' to 'dog'"
},
"properties": {
"nestingLevel": 1
}
},
{
"id": 5,
"message": {
"text": "No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called"
},
"properties": {
"nestingLevel": 2
}
},
{
"id": 6,
"message": {
"text": "while trying to match the argument list '(lizard)'"
}
}
]
}
Логическое диагностика дерево, создаваемое из сообщений в этом result
объекте:
- "pet": перегруженная функция не может преобразовать все типы аргументов
- может быть "void pet(cat)"
- "void pet(cat)": не может преобразовать аргумент 1 из "ящерица" в "cat"
- Нет определяемого пользователем оператора преобразования, который может выполнять это преобразование, или не удается вызвать оператор.
- "void pet(cat)": не может преобразовать аргумент 1 из "ящерица" в "cat"
- или "void pet(dog)"
- "void pet(dog)": не может преобразовать аргумент 1 из "ящерица" в "собака"
- Нет определяемого пользователем оператора преобразования, который может выполнять это преобразование, или не удается вызвать оператор.
- "void pet(dog)": не может преобразовать аргумент 1 из "ящерица" в "собака"
- при попытке сопоставить список аргументов "(ящерица)"
- может быть "void pet(cat)"
См. также
/experimental:log
(Включение структурированных диагностика SARIF)