Delen via


Gestructureerde SARIF Diagnostics

De MSVC-compiler kan worden gemaakt om diagnostische gegevens uit te voeren als SARIF (Static Analysis Results Interchange Format). SARIF is een op machines leesbare JSON-indeling.

Er zijn twee manieren om de MSVC-compiler SARIF-diagnostische gegevens te laten produceren:

  • Geef de /experimental:log schakeloptie door op de opdrachtregel. Raadpleeg de documentatie voor /experimental:log meer informatie.
  • Start cl.exe programmatisch en stel de SARIF_OUTPUT_PIPE omgevingsvariabele in om SARIF-blokken via een pijp op te halen.

SARIF ophalen via een pijp

Hulpprogramma's die SARIF van de MSVC-compiler gebruiken terwijl er een compilatie wordt uitgevoerd, wordt een pijp gebruikt. Raadpleeg de documentatie voor CreatePipe meer informatie over het maken van Windows-pijpen.

Als u SARIF wilt ophalen via een pijp, stelt u de SARIF_OUTPUT_PIPE omgevingsvariabele in op de UTF-16-gecodeerde gehele getalweergave van het HANDLE naar het schrijfeind van de pijp en start cl.exeu vervolgens. SARIF wordt als volgt langs de pijp verzonden:

  • Wanneer er een nieuwe diagnose beschikbaar is, wordt deze naar deze pijp geschreven.
  • Diagnostische gegevens worden één voor één naar de pijp geschreven in plaats van als een volledig SARIF-object.
  • Elke diagnose wordt vertegenwoordigd door een JSON-RPC 2.0-bericht van het type Melding.
  • Het JSON-RPC bericht wordt voorafgegaan door een Content-Length koptekst met het formulier Content-Length: <N> gevolgd door twee nieuwe regels, waarbij <N> de lengte is van het volgende JSON-RPC bericht in bytes.
  • Het JSON-RPC bericht en de koptekst zijn beide gecodeerd in UTF-8.
  • Deze JSON-RPC-with-header-indeling is compatibel met vs-streamjsonrpc.
  • De methodenaam voor de JSON-RPC aanroep is OnSarifResult.
  • De aanroep heeft één parameter die is gecodeerd op naam met de parameternaam result.
  • De waarde van het argument is één result object zoals opgegeven door de SARIF versie 2.1-standaard.

Voorbeeld

Hier volgt een voorbeeld van een JSON-RPC SARIF-resultaat geproduceerd door 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-resultaatgegevens

De compiler voert SARIF uit die mogelijk aanvullende informatie bevat om de geneste structuur van bepaalde diagnostische gegevens weer te geven. Een diagnose (vertegenwoordigd door een result SARIF-object) kan een 'diagnostische structuur' van aanvullende informatie in het relatedLocations veld bevatten. Deze structuur wordt als volgt gecodeerd met behulp van een SARIF-eigenschappentas :

Het location veld van properties een object kan een nestingLevel eigenschap bevatten waarvan de waarde de diepte is van deze locatie in de diagnostische structuur. Als een locatie geen opgegeven locatie heeft nestingLevel , wordt de diepte als beschouwd 0 en deze locatie is een onderliggend element van de hoofddiagnose die wordt vertegenwoordigd door het result object dat het bevat. Als de waarde groter is dan de diepte van de locatie direct voorafgaand aan deze locatie in het relatedLocations veld, is deze locatie een onderliggend element van die locatie. Anders is deze locatie een niveau van het dichtstbijzijnde voorafgaande location aan het relatedLocations veld met dezelfde diepte.

Voorbeeld

Houd rekening met de volgende code:

struct dog {};
struct cat {};

void pet(dog);
void pet(cat);

struct lizard {};

int main() {
    pet(lizard{});
}

Wanneer deze code wordt gecompileerd, produceert de compiler het volgende result object (physicalLocation eigenschappen zijn verwijderd ter beknoptheid):

{
    "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)'"
            }
        }
    ]
}

De logische diagnostische structuur die wordt geproduceerd op basis van de berichten in dit result object is:

  • 'huisdier': geen overbelaste functie kan alle argumenttypen converteren
    • kan 'ongeldig huisdier(kat)' zijn
      • 'void pet(cat)': kan argument 1 niet converteren van 'hagedis' naar 'kat'.
        • Er is geen door de gebruiker gedefinieerde conversieoperator beschikbaar die deze conversie kan uitvoeren of de operator kan niet worden aangeroepen
    • of 'void pet(dog)'
      • 'void pet(dog)': argument 1 kan niet worden geconverteerd van 'hagedis' naar 'hond'
        • Er is geen door de gebruiker gedefinieerde conversieoperator beschikbaar die deze conversie kan uitvoeren of de operator kan niet worden aangeroepen
    • tijdens een poging om overeen te komen met de lijst met argumenten '(hagedis)'

Zie ook

/experimental:log (Gestructureerde SARIF-diagnose inschakelen)