Add the AST Viewer
This commit adds the AST Viewer for viewing the QL AST of a file in a database. The different components are as follows: 1. There is a new view `codeQLAstViewer`, which displays the AST 2. This view is backed by the `AstViewerDataProvider` and `AstViewer` classes in astView.ts 3. To generate an AST, we use contextual queries, similar to how Find references/declarations are implemented. In particular, in `definitions.ts` there is `TemplatePrintAstProvider` which provides an AST for a given source buffer. - Similar to the other queries, we first determine which database the buffer belongs to. - Based on that, we generate a synthetic qlpack and run the templatized `printAst.ql` query - We plug in the archive-relative path name of the source file. - After the query is run, we wrap the results in an `AstBuilder` instance. - When requested, the `AstBuilder` will generate the full AST of the file from the BQRS results. - The AST roots (all top-level elements, functions, variable declarations, etc, are roots) are passed to the `AstViewer` instance, which handles the display lifecycle and other VS Code-specific functions. There are a few unrelated pieces here, which can be pulled out to another PR if required: - The `codeQLQueryHistory` view now has a _welcome_ message to make it more obvious to users how to start. - `definitions.ts` is moved to the `contextual` subfolder. - `fileRangeFromURI` is extracted from `definitions.ts` to its own file so it can be reused. Also, note that this relies on https://github.com/github/codeql/pull/3931 for the C/C++ query to be available in the QL sources. Other languages will need similar queries.
This commit is contained in:
7
extensions/ql-vscode/media/dark/clear-all.svg
Normal file
7
extensions/ql-vscode/media/dark/clear-all.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#C5C5C5"/>
|
||||
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#C5C5C5"/>
|
||||
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#C5C5C5"/>
|
||||
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#C5C5C5"/>
|
||||
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 483 B |
7
extensions/ql-vscode/media/light/clear-all.svg
Normal file
7
extensions/ql-vscode/media/light/clear-all.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.0001 12.6L10.7001 13.3L12.3001 11.7L13.9001 13.3L14.7001 12.6L13.0001 11L14.7001 9.40005L13.9001 8.60005L12.3001 10.3L10.7001 8.60005L10.0001 9.40005L11.6001 11L10.0001 12.6Z" fill="#424242"/>
|
||||
<path d="M1.00006 4L15.0001 4L15.0001 3L1.00006 3L1.00006 4Z" fill="#424242"/>
|
||||
<path d="M1.00006 7L15.0001 7L15.0001 6L1.00006 6L1.00006 7Z" fill="#424242"/>
|
||||
<path d="M9.00006 9.5L9.00006 9L1.00006 9L1.00006 10L9.00006 10L9.00006 9.5Z" fill="#424242"/>
|
||||
<path d="M9.00006 13L9.00006 12.5L9.00006 12L1.00006 12L1.00006 13L9.00006 13Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 658 B |
@@ -25,6 +25,7 @@
|
||||
"onLanguage:ql",
|
||||
"onView:codeQLDatabases",
|
||||
"onView:codeQLQueryHistory",
|
||||
"onView:codeQLAstViewer",
|
||||
"onView:test-explorer",
|
||||
"onCommand:codeQL.checkForUpdatesToCLI",
|
||||
"onCommand:codeQLDatabases.chooseDatabaseFolder",
|
||||
@@ -32,6 +33,7 @@
|
||||
"onCommand:codeQLDatabases.chooseDatabaseInternet",
|
||||
"onCommand:codeQLDatabases.chooseDatabaseLgtm",
|
||||
"onCommand:codeQL.setCurrentDatabase",
|
||||
"onCommand:codeQL.viewAst",
|
||||
"onCommand:codeQL.chooseDatabaseFolder",
|
||||
"onCommand:codeQL.chooseDatabaseArchive",
|
||||
"onCommand:codeQL.chooseDatabaseInternet",
|
||||
@@ -218,6 +220,10 @@
|
||||
"command": "codeQL.setCurrentDatabase",
|
||||
"title": "CodeQL: Set Current Database"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.viewAst",
|
||||
"title": "CodeQL: View AST"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.upgradeCurrentDatabase",
|
||||
"title": "CodeQL: Upgrade Current Database"
|
||||
@@ -333,6 +339,18 @@
|
||||
{
|
||||
"command": "codeQLTests.acceptOutput",
|
||||
"title": "CodeQL: Accept Test Output"
|
||||
},
|
||||
{
|
||||
"command": "codeQLAstViewer.gotoCode",
|
||||
"title": "Go To Code"
|
||||
},
|
||||
{
|
||||
"command": "codeQLAstViewer.clear",
|
||||
"title": "Clear AST",
|
||||
"icon": {
|
||||
"light": "media/light/clear-all.svg",
|
||||
"dark": "media/dark/clear-all.svg"
|
||||
}
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
@@ -366,6 +384,11 @@
|
||||
"command": "codeQLDatabases.chooseDatabaseLgtm",
|
||||
"when": "view == codeQLDatabases",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "codeQLAstViewer.clear",
|
||||
"when": "view == codeQLAstViewer",
|
||||
"group": "navigation"
|
||||
}
|
||||
],
|
||||
"view/item/context": [
|
||||
@@ -446,6 +469,11 @@
|
||||
"group": "9_qlCommands",
|
||||
"when": "resourceScheme == codeql-zip-archive || explorerResourceIsFolder || resourceExtname == .zip"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.viewAst",
|
||||
"group": "9_qlCommands",
|
||||
"when": "resourceScheme == codeql-zip-archive"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.runQueries",
|
||||
"group": "9_qlCommands"
|
||||
@@ -468,6 +496,10 @@
|
||||
"command": "codeQL.setCurrentDatabase",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.viewAst",
|
||||
"when": "resourceScheme == codeql-zip-archive"
|
||||
},
|
||||
{
|
||||
"command": "codeQLDatabases.setCurrentDatabase",
|
||||
"when": "false"
|
||||
@@ -543,6 +575,14 @@
|
||||
{
|
||||
"command": "codeQLQueryHistory.compareWith",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codeQLAstViewer.gotoCode",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codeQLAstViewer.clear",
|
||||
"when": "false"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
@@ -574,9 +614,23 @@
|
||||
{
|
||||
"id": "codeQLQueryHistory",
|
||||
"name": "Query History"
|
||||
},
|
||||
{
|
||||
"id": "codeQLAstViewer",
|
||||
"name": "AST Viewer"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"viewsWelcome": [
|
||||
{
|
||||
"view": "codeQLAstViewer",
|
||||
"contents": "Run the 'CodeQL: View AST' command on an open source file from a Code QL database.\n[View AST](command:codeQL.viewAst)"
|
||||
},
|
||||
{
|
||||
"view": "codeQLQueryHistory",
|
||||
"contents": "Run the 'CodeQL: Run Query' command on QL query.\n[Run Query](command:codeQL.runQuery)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp",
|
||||
|
||||
102
extensions/ql-vscode/src/astViewer.ts
Normal file
102
extensions/ql-vscode/src/astViewer.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { DatabaseItem } from './databases';
|
||||
import { UrlValue, BqrsId } from './bqrs-cli-types';
|
||||
import fileRangeFromURI from './contextual/fileRangeFromURI';
|
||||
import { showLocation } from './interface-utils';
|
||||
|
||||
export interface AstItem {
|
||||
id: BqrsId;
|
||||
label?: string;
|
||||
location?: UrlValue;
|
||||
parent: AstItem | RootAstItem;
|
||||
children: AstItem[];
|
||||
order: number;
|
||||
}
|
||||
|
||||
export type RootAstItem = Omit<AstItem, 'parent'>;
|
||||
|
||||
class AstViewerDataProvider implements vscode.TreeDataProvider<AstItem | RootAstItem> {
|
||||
|
||||
public roots: RootAstItem[] = [];
|
||||
public db: DatabaseItem | undefined;
|
||||
|
||||
private _onDidChangeTreeData =
|
||||
new vscode.EventEmitter<AstItem | undefined>();
|
||||
readonly onDidChangeTreeData: vscode.Event<AstItem | undefined> =
|
||||
this._onDidChangeTreeData.event;
|
||||
|
||||
constructor() {
|
||||
vscode.commands.registerCommand('codeQLAstViewer.gotoCode',
|
||||
async (location: UrlValue, db: DatabaseItem) => {
|
||||
if (location) {
|
||||
await showLocation(fileRangeFromURI(location, db));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
getChildren(item?: AstItem): vscode.ProviderResult<(AstItem | RootAstItem)[]> {
|
||||
const children = item ? item.children : this.roots;
|
||||
return children.sort((c1, c2) => (c1.order - c2.order));
|
||||
}
|
||||
|
||||
getParent(item: AstItem): vscode.ProviderResult<AstItem> {
|
||||
return item.parent as AstItem;
|
||||
}
|
||||
|
||||
getTreeItem(item: AstItem): vscode.TreeItem {
|
||||
const line = typeof item.location === 'string'
|
||||
? item.location
|
||||
: item.location?.startLine;
|
||||
|
||||
const state = item.children.length
|
||||
? vscode.TreeItemCollapsibleState.Collapsed
|
||||
: vscode.TreeItemCollapsibleState.None;
|
||||
const treeItem = new vscode.TreeItem(item.label || '', state);
|
||||
treeItem.description = line ? `Line ${line}` : '';
|
||||
treeItem.id = String(item.id);
|
||||
treeItem.tooltip = `${treeItem.description} ${treeItem.label}`;
|
||||
treeItem.command = {
|
||||
command: 'codeQLAstViewer.gotoCode',
|
||||
title: 'Go To Code',
|
||||
tooltip: `Go To ${item.location}`,
|
||||
arguments: [item.location, this.db]
|
||||
};
|
||||
return treeItem;
|
||||
}
|
||||
}
|
||||
|
||||
export class AstViewer {
|
||||
private treeView: vscode.TreeView<AstItem | RootAstItem>;
|
||||
private treeDataProvider: AstViewerDataProvider;
|
||||
|
||||
constructor() {
|
||||
this.treeDataProvider = new AstViewerDataProvider();
|
||||
this.treeView = vscode.window.createTreeView('codeQLAstViewer', {
|
||||
treeDataProvider: this.treeDataProvider,
|
||||
showCollapseAll: true
|
||||
});
|
||||
|
||||
vscode.commands.registerCommand('codeQLAstViewer.clear', () => {
|
||||
this.clear();
|
||||
});
|
||||
}
|
||||
|
||||
updateRoots(roots: RootAstItem[], db: DatabaseItem, fileName: string) {
|
||||
this.treeDataProvider.roots = roots;
|
||||
this.treeDataProvider.db = db;
|
||||
this.treeDataProvider.refresh();
|
||||
this.treeView.message = `AST for ${fileName}`;
|
||||
this.treeView.reveal(roots[0], { focus: true });
|
||||
}
|
||||
|
||||
private clear() {
|
||||
this.treeDataProvider.roots = [];
|
||||
this.treeDataProvider.db = undefined;
|
||||
this.treeDataProvider.refresh();
|
||||
this.treeView.message = undefined;
|
||||
}
|
||||
}
|
||||
@@ -53,9 +53,12 @@ export interface BQRSInfo {
|
||||
'result-sets': ResultSetSchema[];
|
||||
}
|
||||
|
||||
export type BqrsId = number;
|
||||
|
||||
export interface EntityValue {
|
||||
url?: UrlValue;
|
||||
label?: string;
|
||||
id?: BqrsId;
|
||||
}
|
||||
|
||||
export interface LineColumnLocation {
|
||||
|
||||
@@ -499,7 +499,7 @@ export class CodeQLCliServer implements Disposable {
|
||||
*/
|
||||
async bqrsDecode(bqrsPath: string, resultSet: string, pageSize?: number, offset?: number): Promise<DecodedBqrsChunk> {
|
||||
const subcommandArgs = [
|
||||
'--entities=url,string',
|
||||
'--entities=id,url,string',
|
||||
'--result-set', resultSet,
|
||||
].concat(
|
||||
pageSize ? ['--rows', pageSize.toString()] : []
|
||||
|
||||
121
extensions/ql-vscode/src/contextual/astBuilder.ts
Normal file
121
extensions/ql-vscode/src/contextual/astBuilder.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { QueryWithResults } from '../run-queries';
|
||||
import { CodeQLCliServer } from '../cli';
|
||||
import { DecodedBqrsChunk, BqrsId, EntityValue } from '../bqrs-cli-types';
|
||||
import { DatabaseItem } from '../databases';
|
||||
import { AstItem, RootAstItem } from '../astViewer';
|
||||
|
||||
/**
|
||||
* A class that wraps a tree of QL results from a query that
|
||||
* has an @kind of graph
|
||||
*/
|
||||
// RENAME to ASTParser / ASTCreator
|
||||
export default class AstBuilder {
|
||||
|
||||
private roots: RootAstItem[] | undefined;
|
||||
private bqrsPath: string;
|
||||
constructor(
|
||||
queryResults: QueryWithResults,
|
||||
private cli: CodeQLCliServer,
|
||||
public db: DatabaseItem,
|
||||
public fileName: string
|
||||
) {
|
||||
this.bqrsPath = queryResults.query.resultsPaths.resultsPath;
|
||||
}
|
||||
|
||||
async getRoots(): Promise<RootAstItem[]> {
|
||||
if (!this.roots) {
|
||||
this.roots = await this.parseRoots();
|
||||
}
|
||||
return this.roots;
|
||||
}
|
||||
|
||||
private async parseRoots(): Promise<RootAstItem[]> {
|
||||
const [nodeTuples, edgeTuples, graphProperties] = await Promise.all([
|
||||
await this.cli.bqrsDecode(this.bqrsPath, 'nodes'),
|
||||
await this.cli.bqrsDecode(this.bqrsPath, 'edges'),
|
||||
await this.cli.bqrsDecode(this.bqrsPath, 'graphProperties'),
|
||||
]);
|
||||
|
||||
if (!this.isValidGraph(graphProperties)) {
|
||||
throw new Error('AST is invalid');
|
||||
}
|
||||
|
||||
const idToItem = new Map<BqrsId, AstItem | RootAstItem>();
|
||||
const parentToChildren = new Map<BqrsId, BqrsId[]>();
|
||||
const childToParent = new Map<BqrsId, BqrsId>();
|
||||
const astOrder = new Map<BqrsId, number>();
|
||||
const roots = [];
|
||||
|
||||
// Build up the parent-child relationships
|
||||
edgeTuples.tuples.forEach(tuple => {
|
||||
const from = tuple[0] as EntityValue;
|
||||
const to = tuple[1] as EntityValue;
|
||||
const toId = to.id!;
|
||||
const fromId = from.id!;
|
||||
|
||||
if (tuple[2] === 'semmle.order') {
|
||||
astOrder.set(toId, Number(tuple[3]));
|
||||
} else if (tuple[2] === 'semmle.label') {
|
||||
childToParent.set(toId, fromId);
|
||||
let children = parentToChildren.get(fromId);
|
||||
if (!children) {
|
||||
parentToChildren.set(fromId, children = []);
|
||||
}
|
||||
children.push(toId);
|
||||
}
|
||||
});
|
||||
|
||||
// populate parents and children
|
||||
nodeTuples.tuples.forEach(tuple => {
|
||||
const entity = tuple[0] as EntityValue;
|
||||
const id = entity.id!;
|
||||
|
||||
if (tuple[1] === 'semmle.order') {
|
||||
astOrder.set(id, Number(tuple[2]));
|
||||
|
||||
} else if (tuple[1] === 'semmle.label') {
|
||||
const item = {
|
||||
id,
|
||||
label: entity.label,
|
||||
location: entity.url,
|
||||
children: [] as AstItem[],
|
||||
order: Number.MAX_SAFE_INTEGER
|
||||
};
|
||||
|
||||
idToItem.set(id, item as RootAstItem);
|
||||
const parent = idToItem.get(childToParent.get(id) || -1);
|
||||
|
||||
if (parent) {
|
||||
const astItem = item as AstItem;
|
||||
astItem.parent = parent;
|
||||
parent.children.push(astItem);
|
||||
}
|
||||
const children = parentToChildren.get(id) || [];
|
||||
children.forEach(childId => {
|
||||
const child = idToItem.get(childId) as AstItem | undefined;
|
||||
if (child) {
|
||||
child.parent = item;
|
||||
item.children.push(child);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// find the roots and add the order
|
||||
for(const [, item] of idToItem) {
|
||||
item.order = astOrder.has(item.id)
|
||||
? astOrder.get(item.id)!
|
||||
: Number.MAX_SAFE_INTEGER;
|
||||
|
||||
if (!('parent' in item)) {
|
||||
roots.push(item);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
private isValidGraph(graphProperties: DecodedBqrsChunk) {
|
||||
const tuple = graphProperties?.tuples?.find(t => t[0] === 'semmle.graphKind');
|
||||
return tuple?.[1] === 'tree';
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,19 @@ import * as fs from 'fs-extra';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as tmp from 'tmp-promise';
|
||||
import * as vscode from 'vscode';
|
||||
import { decodeSourceArchiveUri, zipArchiveScheme } from './archive-filesystem-provider';
|
||||
import { ColumnKindCode, EntityValue, getResultSetSchema, LineColumnLocation, UrlValue } from './bqrs-cli-types';
|
||||
import { CodeQLCliServer } from './cli';
|
||||
import { DatabaseItem, DatabaseManager } from './databases';
|
||||
import * as helpers from './helpers';
|
||||
import { CachedOperation } from './helpers';
|
||||
import * as messages from './messages';
|
||||
import { QueryServerClient } from './queryserver-client';
|
||||
import { compileAndRunQueryAgainstDatabase, QueryWithResults } from './run-queries';
|
||||
import * as path from 'path';
|
||||
|
||||
import { decodeSourceArchiveUri, zipArchiveScheme } from '../archive-filesystem-provider';
|
||||
import { ColumnKindCode, EntityValue, getResultSetSchema } from '../bqrs-cli-types';
|
||||
import { CodeQLCliServer } from '../cli';
|
||||
import { DatabaseItem, DatabaseManager } from '../databases';
|
||||
import * as helpers from '../helpers';
|
||||
import { CachedOperation } from '../helpers';
|
||||
import * as messages from '../messages';
|
||||
import { QueryServerClient } from '../queryserver-client';
|
||||
import { compileAndRunQueryAgainstDatabase, QueryWithResults } from '../run-queries';
|
||||
import AstBuilder from './astBuilder';
|
||||
import fileRangeFromURI from './fileRangeFromURI';
|
||||
|
||||
/**
|
||||
* Run templated CodeQL queries to find definitions and references in
|
||||
@@ -25,19 +29,38 @@ const SELECT_QUERY_NAME = '#select';
|
||||
enum KeyType {
|
||||
DefinitionQuery = 'DefinitionQuery',
|
||||
ReferenceQuery = 'ReferenceQuery',
|
||||
PrintAstQuery = 'PrintAstQuery',
|
||||
}
|
||||
|
||||
function tagOfKeyType(keyType: KeyType): string {
|
||||
switch (keyType) {
|
||||
case KeyType.DefinitionQuery: return 'ide-contextual-queries/local-definitions';
|
||||
case KeyType.ReferenceQuery: return 'ide-contextual-queries/local-references';
|
||||
case KeyType.DefinitionQuery:
|
||||
return 'ide-contextual-queries/local-definitions';
|
||||
case KeyType.ReferenceQuery:
|
||||
return 'ide-contextual-queries/local-references';
|
||||
case KeyType.PrintAstQuery:
|
||||
return 'ide-contextual-queries/print-ast';
|
||||
}
|
||||
}
|
||||
|
||||
function nameOfKeyType(keyType: KeyType): string {
|
||||
switch (keyType) {
|
||||
case KeyType.DefinitionQuery: return 'definitions';
|
||||
case KeyType.ReferenceQuery: return 'references';
|
||||
case KeyType.DefinitionQuery:
|
||||
return 'definitions';
|
||||
case KeyType.ReferenceQuery:
|
||||
return 'references';
|
||||
case KeyType.PrintAstQuery:
|
||||
return 'print AST';
|
||||
}
|
||||
}
|
||||
|
||||
function kindOfKeyType(keyType: KeyType): string {
|
||||
switch (keyType) {
|
||||
case KeyType.DefinitionQuery:
|
||||
case KeyType.ReferenceQuery:
|
||||
return 'definitions';
|
||||
case KeyType.PrintAstQuery:
|
||||
return 'graph';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +68,7 @@ async function resolveQueries(cli: CodeQLCliServer, qlpack: string, keyType: Key
|
||||
const suiteFile = (await tmp.file({
|
||||
postfix: '.qls'
|
||||
})).path;
|
||||
const suiteYaml = { qlpack, include: { kind: 'definitions', 'tags contain': tagOfKeyType(keyType) } };
|
||||
const suiteYaml = { qlpack, include: { kind: kindOfKeyType(keyType), 'tags contain': tagOfKeyType(keyType) } };
|
||||
await fs.writeFile(suiteFile, yaml.safeDump(suiteYaml), 'utf8');
|
||||
|
||||
const queries = await cli.resolveQueriesInSuite(suiteFile, helpers.getOnDiskWorkspaceFolders());
|
||||
@@ -81,10 +104,6 @@ export class TemplateQueryDefinitionProvider implements vscode.DefinitionProvide
|
||||
this.cache = new CachedOperation<vscode.LocationLink[]>(this.getDefinitions.bind(this));
|
||||
}
|
||||
|
||||
async getDefinitions(uriString: string): Promise<vscode.LocationLink[]> {
|
||||
return getLinksForUriString(this.cli, this.qs, this.dbm, uriString, KeyType.DefinitionQuery, (src, _dest) => src === uriString);
|
||||
}
|
||||
|
||||
async provideDefinition(document: vscode.TextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.LocationLink[]> {
|
||||
const fileLinks = await this.cache.get(document.uri.toString());
|
||||
const locLinks: vscode.LocationLink[] = [];
|
||||
@@ -95,6 +114,17 @@ export class TemplateQueryDefinitionProvider implements vscode.DefinitionProvide
|
||||
}
|
||||
return locLinks;
|
||||
}
|
||||
|
||||
private async getDefinitions(uriString: string): Promise<vscode.LocationLink[]> {
|
||||
return getLinksForUriString(
|
||||
this.cli,
|
||||
this.qs,
|
||||
this.dbm,
|
||||
uriString,
|
||||
KeyType.DefinitionQuery,
|
||||
(src, _dest) => src === uriString
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class TemplateQueryReferenceProvider implements vscode.ReferenceProvider {
|
||||
@@ -108,11 +138,12 @@ export class TemplateQueryReferenceProvider implements vscode.ReferenceProvider
|
||||
this.cache = new CachedOperation<FullLocationLink[]>(this.getReferences.bind(this));
|
||||
}
|
||||
|
||||
async getReferences(uriString: string): Promise<FullLocationLink[]> {
|
||||
return getLinksForUriString(this.cli, this.qs, this.dbm, uriString, KeyType.ReferenceQuery, (_src, dest) => dest === uriString);
|
||||
}
|
||||
|
||||
async provideReferences(document: vscode.TextDocument, position: vscode.Position, _context: vscode.ReferenceContext, _token: vscode.CancellationToken): Promise<vscode.Location[]> {
|
||||
async provideReferences(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
_context: vscode.ReferenceContext,
|
||||
_token: vscode.CancellationToken
|
||||
): Promise<vscode.Location[]> {
|
||||
const fileLinks = await this.cache.get(document.uri.toString());
|
||||
const locLinks: vscode.Location[] = [];
|
||||
for (const link of fileLinks) {
|
||||
@@ -122,14 +153,99 @@ export class TemplateQueryReferenceProvider implements vscode.ReferenceProvider
|
||||
}
|
||||
return locLinks;
|
||||
}
|
||||
|
||||
private async getReferences(uriString: string): Promise<FullLocationLink[]> {
|
||||
return getLinksForUriString(
|
||||
this.cli,
|
||||
this.qs,
|
||||
this.dbm,
|
||||
uriString,
|
||||
KeyType.ReferenceQuery,
|
||||
(_src, dest) => dest === uriString
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface FileRange {
|
||||
file: vscode.Uri;
|
||||
range: vscode.Range;
|
||||
export class TemplatePrintAstProvider {
|
||||
private cache: CachedOperation<QueryWithResults | undefined>;
|
||||
|
||||
constructor(
|
||||
private cli: CodeQLCliServer,
|
||||
private qs: QueryServerClient,
|
||||
private dbm: DatabaseManager,
|
||||
) {
|
||||
this.cache = new CachedOperation<QueryWithResults | undefined>(this.getAst.bind(this));
|
||||
}
|
||||
|
||||
async provideAst(document?: vscode.TextDocument): Promise<AstBuilder | undefined> {
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
const queryResults = await this.cache.get(document.uri.toString());
|
||||
if (!queryResults) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new AstBuilder(
|
||||
queryResults, this.cli,
|
||||
this.dbm.findDatabaseItem(vscode.Uri.parse(queryResults.database.databaseUri!))!,
|
||||
path.basename(document.fileName)
|
||||
);
|
||||
}
|
||||
|
||||
private async getAst(uriString: string): Promise<QueryWithResults> {
|
||||
const uri = vscode.Uri.parse(uriString, true);
|
||||
if (uri.scheme !== zipArchiveScheme) {
|
||||
throw new Error('AST Viewing is only available for databases with zipped source archives.');
|
||||
}
|
||||
|
||||
const zippedArchive = decodeSourceArchiveUri(uri);
|
||||
const sourceArchiveUri = vscode.Uri.file(zippedArchive.sourceArchiveZipPath).with({ scheme: zipArchiveScheme });
|
||||
const db = this.dbm.findDatabaseItemBySourceArchive(sourceArchiveUri);
|
||||
|
||||
if (!db) {
|
||||
throw new Error('Can\'t infer database from the provided source.');
|
||||
}
|
||||
|
||||
const qlpack = await qlpackOfDatabase(this.cli, db);
|
||||
if (!qlpack) {
|
||||
throw new Error('Can\'t infer qlpack from database source archive');
|
||||
}
|
||||
const queries = await resolveQueries(this.cli, qlpack, KeyType.PrintAstQuery);
|
||||
if (queries.length > 1) {
|
||||
throw new Error('Found multiple Print AST queries. Can\'t continue');
|
||||
}
|
||||
if (queries.length === 0) {
|
||||
throw new Error('Did not find any Print AST queries. Can\'t continue');
|
||||
}
|
||||
|
||||
const query = queries[0];
|
||||
const templates: messages.TemplateDefinitions = {
|
||||
[TEMPLATE_NAME]: {
|
||||
values: {
|
||||
tuples: [[{
|
||||
stringValue: zippedArchive.pathWithinSourceArchive
|
||||
}]]
|
||||
}
|
||||
}
|
||||
};
|
||||
return await compileAndRunQueryAgainstDatabase(
|
||||
this.cli,
|
||||
this.qs,
|
||||
db,
|
||||
false,
|
||||
vscode.Uri.file(query),
|
||||
templates
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function getLinksFromResults(results: QueryWithResults, cli: CodeQLCliServer, db: DatabaseItem, filter: (srcFile: string, destFile: string) => boolean): Promise<FullLocationLink[]> {
|
||||
async function getLinksFromResults(
|
||||
results: QueryWithResults,
|
||||
cli: CodeQLCliServer,
|
||||
db: DatabaseItem,
|
||||
filter: (srcFile: string, destFile: string) => boolean
|
||||
): Promise<FullLocationLink[]> {
|
||||
const localLinks: FullLocationLink[] = [];
|
||||
const bqrsPath = results.query.resultsPaths.resultsPath;
|
||||
const info = await cli.bqrsInfo(bqrsPath);
|
||||
@@ -145,8 +261,8 @@ async function getLinksFromResults(results: QueryWithResults, cli: CodeQLCliServ
|
||||
const dest = tuple[1] as EntityValue;
|
||||
const srcFile = src.url && fileRangeFromURI(src.url, db);
|
||||
const destFile = dest.url && fileRangeFromURI(dest.url, db);
|
||||
if (srcFile && destFile && filter(srcFile.file.toString(), destFile.file.toString())) {
|
||||
localLinks.push({ targetRange: destFile.range, targetUri: destFile.file, originSelectionRange: srcFile.range, originUri: srcFile.file });
|
||||
if (srcFile && destFile && filter(srcFile.uri.toString(), destFile.uri.toString())) {
|
||||
localLinks.push({ targetRange: destFile.range, targetUri: destFile.uri, originSelectionRange: srcFile.range, originUri: srcFile.uri });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,26 +307,3 @@ async function getLinksForUriString(
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function fileRangeFromURI(uri: UrlValue, db: DatabaseItem): FileRange | undefined {
|
||||
if (typeof uri === 'string') {
|
||||
return undefined;
|
||||
} else if ('startOffset' in uri) {
|
||||
return undefined;
|
||||
} else {
|
||||
const loc = uri as LineColumnLocation;
|
||||
const range = new vscode.Range(Math.max(0, loc.startLine - 1),
|
||||
Math.max(0, loc.startColumn - 1),
|
||||
Math.max(0, loc.endLine - 1),
|
||||
Math.max(0, loc.endColumn));
|
||||
try {
|
||||
const parsed = vscode.Uri.parse(uri.uri, true);
|
||||
if (parsed.scheme === 'file') {
|
||||
return { file: db.resolveSourceFile(parsed.fsPath), range };
|
||||
}
|
||||
return undefined;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
extensions/ql-vscode/src/contextual/fileRangeFromURI.ts
Normal file
28
extensions/ql-vscode/src/contextual/fileRangeFromURI.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { UrlValue, LineColumnLocation } from '../bqrs-cli-types';
|
||||
import { DatabaseItem } from '../databases';
|
||||
|
||||
|
||||
export default function fileRangeFromURI(uri: UrlValue, db: DatabaseItem): vscode.Location | undefined {
|
||||
if (typeof uri === 'string') {
|
||||
return undefined;
|
||||
} else if ('startOffset' in uri) {
|
||||
return undefined;
|
||||
} else {
|
||||
const loc = uri as LineColumnLocation;
|
||||
const range = new vscode.Range(Math.max(0, (loc.startLine || 0) - 1),
|
||||
Math.max(0, (loc.startColumn || 0) - 1),
|
||||
Math.max(0, (loc.endLine || 0) - 1),
|
||||
Math.max(0, (loc.endColumn || 0)));
|
||||
try {
|
||||
const parsed = vscode.Uri.parse(uri.uri, true);
|
||||
if (parsed.scheme === 'file') {
|
||||
return new vscode.Location(db.resolveSourceFile(parsed.fsPath), range);
|
||||
}
|
||||
return undefined;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,32 @@
|
||||
import { commands, Disposable, ExtensionContext, extensions, languages, ProgressLocation, ProgressOptions, Uri, window as Window, env } from 'vscode';
|
||||
import {
|
||||
commands,
|
||||
Disposable,
|
||||
ExtensionContext,
|
||||
extensions,
|
||||
languages,
|
||||
ProgressLocation,
|
||||
ProgressOptions,
|
||||
Uri,
|
||||
window as Window,
|
||||
env,
|
||||
window
|
||||
} from 'vscode';
|
||||
import { LanguageClient } from 'vscode-languageclient';
|
||||
import * as path from 'path';
|
||||
import { testExplorerExtensionId, TestHub } from 'vscode-test-adapter-api';
|
||||
|
||||
import { AstViewer } from './astViewer';
|
||||
import * as archiveFilesystemProvider from './archive-filesystem-provider';
|
||||
import { CodeQLCliServer } from './cli';
|
||||
import { DistributionConfigListener, QueryHistoryConfigListener, QueryServerConfigListener } from './config';
|
||||
import * as languageSupport from './languageSupport';
|
||||
import { DatabaseManager } from './databases';
|
||||
import { DatabaseUI } from './databases-ui';
|
||||
import { TemplateQueryDefinitionProvider, TemplateQueryReferenceProvider } from './definitions';
|
||||
import {
|
||||
TemplateQueryDefinitionProvider,
|
||||
TemplateQueryReferenceProvider,
|
||||
TemplatePrintAstProvider
|
||||
} from './contextual/definitions';
|
||||
import {
|
||||
DEFAULT_DISTRIBUTION_VERSION_RANGE,
|
||||
DistributionKind,
|
||||
@@ -523,6 +541,15 @@ async function activateWithInstalledDistribution(
|
||||
new TemplateQueryReferenceProvider(cliServer, qs, dbm)
|
||||
);
|
||||
|
||||
const astViewer = new AstViewer();
|
||||
ctx.subscriptions.push(commands.registerCommand('codeQL.viewAst', async () => {
|
||||
const ast = await new TemplatePrintAstProvider(cliServer, qs, dbm)
|
||||
.provideAst(window.activeTextEditor?.document);
|
||||
if (ast) {
|
||||
astViewer.updateRoots(await ast.getRoots(), ast.db, ast.fileName);
|
||||
}
|
||||
}));
|
||||
|
||||
logger.log('Successfully finished extension initialization.');
|
||||
}
|
||||
|
||||
|
||||
@@ -149,13 +149,16 @@ export function getHtmlForWebview(
|
||||
</html>`;
|
||||
}
|
||||
|
||||
export async function showLocation(
|
||||
export async function showResolvableLocation(
|
||||
loc: ResolvableLocationValue,
|
||||
databaseItem: DatabaseItem
|
||||
): Promise<void> {
|
||||
const resolvedLocation = tryResolveLocation(loc, databaseItem);
|
||||
if (resolvedLocation) {
|
||||
const doc = await workspace.openTextDocument(resolvedLocation.uri);
|
||||
await showLocation(tryResolveLocation(loc, databaseItem));
|
||||
}
|
||||
|
||||
export async function showLocation(location?: Location) {
|
||||
if (location) {
|
||||
const doc = await workspace.openTextDocument(location.uri);
|
||||
const editorsWithDoc = Window.visibleTextEditors.filter(
|
||||
(e) => e.document === doc
|
||||
);
|
||||
@@ -163,7 +166,7 @@ export async function showLocation(
|
||||
editorsWithDoc.length > 0
|
||||
? editorsWithDoc[0]
|
||||
: await Window.showTextDocument(doc, ViewColumn.One);
|
||||
const range = resolvedLocation.range;
|
||||
const range = location.range;
|
||||
// When highlighting the range, vscode's occurrence-match and bracket-match highlighting will
|
||||
// trigger based on where we place the cursor/selection, and will compete for the user's attention.
|
||||
// For reference:
|
||||
@@ -188,6 +191,7 @@ const findRangeHighlightBackground = new ThemeColor(
|
||||
'editor.findRangeHighlightBackground'
|
||||
);
|
||||
|
||||
|
||||
export const shownLocationDecoration = Window.createTextEditorDecorationType({
|
||||
backgroundColor: findMatchBackground,
|
||||
});
|
||||
@@ -209,7 +213,7 @@ export async function jumpToLocation(
|
||||
);
|
||||
if (databaseItem !== undefined) {
|
||||
try {
|
||||
await showLocation(msg.loc, databaseItem);
|
||||
await showResolvableLocation(msg.loc, databaseItem);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
if (e.message.match(/File not found/)) {
|
||||
|
||||
@@ -105,11 +105,7 @@ class HistoryTreeDataProvider
|
||||
getChildren(
|
||||
element?: CompletedQuery
|
||||
): vscode.ProviderResult<CompletedQuery[]> {
|
||||
if (element == undefined) {
|
||||
return this.history;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
return element ? [] : this.history;
|
||||
}
|
||||
|
||||
getParent(_element: CompletedQuery): vscode.ProviderResult<CompletedQuery> {
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import * as fs from 'fs-extra';
|
||||
// import * as sinonChai from 'sinon-chai';
|
||||
import * as chai from 'chai';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import * as sinon from 'sinon';
|
||||
import AstBuilder from '../../../contextual/astBuilder';
|
||||
import { QueryWithResults } from '../../../run-queries';
|
||||
import { CodeQLCliServer } from '../../../cli';
|
||||
import { DatabaseItem } from '../../../databases';
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
const expect = chai.expect;
|
||||
|
||||
/**
|
||||
*
|
||||
This test uses an AST generated from this file (already BQRS-decoded in ../data/astBuilder.json):
|
||||
|
||||
#include <common.h>
|
||||
|
||||
int interrupt_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void enable_interrupts(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int disable_interrupts(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
describe('AstBuilder', () => {
|
||||
let mockCli: CodeQLCliServer;
|
||||
let overrides: Record<string, object | undefined>;
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
mockCli = {
|
||||
bqrsDecode: sinon.stub().callsFake((_: string, resultSet: 'nodes' | 'edges' | 'graphProperties') => {
|
||||
return mockDecode(resultSet);
|
||||
})
|
||||
} as unknown as CodeQLCliServer;
|
||||
overrides = {
|
||||
nodes: undefined,
|
||||
edges: undefined,
|
||||
graphProperties: undefined
|
||||
};
|
||||
});
|
||||
|
||||
it('should build the AST roots', async () => {
|
||||
const astBuilder = createAstBuilder();
|
||||
const roots = await astBuilder.getRoots();
|
||||
|
||||
expect(mockCli.bqrsDecode).to.have.been.calledWith('/a/b/c', 'nodes');
|
||||
expect(mockCli.bqrsDecode).to.have.been.calledWith('/a/b/c', 'edges');
|
||||
expect(mockCli.bqrsDecode).to.have.been.calledWith('/a/b/c', 'graphProperties');
|
||||
|
||||
expect(roots.map(
|
||||
r => ({ ...r, children: undefined })
|
||||
)).to.deep.eq(expectedRoots);
|
||||
});
|
||||
|
||||
it('should fail when graphProperties are not correct', async () => {
|
||||
overrides.graphProperties = {
|
||||
tuples: [
|
||||
[
|
||||
'semmle.graphKind',
|
||||
'hucairz'
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
const astBuilder = createAstBuilder();
|
||||
expect(astBuilder.getRoots()).to.be.rejectedWith('AST is invalid');
|
||||
});
|
||||
|
||||
function createAstBuilder() {
|
||||
return new AstBuilder({
|
||||
query: {
|
||||
resultsPaths: {
|
||||
resultsPath: '/a/b/c'
|
||||
}
|
||||
}
|
||||
} as QueryWithResults, mockCli, {} as DatabaseItem, '');
|
||||
}
|
||||
|
||||
function mockDecode(resultSet: 'nodes' | 'edges' | 'graphProperties') {
|
||||
if (overrides[resultSet]) {
|
||||
return overrides[resultSet];
|
||||
}
|
||||
|
||||
const mapper = {
|
||||
nodes: 0,
|
||||
edges: 1,
|
||||
graphProperties: 2
|
||||
};
|
||||
const index = mapper[resultSet] as number;
|
||||
if (index >= 0 && index <= 2) {
|
||||
return JSON.parse(fs.readFileSync(`${__dirname}/../data/astBuilder.json`, 'utf8'))[index];
|
||||
} else {
|
||||
throw new Error(`Invalid resultSet: ${resultSet}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const expectedRoots = [
|
||||
{
|
||||
id: 26362,
|
||||
label: '[TopLevelFunction] int disable_interrupts()',
|
||||
location: {
|
||||
uri: 'file:/opt/src/arch/sandbox/lib/interrupts.c',
|
||||
startLine: 19,
|
||||
startColumn: 5,
|
||||
endLine: 19,
|
||||
endColumn: 22
|
||||
},
|
||||
order: 3,
|
||||
children: undefined
|
||||
},
|
||||
{
|
||||
id: 26363,
|
||||
label: '[TopLevelFunction] void enable_interrupts()',
|
||||
location: {
|
||||
uri: 'file:/opt/src/arch/sandbox/lib/interrupts.c',
|
||||
startLine: 15,
|
||||
startColumn: 6,
|
||||
endLine: 15,
|
||||
endColumn: 22
|
||||
},
|
||||
order: 2,
|
||||
children: undefined
|
||||
},
|
||||
{
|
||||
id: 26364,
|
||||
label: '[TopLevelFunction] int interrupt_init()',
|
||||
location: {
|
||||
uri: 'file:/opt/src/arch/sandbox/lib/interrupts.c',
|
||||
startLine: 10,
|
||||
startColumn: 5,
|
||||
endLine: 10,
|
||||
endColumn: 18
|
||||
},
|
||||
order: 1,
|
||||
children: undefined
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'vscode-test';
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { Uri, Range } from 'vscode';
|
||||
|
||||
import fileRangeFromURI from '../../../contextual/fileRangeFromURI';
|
||||
import { DatabaseItem } from '../../../databases';
|
||||
import { WholeFileLocation, LineColumnLocation } from '../../../bqrs-cli-types';
|
||||
|
||||
describe('fileRangeFromURI', () => {
|
||||
it('should return undefined when value is a string', () => {
|
||||
expect(fileRangeFromURI('hucairz', createMockDatabaseItem())).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should return a range for a WholeFileLocation', () => {
|
||||
expect(fileRangeFromURI({
|
||||
uri: 'file:///hucairz',
|
||||
} as WholeFileLocation, createMockDatabaseItem())).to.deep.eq({
|
||||
uri: Uri.parse('file:///hucairz', true),
|
||||
range: new Range(0, 0, 0, 0)
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a range for a LineColumnLocation', () => {
|
||||
expect(fileRangeFromURI({
|
||||
uri: 'file:///hucairz',
|
||||
startLine: 1,
|
||||
startColumn: 2,
|
||||
endLine: 3,
|
||||
endColumn: 4,
|
||||
} as LineColumnLocation, createMockDatabaseItem())).to.deep.eq({
|
||||
uri: Uri.parse('file:///hucairz', true),
|
||||
range: new Range(0, 1, 2, 4)
|
||||
});
|
||||
});
|
||||
|
||||
function createMockDatabaseItem(): DatabaseItem {
|
||||
return {
|
||||
resolveSourceFile: (uri: string) => Uri.parse('file://' + uri, true)
|
||||
} as DatabaseItem;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,977 @@
|
||||
[
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"name": "node",
|
||||
"kind": "Entity"
|
||||
},
|
||||
{
|
||||
"name": "key",
|
||||
"kind": "String"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"kind": "String"
|
||||
}
|
||||
],
|
||||
"tuples": [
|
||||
[
|
||||
{
|
||||
"id": 26359,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
""
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26360,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
""
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26361,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
""
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[TopLevelFunction] int disable_interrupts()"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"3"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[TopLevelFunction] void enable_interrupts()"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"2"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[TopLevelFunction] int interrupt_init()"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"1"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"Type",
|
||||
"[IntType] int"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[Literal] 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"Value",
|
||||
"[Literal] 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"ValueCategory",
|
||||
"prvalue"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26366,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 2,
|
||||
"endLine": 21,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[ReturnStmt] return ..."
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26367,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 20,
|
||||
"startColumn": 1,
|
||||
"endLine": 22,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[Block] { ... }"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26368,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 17,
|
||||
"startColumn": 2,
|
||||
"endLine": 17,
|
||||
"endColumn": 8
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[ReturnStmt] return ..."
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26369,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 16,
|
||||
"startColumn": 1,
|
||||
"endLine": 18,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[Block] { ... }"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"Type",
|
||||
"[IntType] int"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[Literal] 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"Value",
|
||||
"[Literal] 0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"ValueCategory",
|
||||
"prvalue"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26371,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 2,
|
||||
"endLine": 12,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[ReturnStmt] return ..."
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26372,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 11,
|
||||
"startColumn": 1,
|
||||
"endLine": 13,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"[Block] { ... }"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"name": "source",
|
||||
"kind": "Entity"
|
||||
},
|
||||
{
|
||||
"name": "target",
|
||||
"kind": "Entity"
|
||||
},
|
||||
{
|
||||
"name": "key",
|
||||
"kind": "String"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"kind": "String"
|
||||
}
|
||||
],
|
||||
"tuples": [
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26359,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"params"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26359,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26367,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 20,
|
||||
"startColumn": 1,
|
||||
"endLine": 22,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"body"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26362,
|
||||
"label": "[TopLevelFunction] int disable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 19,
|
||||
"startColumn": 5,
|
||||
"endLine": 19,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26367,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 20,
|
||||
"startColumn": 1,
|
||||
"endLine": 22,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"2"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26360,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"params"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26360,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26369,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 16,
|
||||
"startColumn": 1,
|
||||
"endLine": 18,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"body"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26363,
|
||||
"label": "[TopLevelFunction] void enable_interrupts()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 15,
|
||||
"startColumn": 6,
|
||||
"endLine": 15,
|
||||
"endColumn": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26369,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 16,
|
||||
"startColumn": 1,
|
||||
"endLine": 18,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"2"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26361,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"params"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26361,
|
||||
"label": "",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26372,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 11,
|
||||
"startColumn": 1,
|
||||
"endLine": 13,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"body"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26364,
|
||||
"label": "[TopLevelFunction] int interrupt_init()",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 10,
|
||||
"startColumn": 5,
|
||||
"endLine": 10,
|
||||
"endColumn": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26372,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 11,
|
||||
"startColumn": 1,
|
||||
"endLine": 13,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"2"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26366,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 2,
|
||||
"endLine": 21,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26366,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 2,
|
||||
"endLine": 21,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26365,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 9,
|
||||
"endLine": 21,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26367,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 20,
|
||||
"startColumn": 1,
|
||||
"endLine": 22,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26366,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 2,
|
||||
"endLine": 21,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26367,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 20,
|
||||
"startColumn": 1,
|
||||
"endLine": 22,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26366,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 21,
|
||||
"startColumn": 2,
|
||||
"endLine": 21,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26369,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 16,
|
||||
"startColumn": 1,
|
||||
"endLine": 18,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26368,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 17,
|
||||
"startColumn": 2,
|
||||
"endLine": 17,
|
||||
"endColumn": 8
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26369,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 16,
|
||||
"startColumn": 1,
|
||||
"endLine": 18,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26368,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 17,
|
||||
"startColumn": 2,
|
||||
"endLine": 17,
|
||||
"endColumn": 8
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26371,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 2,
|
||||
"endLine": 12,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26371,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 2,
|
||||
"endLine": 12,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26370,
|
||||
"label": "[Literal] 0",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 9,
|
||||
"endLine": 12,
|
||||
"endColumn": 9
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26372,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 11,
|
||||
"startColumn": 1,
|
||||
"endLine": 13,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26371,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 2,
|
||||
"endLine": 12,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.label",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": 26372,
|
||||
"label": "[Block] { ... }",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 11,
|
||||
"startColumn": 1,
|
||||
"endLine": 13,
|
||||
"endColumn": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 26371,
|
||||
"label": "[ReturnStmt] return ...",
|
||||
"url": {
|
||||
"uri": "file:/opt/src/arch/sandbox/lib/interrupts.c",
|
||||
"startLine": 12,
|
||||
"startColumn": 2,
|
||||
"endLine": 12,
|
||||
"endColumn": 10
|
||||
}
|
||||
},
|
||||
"semmle.order",
|
||||
"0"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"name": "key",
|
||||
"kind": "String"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"kind": "String"
|
||||
}
|
||||
],
|
||||
"tuples": [
|
||||
[
|
||||
"semmle.graphKind",
|
||||
"tree"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2,7 +2,6 @@ import 'vscode-test';
|
||||
import 'mocha';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import * as sinon from 'sinon';
|
||||
// import * as sinonChai from 'sinon-chai';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as tmp from 'tmp';
|
||||
|
||||
Reference in New Issue
Block a user