Use MaD definition when decoding BQRS
This will use the MaD's definition of a method signature when decoding BQRS files. This will allow us to change the method signature definition for dynamic languages.
This commit is contained in:
@@ -4,13 +4,18 @@ import { ModeledMethodType } from "./modeled-method";
|
||||
import { parseLibraryFilename } from "./library";
|
||||
import { Mode } from "./shared/mode";
|
||||
import { ApplicationModeTuple, FrameworkModeTuple } from "./queries/query";
|
||||
import { QueryLanguage } from "../common/query-language";
|
||||
import { getModelsAsDataLanguage } from "./languages";
|
||||
|
||||
export function decodeBqrsToMethods(
|
||||
chunk: DecodedBqrsChunk,
|
||||
mode: Mode,
|
||||
language: QueryLanguage,
|
||||
): Method[] {
|
||||
const methodsByApiName = new Map<string, Method>();
|
||||
|
||||
const definition = getModelsAsDataLanguage(language);
|
||||
|
||||
chunk?.tuples.forEach((tuple) => {
|
||||
let usage: Call;
|
||||
let packageName: string;
|
||||
@@ -51,7 +56,12 @@ export function decodeBqrsToMethods(
|
||||
classification = CallClassification.Unknown;
|
||||
}
|
||||
|
||||
const signature = `${packageName}.${typeName}#${methodName}${methodParameters}`;
|
||||
const signature = definition.createMethodSignature({
|
||||
packageName,
|
||||
typeName,
|
||||
methodName,
|
||||
methodParameters,
|
||||
});
|
||||
|
||||
// For Java, we'll always get back a .jar file, and the library version may be bad because not all library authors
|
||||
// properly specify the version. Therefore, we'll always try to parse the name and version from the library filename
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MethodDefinition } from "../method";
|
||||
import { ModeledMethod, ModeledMethodType } from "../modeled-method";
|
||||
import { DataTuple } from "../model-extension-file";
|
||||
|
||||
@@ -19,5 +20,6 @@ export type ModelsAsDataLanguagePredicates = Record<
|
||||
>;
|
||||
|
||||
export type ModelsAsDataLanguage = {
|
||||
createMethodSignature: (method: MethodDefinition) => string;
|
||||
predicates: ModelsAsDataLanguagePredicates;
|
||||
};
|
||||
|
||||
@@ -8,6 +8,12 @@ function readRowToMethod(row: DataTuple[]): string {
|
||||
}
|
||||
|
||||
export const staticLanguage: ModelsAsDataLanguage = {
|
||||
createMethodSignature: ({
|
||||
packageName,
|
||||
typeName,
|
||||
methodName,
|
||||
methodParameters,
|
||||
}) => `${packageName}.${typeName}#${methodName}${methodParameters}`,
|
||||
predicates: {
|
||||
source: {
|
||||
extensiblePredicate: sharedExtensiblePredicates.source,
|
||||
|
||||
@@ -17,19 +17,7 @@ export type Usage = Call & {
|
||||
readonly classification: CallClassification;
|
||||
};
|
||||
|
||||
export interface MethodSignature {
|
||||
/**
|
||||
* Contains the version of the library if it can be determined by CodeQL, e.g. `4.2.2.2`
|
||||
*/
|
||||
readonly libraryVersion?: string;
|
||||
/**
|
||||
* A unique signature that can be used to identify this external API usage.
|
||||
*
|
||||
* The signature contains the package name, type name, method name, and method parameters
|
||||
* in the form "packageName.typeName#methodName(methodParameters)".
|
||||
* e.g. `org.sql2o.Connection#createQuery(String)`
|
||||
*/
|
||||
readonly signature: string;
|
||||
export interface MethodDefinition {
|
||||
/**
|
||||
* The package name in Java, or the namespace in C#, e.g. `org.sql2o` or `System.Net.Http.Headers`.
|
||||
*
|
||||
@@ -44,6 +32,21 @@ export interface MethodSignature {
|
||||
readonly methodParameters: string;
|
||||
}
|
||||
|
||||
export interface MethodSignature extends MethodDefinition {
|
||||
/**
|
||||
* Contains the version of the library if it can be determined by CodeQL, e.g. `4.2.2.2`
|
||||
*/
|
||||
readonly libraryVersion?: string;
|
||||
/**
|
||||
* A unique signature that can be used to identify this external API usage.
|
||||
*
|
||||
* The signature contains the package name, type name, method name, and method parameters
|
||||
* in the form "packageName.typeName#methodName(methodParameters)".
|
||||
* e.g. `org.sql2o.Connection#createQuery(String)`
|
||||
*/
|
||||
readonly signature: string;
|
||||
}
|
||||
|
||||
export interface Method extends MethodSignature {
|
||||
/**
|
||||
* Contains the name of the library containing the method declaration, e.g. `sql2o-1.6.0.jar` or `System.Runtime.dll`
|
||||
|
||||
@@ -25,6 +25,7 @@ type RunQueryOptions = {
|
||||
cliServer: CodeQLCliServer;
|
||||
queryRunner: QueryRunner;
|
||||
databaseItem: DatabaseItem;
|
||||
language: QueryLanguage;
|
||||
queryStorageDir: string;
|
||||
queryDir: string;
|
||||
|
||||
@@ -70,6 +71,7 @@ export async function runModelEditorQueries(
|
||||
cliServer,
|
||||
queryRunner,
|
||||
databaseItem,
|
||||
language,
|
||||
queryStorageDir,
|
||||
queryDir,
|
||||
progress,
|
||||
@@ -157,7 +159,7 @@ export async function runModelEditorQueries(
|
||||
maxStep: externalApiQueriesProgressMaxStep,
|
||||
});
|
||||
|
||||
return decodeBqrsToMethods(bqrsChunk, mode);
|
||||
return decodeBqrsToMethods(bqrsChunk, mode, language);
|
||||
}
|
||||
|
||||
type GetResultsOptions = {
|
||||
|
||||
@@ -430,6 +430,7 @@ export class ModelEditorView extends AbstractWebview<
|
||||
cliServer: this.cliServer,
|
||||
queryRunner: this.queryRunner,
|
||||
databaseItem: this.databaseItem,
|
||||
language: this.language,
|
||||
queryStorageDir: this.queryStorageDir,
|
||||
queryDir: this.queryDir,
|
||||
progress: (update) =>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { decodeBqrsToMethods } from "../../../src/model-editor/bqrs";
|
||||
import { DecodedBqrsChunk } from "../../../src/common/bqrs-cli-types";
|
||||
import { CallClassification } from "../../../src/model-editor/method";
|
||||
import { Mode } from "../../../src/model-editor/shared/mode";
|
||||
import { QueryLanguage } from "../../../src/common/query-language";
|
||||
|
||||
describe("decodeBqrsToMethods", () => {
|
||||
describe("Java queries", () => {
|
||||
@@ -237,7 +238,9 @@ describe("decodeBqrsToMethods", () => {
|
||||
// Even though there are a number of methods with the same number of usages, the order returned should be stable:
|
||||
// - Iterating over a map (as done by .values()) is guaranteed to be in insertion order
|
||||
// - Sorting the array of methods is guaranteed to be a stable sort
|
||||
expect(decodeBqrsToMethods(chunk, Mode.Application)).toEqual([
|
||||
expect(
|
||||
decodeBqrsToMethods(chunk, Mode.Application, QueryLanguage.Java),
|
||||
).toEqual([
|
||||
{
|
||||
library: "rt",
|
||||
libraryVersion: undefined,
|
||||
@@ -499,7 +502,9 @@ describe("decodeBqrsToMethods", () => {
|
||||
};
|
||||
|
||||
it("extracts methods", () => {
|
||||
expect(decodeBqrsToMethods(chunk, Mode.Framework)).toEqual([
|
||||
expect(
|
||||
decodeBqrsToMethods(chunk, Mode.Framework, QueryLanguage.Java),
|
||||
).toEqual([
|
||||
{
|
||||
library: "",
|
||||
libraryVersion: undefined,
|
||||
@@ -594,7 +599,9 @@ describe("decodeBqrsToMethods", () => {
|
||||
};
|
||||
|
||||
it("extracts methods", () => {
|
||||
expect(decodeBqrsToMethods(chunk, Mode.Application)).toEqual([
|
||||
expect(
|
||||
decodeBqrsToMethods(chunk, Mode.Application, QueryLanguage.Java),
|
||||
).toEqual([
|
||||
{
|
||||
library: "mscorlib",
|
||||
libraryVersion: "4.0.0.0",
|
||||
@@ -660,7 +667,9 @@ describe("decodeBqrsToMethods", () => {
|
||||
};
|
||||
|
||||
it("extracts methods", () => {
|
||||
expect(decodeBqrsToMethods(chunk, Mode.Framework)).toEqual([
|
||||
expect(
|
||||
decodeBqrsToMethods(chunk, Mode.Framework, QueryLanguage.Java),
|
||||
).toEqual([
|
||||
{
|
||||
library: "Times",
|
||||
libraryVersion: undefined,
|
||||
|
||||
@@ -74,6 +74,7 @@ describe("runModelEditorQueries", () => {
|
||||
},
|
||||
language,
|
||||
}),
|
||||
language,
|
||||
queryStorageDir: "/tmp/queries",
|
||||
queryDir,
|
||||
progress: jest.fn(),
|
||||
@@ -139,6 +140,7 @@ describe("runModelEditorQueries", () => {
|
||||
},
|
||||
language,
|
||||
}),
|
||||
language,
|
||||
queryStorageDir: "/tmp/queries",
|
||||
queryDir,
|
||||
progress: jest.fn(),
|
||||
|
||||
Reference in New Issue
Block a user