Skip to content

Commit

Permalink
Dev Release 2.5.0 (#100)
Browse files Browse the repository at this point in the history
* Added feature to open and convert non-sarif static analysis file to sarif for analysis (#79)
    * New command to activate the converter is "Sarif: Convert and open a non-sarif file"
    * Supported analysis tool files are:
        * AndroidStudio, ClangAnalyzer, CppCheck, Fortify, FortifyFpr, FxCop, PREfast, Pylint, SemmleQL, StaticDriverVerifier, TSLint
* Added support for showing QuickFix light bulb and context menu in the Problems panel when a Sarif result can be remapped (#98)
* Fixed bug where the UI dialog for remapping allowed a non valid path to be entered (#92)
* Fixed bug where the Sarif Explorer showed empty when a sarif result was missing data such as rule id, rule name or location (#94)
  • Loading branch information
rscrivens authored Sep 24, 2018
1 parent 976d627 commit 5e4dfed
Show file tree
Hide file tree
Showing 127 changed files with 582 additions and 91 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Change Log

## 2.5.0
* Added feature to open and convert non-sarif static analysis file to sarif for analysis [issue #79](https://github.com/Microsoft/sarif-vscode-extension/issues/79)
* New command to activate the converter is "Sarif: Convert and open a non-sarif file"
* Supported analysis tool files are:
* AndroidStudio, ClangAnalyzer, CppCheck, Fortify, FortifyFpr, FxCop, PREfast, Pylint, SemmleQL, StaticDriverVerifier, TSLint
* Added support for showing QuickFix light bulb and context menu in the Problems panel when a Sarif result can be remapped
* Fixed bug where the UI dialog for remapping allowed a non valid path to be entered [issue #92](https://github.com/Microsoft/sarif-vscode-extension/issues/92)
* Fixed bug where the Sarif Explorer showed empty when a sarif result was missing data such as rule id, rule name or location

## 2.4.0
* Changed the remapping files input box UX: [issue #71](https://github.com/Microsoft/sarif-vscode-extension/issues/71)
* Added a button that opens a file picker, and populates the input box with the path of the file selected
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Visualizes the results contained in a 'Static Analysis Results Interchange Forma
* Supports embedded target files
* Allows you to remap (in memory) source locations, if they can't be found using the location in the log file
* Can set rootpaths in the settings for the extension to try when looking for files, ex. the rootpath of your local enlistment
* *new* Can open and convert a non-sarif static analysis file to sarif for analysis - see ChangeLog for list of supported tools
* To execute the convert command via the Command window(F1 key):
1. Type in "Sarif: Convert and open a non-sarif file"
2. Select the tool that generated the file
3. In the file picker that opens up select the file

### Sarif Explorer:
* Automatically launches when the first result is navigated to
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "The Sarif Viewer extension visualizes the results in a Sarif file",
"author": "Microsoft Corporation",
"license": "MIT",
"version": "2.4.0",
"version": "2.5.0",
"publisher": "MS-SarifVSCode",
"repository": {
"type": "git",
Expand All @@ -29,6 +29,7 @@
},
"activationEvents": [
"onLanguage:json",
"onCommand:extension.sarif.Convert",
"onCommand:extension.sarif.LaunchExplorer"
],
"main": "./out/extension",
Expand All @@ -54,6 +55,11 @@
}
],
"commands": [
{
"command": "extension.sarif.Convert",
"title": "Convert and open a non-sarif file",
"category": "Sarif"
},
{
"command": "extension.sarif.LaunchExplorer",
"title": "Launch the Sarif Explorer",
Expand Down
Binary file added resources/sarif.multitool/CommandLine.dll
Binary file not shown.
Binary file added resources/sarif.multitool/CsvHelper.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/Newtonsoft.Json.dll
Binary file not shown.
Binary file added resources/sarif.multitool/Sarif.Converters.dll
Binary file not shown.
Binary file added resources/sarif.multitool/Sarif.Driver.dll
Binary file not shown.
Binary file added resources/sarif.multitool/Sarif.Multitool.exe
Binary file not shown.
323 changes: 323 additions & 0 deletions resources/sarif.multitool/Sarif.Multitool.exe.config

Large diffs are not rendered by default.

Binary file added resources/sarif.multitool/Sarif.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Collections.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Console.dll
Binary file not shown.
Binary file added resources/sarif.multitool/System.Data.Common.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.IO.Pipes.dll
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.IO.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Linq.dll
Binary file not shown.
Binary file added resources/sarif.multitool/System.Net.Http.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Net.Ping.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Net.Security.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.ObjectModel.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Runtime.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Threading.dll
Binary file not shown.
Binary file added resources/sarif.multitool/System.ValueTuple.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/System.Xml.XPath.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added resources/sarif.multitool/netstandard.dll
Binary file not shown.
2 changes: 1 addition & 1 deletion src/CodeFlows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class CodeFlows {
const thread = codeFlow.threads[tFKey];
for (const stepKey of thread.steps.keys()) {
const step = thread.steps[stepKey];
if (step.location !== null && step.location.mapped !== true) {
if (step.location !== undefined && step.location.mapped !== true) {
const sarifLoc = sarifCodeFlows[cFKey].threadFlows[tFKey].locations[stepKey].location;
await LocationFactory.create(sarifLoc.physicalLocation, runId).then((location: Location) => {
codeFlows[cFKey].threads[tFKey].steps[stepKey].location = location;
Expand Down
101 changes: 101 additions & 0 deletions src/FileConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// /********************************************************
// * *
// * Copyright (C) Microsoft. All rights reserved. *
// * *
// ********************************************************/
import {
commands, extensions, MessageOptions, OpenDialogOptions, TextDocumentShowOptions, Uri, ViewColumn, window,
} from "vscode";
import { Utilities } from "./Utilities";

/**
* Handles converting a non sarif static analysis file to a sarif file via the sarif-sdk multitool
*/
export class FileConverter {
public static ConvertCommand = "extension.sarif.Convert";

/**
* Opens a quick pick list to select a tool, then opens a file picker to select the file and converts selected file
*/
public static selectConverter() {
let tool: string;
window.showQuickPick(Array.from(FileConverter.Tools.keys())).then((value: string) => {
if (value === undefined) {
return;
}

tool = value;
const dialogOptions = { canSelectFiles: true, canSelectMany: false, filters: {} } as OpenDialogOptions;
const toolExt = FileConverter.Tools.get(tool);
dialogOptions.filters[`${tool} log files`] = toolExt;

return window.showOpenDialog(dialogOptions);
}).then((uris: Uri[]) => {
if (uris !== undefined && uris.length > 0) {
FileConverter.convert(uris[0], tool);
}
});
}

private static childProcess;
private static multiTool: string;
private static tools: Map<string, string[]>;

private static get ChildProcess() {
if (FileConverter.childProcess === undefined) {
FileConverter.childProcess = require("child_process");
}

return FileConverter.childProcess;
}

private static get MultiTool(): string {
if (FileConverter.multiTool === undefined) {
FileConverter.multiTool = extensions.getExtension("MS-SarifVSCode.sarif-viewer").extensionPath +
"/resources/sarif.multitool/Sarif.Multitool.exe";
}

return FileConverter.multiTool;
}

private static get Tools(): Map<string, string[]> {
if (FileConverter.tools === undefined) {
FileConverter.tools = new Map<string, string[]>();
FileConverter.tools.set("AndroidStudio", ["xml"]);
FileConverter.tools.set("ClangAnalyzer", ["xml"]);
FileConverter.tools.set("CppCheck", ["xml"]);
FileConverter.tools.set("Fortify", ["xml"]);
FileConverter.tools.set("FortifyFpr", ["fpr"]);
FileConverter.tools.set("FxCop", ["fxcop", "xml"]);
FileConverter.tools.set("PREfast", ["xml"]);
FileConverter.tools.set("Pylint", ["json"]);
FileConverter.tools.set("SemmleQL", ["csv"]);
FileConverter.tools.set("StaticDriverVerifier", ["tt"]);
FileConverter.tools.set("TSLint", ["json"]);
}

return FileConverter.tools;
}

/**
* Converts a file generated by a tool to a sarif file format using the sarif sdk multitool
* @param uri path to the file to convert
* @param tool tool that generated the file to convert
*/
private static convert(uri: Uri, tool: string) {
const output = Utilities.generateTempPath(uri.fsPath) + ".sarif";
const proc = FileConverter.ChildProcess.spawn(FileConverter.MultiTool,
["convert", "-t", tool, "-o", output, "-p", "-f", uri.fsPath],
);

proc.on("close", (code) => {
if (code === 0) {
commands.executeCommand("vscode.open", Uri.file(output),
{ preserveFocus: false, preview: false, viewColumn: ViewColumn.One } as TextDocumentShowOptions);
} else {
window.showErrorMessage(`Sarif converter failed with error code: ${code}`,
{ modal: false } as MessageOptions);
}
});
}
}
81 changes: 7 additions & 74 deletions src/FileMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { Utilities } from "./Utilities";
export class FileMapper {
public static readonly MapCommand = "extension.sarif.Map";

private static readonly SarifViewerTempDir = "SarifViewerExtension";
private static instance: FileMapper;

private baseRemapping: Map<string, string>;
Expand Down Expand Up @@ -53,7 +52,6 @@ export class FileMapper {
*/
public dispose(): void {
this.changeConfigDisposable.dispose();
this.removeSarifViewerTempDirectory();
}

/**
Expand Down Expand Up @@ -188,42 +186,6 @@ export class FileMapper {
}
}

/**
* Loops through the passed in path's directories and creates the directory structure
* @param path directory path that needs to be created in temp directory(including temp directory)
*/
private createDirectoryInTemp(path: string): string {
const directories = path.split(Utilities.Path.sep);
let createPath: string = Utilities.Os.tmpdir();

for (const directory of directories) {
createPath = Utilities.Path.join(createPath, directory);
try {
Utilities.Fs.mkdirSync(createPath);
} catch (error) {
if (error.code !== "EEXIST") { throw error; }
}
}

return createPath;
}

/**
* Creates a readonly file at the path with the contents specified
* If the file already exists method will delete that file and replace it with the new one
* @param path path to create the file in
* @param contents content to add to the file after created
*/
private createReadOnlyFile(path: string, contents: string): void {
try {
Utilities.Fs.unlinkSync(path);
} catch (error) {
if (error.code !== "ENOENT") { throw error; }
}

Utilities.Fs.writeFileSync(path, contents, { mode: 0o444/*readonly*/ });
}

/**
* Gets the hash value for the embedded content. Preference for sha256, if not found it uses the first hash value
* @param hashes Array of hash objects
Expand Down Expand Up @@ -252,12 +214,7 @@ export class FileMapper {
private mapEmbeddedContent(fileUri: Uri, file: sarif.File): void {
const hashValue = this.getHashValue(file.hashes);
const fileUriPath = Utilities.getFsPathWithFragment(fileUri);
const pathObj = Utilities.Path.parse(fileUriPath);
let tempPath: string = Utilities.Path.join(FileMapper.SarifViewerTempDir, hashValue,
pathObj.dir.replace(pathObj.root, ""));
tempPath = tempPath.split("#").join(""); // remove the #s to not create a folder structure with fragments
tempPath = this.createDirectoryInTemp(tempPath);
tempPath = Utilities.Path.join(tempPath, Utilities.Path.win32.basename(fileUriPath));
const tempPath = Utilities.generateTempPath(fileUriPath, hashValue);

let contents: string;
if (file.contents.text !== undefined) {
Expand All @@ -266,7 +223,7 @@ export class FileMapper {
contents = Buffer.from(file.contents.binary, "base64").toString();
}

this.createReadOnlyFile(tempPath, contents);
Utilities.createReadOnlyFile(tempPath, contents);
this.fileRemapping.set(fileUriPath, Uri.file(tempPath));
}

Expand All @@ -293,9 +250,11 @@ export class FileMapper {
);

disposables.push(input.onDidAccept(() => {
resolved = true;
input.hide();
resolve(input.value);
if (input.validationMessage === undefined) {
resolved = true;
input.hide();
resolve(input.value);
}
}));

disposables.push(input.onDidHide(() => {
Expand Down Expand Up @@ -373,32 +332,6 @@ export class FileMapper {
});
}

/**
* Recursivly removes all of the contents in a directory, including subfolders
* @param path directory to remove all contents from
*/
private removeDirectoryContents(path: string): void {
const contents = Utilities.Fs.readdirSync(path);
for (const content of contents) {
const contentPath = Utilities.Path.join(path, content);
if (Utilities.Fs.lstatSync(contentPath).isDirectory()) {
this.removeDirectoryContents(contentPath);
Utilities.Fs.rmdirSync(contentPath);
} else {
Utilities.Fs.unlinkSync(contentPath);
}
}
}

/**
* Handles cleaning up the Sarif Viewer temp directory used for embeded code
*/
private removeSarifViewerTempDirectory(): void {
const path = Utilities.Path.join(Utilities.Os.tmpdir(), FileMapper.SarifViewerTempDir);
this.removeDirectoryContents(path);
Utilities.Fs.rmdirSync(path);
}

/**
* Determines the base path of the remapped Uri. Does so by
* starting at the end of both pathes character compares
Expand Down
24 changes: 17 additions & 7 deletions src/SVCodeActionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
// * *
// ********************************************************/
import {
CancellationToken, CodeActionContext, CodeActionProvider, Command, commands, Disposable, languages, ProviderResult,
Range, TextDocument,
CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, Command, commands, Disposable,
languages, ProviderResult, Range, TextDocument,
} from "vscode";
import { CodeFlowCodeLensProvider } from "./CodeFlowCodeLens";
import { CodeFlowDecorations } from "./CodeFlowDecorations";
import { SarifViewerDiagnostic } from "./common/Interfaces";
import { ExplorerController } from "./ExplorerController";
import { FileMapper } from "./FileMapper";
import { SVDiagnosticCollection } from "./SVDiagnosticCollection";
import { SVDiagnosticFactory } from "./SVDiagnosticFactory";

/**
Expand Down Expand Up @@ -56,7 +57,7 @@ export class SVCodeActionProvider implements CodeActionProvider {
document: TextDocument,
range: Range,
context: CodeActionContext,
token: CancellationToken): ProviderResult<Command[]> {
token: CancellationToken): ProviderResult<CodeAction[]> {
const index = context.diagnostics.findIndex((x) => x.code === SVDiagnosticFactory.Code);
if (index !== -1) {
const svDiagnostic = context.diagnostics[index] as SarifViewerDiagnostic;
Expand Down Expand Up @@ -92,18 +93,27 @@ export class SVCodeActionProvider implements CodeActionProvider {
* Creates the set of code actions for the passed in Sarif Viewer Diagnostic
* @param svDiagnostic the Sarif Viewer Diagnostic to create the code actions from
*/
private getCodeActions(svDiagnostic: SarifViewerDiagnostic): any[] {
private getCodeActions(svDiagnostic: SarifViewerDiagnostic): CodeAction[] {
const rawLocations = svDiagnostic.rawResult.locations;
const actions = [];
const actions: CodeAction[] = [];

if (!svDiagnostic.resultInfo.assignedLocation.mapped && rawLocations !== undefined) {
const physicalLocation = rawLocations[0].physicalLocation;
if (physicalLocation !== undefined && physicalLocation.fileLocation !== undefined) {
actions.push({
const cmd = {
arguments: [physicalLocation.fileLocation, svDiagnostic.resultInfo.runId],
command: FileMapper.MapCommand,
title: "Map To Source",
});
} as Command;

const action = {
command: cmd,
diagnostics: SVDiagnosticCollection.Instance.getAllUnmappedDiagnostics(),
kind: CodeActionKind.QuickFix,
title: "Map To Source",
} as CodeAction;

actions.push(action);
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/SVDiagnosticCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ export class SVDiagnosticCollection {
});
}

/**
* Gets a flat array of all the unmapped diagnostics
*/
public getAllUnmappedDiagnostics(): SarifViewerDiagnostic[] {
const unmapped: SarifViewerDiagnostic[] = [];
this.unmappedIssuesCollection.forEach((value) => {
unmapped.push(...value);
});

return unmapped;
}

/**
* Callback to handle whenever a mapping in the FileMapper changes
* Goes through the diagnostics and tries to remap their locations, if not able to it gets left in the unmapped
Expand Down
Loading

0 comments on commit 5e4dfed

Please sign in to comment.