Use a single SARIF-compatible query instead of two separate queries
This commit is contained in:
@@ -37,7 +37,7 @@ export async function getAutoModelUsages({
|
||||
|
||||
const cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
const queryResult = await runQuery("usagesQuery", {
|
||||
const queryResult = await runQuery({
|
||||
cliServer,
|
||||
queryRunner,
|
||||
queryStorageDir,
|
||||
|
||||
@@ -7,9 +7,9 @@ export function decodeBqrsToExternalApiUsages(
|
||||
const methodsByApiName = new Map<string, ExternalApiUsage>();
|
||||
|
||||
chunk?.tuples.forEach((tuple) => {
|
||||
const signature = tuple[0] as string;
|
||||
const supported = tuple[1] as boolean;
|
||||
const usage = tuple[2] as Call;
|
||||
const usage = tuple[0] as Call;
|
||||
const signature = tuple[1] as string;
|
||||
const supported = (tuple[2] as string) === "true";
|
||||
|
||||
const [packageWithType, methodDeclaration] = signature.split("#");
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
|
||||
const cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
try {
|
||||
const queryResult = await runQuery("mainQuery", {
|
||||
const queryResult = await runQuery({
|
||||
cliServer: this.cliServer,
|
||||
queryRunner: this.queryRunner,
|
||||
databaseItem: this.databaseItem,
|
||||
|
||||
@@ -16,7 +16,6 @@ import { QueryResultType } from "../pure/new-messages";
|
||||
import { join } from "path";
|
||||
import { redactableError } from "../pure/errors";
|
||||
import { QueryLanguage } from "../common/query-language";
|
||||
import { Query } from "./queries/query";
|
||||
|
||||
export type RunQueryOptions = {
|
||||
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">;
|
||||
@@ -28,17 +27,14 @@ export type RunQueryOptions = {
|
||||
token: CancellationToken;
|
||||
};
|
||||
|
||||
export async function runQuery(
|
||||
queryName: keyof Omit<Query, "dependencies">,
|
||||
{
|
||||
cliServer,
|
||||
queryRunner,
|
||||
databaseItem,
|
||||
queryStorageDir,
|
||||
progress,
|
||||
token,
|
||||
}: RunQueryOptions,
|
||||
): Promise<CoreCompletedQuery | undefined> {
|
||||
export async function runQuery({
|
||||
cliServer,
|
||||
queryRunner,
|
||||
databaseItem,
|
||||
queryStorageDir,
|
||||
progress,
|
||||
token,
|
||||
}: RunQueryOptions): Promise<CoreCompletedQuery | undefined> {
|
||||
// The below code is temporary to allow for rapid prototyping of the queries. Once the queries are stabilized, we will
|
||||
// move these queries into the `github/codeql` repository and use them like any other contextual (e.g. AST) queries.
|
||||
// This is intentionally not pretty code, as it will be removed soon.
|
||||
@@ -55,7 +51,7 @@ export async function runQuery(
|
||||
|
||||
const queryDir = (await dir({ unsafeCleanup: true })).path;
|
||||
const queryFile = join(queryDir, "FetchExternalApis.ql");
|
||||
await writeFile(queryFile, query[queryName], "utf8");
|
||||
await writeFile(queryFile, query.mainQuery, "utf8");
|
||||
|
||||
if (query.dependencies) {
|
||||
for (const [filename, contents] of Object.entries(query.dependencies)) {
|
||||
|
||||
@@ -2,52 +2,31 @@ import { Query } from "./query";
|
||||
|
||||
export const fetchExternalApisQuery: Query = {
|
||||
mainQuery: `/**
|
||||
* @name Usage of APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase.
|
||||
* @tags telemetry
|
||||
* @id cs/telemetry/fetch-external-apis
|
||||
*/
|
||||
* @name Usage of APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase.
|
||||
* @tags telemetry
|
||||
* @kind problem
|
||||
* @id cs/telemetry/fetch-external-apis
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import ExternalApi
|
||||
|
||||
private Call aUsage(ExternalApi api) {
|
||||
result.getTarget().getUnboundDeclaration() = api
|
||||
}
|
||||
private Call aUsage(ExternalApi api) { result.getTarget().getUnboundDeclaration() = api }
|
||||
|
||||
private boolean isSupported(ExternalApi api) {
|
||||
api.isSupported() and result = true
|
||||
or
|
||||
not api.isSupported() and
|
||||
result = false
|
||||
api.isSupported() and result = true
|
||||
or
|
||||
not api.isSupported() and
|
||||
result = false
|
||||
}
|
||||
|
||||
from ExternalApi api, string apiName, boolean supported, Call usage
|
||||
where
|
||||
apiName = api.getApiName() and
|
||||
supported = isSupported(api) and
|
||||
usage = aUsage(api)
|
||||
select apiName, supported, usage
|
||||
`,
|
||||
usagesQuery: `/**
|
||||
* @name Usage of APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase.
|
||||
* @kind problem
|
||||
* @id cs/telemetry/fetch-external-api-usages
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import ExternalApi
|
||||
|
||||
private Call aUsage(ExternalApi api) {
|
||||
result.getTarget().getUnboundDeclaration() = api
|
||||
}
|
||||
|
||||
from ExternalApi api, string apiName, Call usage
|
||||
where
|
||||
apiName = api.getApiName() and
|
||||
usage = aUsage(api)
|
||||
select usage, apiName
|
||||
apiName = api.getApiName() and
|
||||
supported = isSupported(api) and
|
||||
usage = aUsage(api)
|
||||
select usage, apiName, supported.toString(), "supported"
|
||||
`,
|
||||
dependencies: {
|
||||
"ExternalApi.qll": `/** Provides classes and predicates related to handling APIs from external libraries. */
|
||||
|
||||
@@ -5,6 +5,7 @@ export const fetchExternalApisQuery: Query = {
|
||||
* @name Usage of APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase. Excludes test and generated code.
|
||||
* @tags telemetry
|
||||
* @kind problem
|
||||
* @id java/telemetry/fetch-external-apis
|
||||
*/
|
||||
|
||||
@@ -27,28 +28,7 @@ where
|
||||
apiName = api.getApiName() and
|
||||
supported = isSupported(api) and
|
||||
usage = aUsage(api)
|
||||
select apiName, supported, usage
|
||||
`,
|
||||
usagesQuery: `/**
|
||||
* @name Usage of APIs coming from external libraries
|
||||
* @description A list of 3rd party APIs used in the codebase. Excludes test and generated code.
|
||||
* @kind problem
|
||||
* @id java/telemetry/fetch-external-api-usages
|
||||
*/
|
||||
|
||||
import java
|
||||
import ExternalApi
|
||||
|
||||
private Call aUsage(ExternalApi api) {
|
||||
result.getCallee().getSourceDeclaration() = api and
|
||||
not result.getFile() instanceof GeneratedFile
|
||||
}
|
||||
|
||||
from ExternalApi api, string apiName, Call usage
|
||||
where
|
||||
apiName = api.getApiName() and
|
||||
usage = aUsage(api)
|
||||
select usage, apiName
|
||||
select usage, apiName, supported.toString(), "supported"
|
||||
`,
|
||||
dependencies: {
|
||||
"ExternalApi.qll": `/** Provides classes and predicates related to handling APIs from external libraries. */
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
export type Query = {
|
||||
/**
|
||||
* The main query.
|
||||
*
|
||||
* It should select all usages of external APIs, and return the following result pattern:
|
||||
* - usage: the usage of the external API. This is an entity.
|
||||
* - apiName: the name of the external API. This is a string.
|
||||
* - supported: whether the external API is supported by the extension. This should be a string representation of a boolean to satify the result pattern for a problem query.
|
||||
* - "supported": a string literal. This is required to make the query a valid problem query.
|
||||
*/
|
||||
mainQuery: string;
|
||||
usagesQuery: string;
|
||||
dependencies?: {
|
||||
[filename: string]: string;
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ export type BqrsKind =
|
||||
| "Entity";
|
||||
|
||||
interface BqrsColumn {
|
||||
name: string;
|
||||
name?: string;
|
||||
kind: BqrsKind;
|
||||
}
|
||||
export interface DecodedBqrsChunk {
|
||||
|
||||
@@ -4,126 +4,13 @@ import { DecodedBqrsChunk } from "../../../src/pure/bqrs-cli-types";
|
||||
describe("decodeBqrsToExternalApiUsages", () => {
|
||||
const chunk: DecodedBqrsChunk = {
|
||||
columns: [
|
||||
{ name: "apiName", kind: "String" },
|
||||
{ name: "supported", kind: "Boolean" },
|
||||
{ name: "usage", kind: "Entity" },
|
||||
{ name: "apiName", kind: "String" },
|
||||
{ kind: "String" },
|
||||
{ kind: "String" },
|
||||
],
|
||||
tuples: [
|
||||
[
|
||||
"java.io.PrintStream#println(String)",
|
||||
true,
|
||||
{
|
||||
label: "println(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 29,
|
||||
startColumn: 9,
|
||||
endLine: 29,
|
||||
endColumn: 49,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.springframework.boot.SpringApplication#run(Class,String[])",
|
||||
false,
|
||||
{
|
||||
label: "run(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/Sql2oExampleApplication.java",
|
||||
startLine: 9,
|
||||
startColumn: 9,
|
||||
endLine: 9,
|
||||
endColumn: 66,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Connection#createQuery(String)",
|
||||
true,
|
||||
{
|
||||
label: "createQuery(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 56,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Connection#createQuery(String)",
|
||||
true,
|
||||
{
|
||||
label: "createQuery(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 26,
|
||||
startColumn: 13,
|
||||
endLine: 26,
|
||||
endColumn: 39,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Query#executeScalar(Class)",
|
||||
true,
|
||||
{
|
||||
label: "executeScalar(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 85,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Query#executeScalar(Class)",
|
||||
true,
|
||||
{
|
||||
label: "executeScalar(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 26,
|
||||
startColumn: 13,
|
||||
endLine: 26,
|
||||
endColumn: 68,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Sql2o#open()",
|
||||
true,
|
||||
{
|
||||
label: "open(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 14,
|
||||
startColumn: 24,
|
||||
endLine: 14,
|
||||
endColumn: 35,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Sql2o#open()",
|
||||
true,
|
||||
{
|
||||
label: "open(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 25,
|
||||
startColumn: 24,
|
||||
endLine: 25,
|
||||
endColumn: 35,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
"org.sql2o.Sql2o#Sql2o(String,String,String)",
|
||||
true,
|
||||
{
|
||||
label: "new Sql2o(...)",
|
||||
url: {
|
||||
@@ -134,10 +21,56 @@ describe("decodeBqrsToExternalApiUsages", () => {
|
||||
endColumn: 88,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Sql2o#Sql2o(String,String,String)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "open(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 14,
|
||||
startColumn: 24,
|
||||
endLine: 14,
|
||||
endColumn: 35,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Sql2o#open()",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "executeScalar(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 85,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Query#executeScalar(Class)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "createQuery(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 15,
|
||||
startColumn: 13,
|
||||
endLine: 15,
|
||||
endColumn: 56,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Connection#createQuery(String)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
"org.sql2o.Sql2o#Sql2o(String)",
|
||||
true,
|
||||
{
|
||||
label: "new Sql2o(...)",
|
||||
url: {
|
||||
@@ -148,6 +81,84 @@ describe("decodeBqrsToExternalApiUsages", () => {
|
||||
endColumn: 36,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Sql2o#Sql2o(String)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "open(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 25,
|
||||
startColumn: 24,
|
||||
endLine: 25,
|
||||
endColumn: 35,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Sql2o#open()",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "executeScalar(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 26,
|
||||
startColumn: 13,
|
||||
endLine: 26,
|
||||
endColumn: 68,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Query#executeScalar(Class)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "createQuery(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 26,
|
||||
startColumn: 13,
|
||||
endLine: 26,
|
||||
endColumn: 39,
|
||||
},
|
||||
},
|
||||
"org.sql2o.Connection#createQuery(String)",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "println(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/HelloController.java",
|
||||
startLine: 29,
|
||||
startColumn: 9,
|
||||
endLine: 29,
|
||||
endColumn: 49,
|
||||
},
|
||||
},
|
||||
"java.io.PrintStream#println(String)",
|
||||
"true",
|
||||
"supported",
|
||||
],
|
||||
[
|
||||
{
|
||||
label: "run(...)",
|
||||
url: {
|
||||
uri: "file:/home/runner/work/sql2o-example/sql2o-example/src/main/java/org/example/Sql2oExampleApplication.java",
|
||||
startLine: 9,
|
||||
startColumn: 9,
|
||||
endLine: 9,
|
||||
endColumn: 66,
|
||||
},
|
||||
},
|
||||
"org.springframework.boot.SpringApplication#run(Class,String[])",
|
||||
"false",
|
||||
"supported",
|
||||
],
|
||||
],
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import { QueryResultType } from "../../../../src/pure/new-messages";
|
||||
import { readdir, readFile } from "fs-extra";
|
||||
import { load } from "js-yaml";
|
||||
import { dirname, join } from "path";
|
||||
import { fetchExternalApiQueries } from "../../../../src/data-extensions-editor/queries/index";
|
||||
import { fetchExternalApiQueries } from "../../../../src/data-extensions-editor/queries";
|
||||
import * as helpers from "../../../../src/helpers";
|
||||
import { RedactableError } from "../../../../src/pure/errors";
|
||||
|
||||
@@ -66,7 +66,7 @@ describe("runQuery", () => {
|
||||
onCancellationRequested: jest.fn(),
|
||||
},
|
||||
};
|
||||
const result = await runQuery("mainQuery", options);
|
||||
const result = await runQuery(options);
|
||||
|
||||
expect(result?.resultType).toEqual(QueryResultType.SUCCESS);
|
||||
|
||||
@@ -161,18 +161,20 @@ describe("readQueryResults", () => {
|
||||
name: "#select",
|
||||
rows: 10,
|
||||
columns: [
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ name: "supported", kind: "b" },
|
||||
{ name: "usage", kind: "e" },
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ kind: "s" },
|
||||
{ kind: "s" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "#select2",
|
||||
rows: 10,
|
||||
columns: [
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ name: "supported", kind: "b" },
|
||||
{ name: "usage", kind: "e" },
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ kind: "s" },
|
||||
{ kind: "s" },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -191,9 +193,10 @@ describe("readQueryResults", () => {
|
||||
name: "#select",
|
||||
rows: 10,
|
||||
columns: [
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ name: "supported", kind: "b" },
|
||||
{ name: "usage", kind: "e" },
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ kind: "s" },
|
||||
{ kind: "s" },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -201,9 +204,10 @@ describe("readQueryResults", () => {
|
||||
});
|
||||
const decodedResultSet = {
|
||||
columns: [
|
||||
{ name: "apiName", kind: "String" },
|
||||
{ name: "supported", kind: "Boolean" },
|
||||
{ name: "usage", kind: "Entity" },
|
||||
{ name: "usage", kind: "e" },
|
||||
{ name: "apiName", kind: "s" },
|
||||
{ kind: "s" },
|
||||
{ kind: "s" },
|
||||
],
|
||||
tuples: [
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user