@@ -3,19 +3,16 @@ import { DatabaseItem } from "../databases/local-databases";
33import { basename } from "path" ;
44import { QueryRunner } from "../query-server" ;
55import { CodeQLCliServer } from "../codeql-cli/cli" ;
6- import { showAndLogExceptionWithTelemetry , TeeLogger } from "../common/logging" ;
6+ import { showAndLogExceptionWithTelemetry } from "../common/logging" ;
77import { extLogger } from "../common/logging/vscode" ;
88import { extensiblePredicateDefinitions } from "./predicates" ;
99import { ProgressCallback } from "../common/vscode/progress" ;
1010import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders" ;
1111import { ModeledMethod , ModeledMethodType } from "./modeled-method" ;
1212import { redactableError } from "../common/errors" ;
13- import { QueryResultType } from "../query-server/new-messages" ;
14- import { file } from "tmp-promise" ;
15- import { writeFile } from "fs-extra" ;
16- import { dump } from "js-yaml" ;
17- import { qlpackOfDatabase } from "../local-queries" ;
13+ import { qlpackOfDatabase , resolveQueries } from "../local-queries" ;
1814import { telemetryListener } from "../common/vscode/telemetry" ;
15+ import { runQuery } from "../local-queries/run-query" ;
1916
2017type FlowModelOptions = {
2118 cliServer : CodeQLCliServer ;
@@ -27,44 +24,73 @@ type FlowModelOptions = {
2724 onResults : ( results : ModeledMethod [ ] ) => void | Promise < void > ;
2825} ;
2926
30- async function resolveQueries (
31- cliServer : CodeQLCliServer ,
32- databaseItem : DatabaseItem ,
33- ) : Promise < string [ ] > {
34- const qlpacks = await qlpackOfDatabase ( cliServer , databaseItem ) ;
27+ export async function runFlowModelQueries ( {
28+ onResults,
29+ ...options
30+ } : FlowModelOptions ) {
31+ const queries = await resolveFlowQueries (
32+ options . cliServer ,
33+ options . databaseItem ,
34+ ) ;
3535
36- const packsToSearch : string [ ] = [ ] ;
36+ const queriesByBasename : Record < string , string > = { } ;
37+ for ( const query of queries ) {
38+ queriesByBasename [ basename ( query ) ] = query ;
39+ }
3740
38- // The CLI can handle both library packs and query packs, so search both packs in order.
39- packsToSearch . push ( qlpacks . dbschemePack ) ;
40- if ( qlpacks . queryPack !== undefined ) {
41- packsToSearch . push ( qlpacks . queryPack ) ;
41+ const summaryResults = await runSingleFlowQuery (
42+ "summary" ,
43+ queriesByBasename [ "CaptureSummaryModels.ql" ] ,
44+ 0 ,
45+ options ,
46+ ) ;
47+ if ( summaryResults ) {
48+ await onResults ( summaryResults ) ;
4249 }
4350
44- const suiteFile = (
45- await file ( {
46- postfix : ".qls" ,
47- } )
48- ) . path ;
49- const suiteYaml = [ ] ;
50- for ( const qlpack of packsToSearch ) {
51- suiteYaml . push ( {
52- from : qlpack ,
53- queries : "." ,
54- include : {
55- "tags contain" : "modelgenerator" ,
56- } ,
57- } ) ;
51+ const sinkResults = await runSingleFlowQuery (
52+ "sink" ,
53+ queriesByBasename [ "CaptureSinkModels.ql" ] ,
54+ 1 ,
55+ options ,
56+ ) ;
57+ if ( sinkResults ) {
58+ await onResults ( sinkResults ) ;
5859 }
59- await writeFile ( suiteFile , dump ( suiteYaml ) , "utf8" ) ;
6060
61- return await cliServer . resolveQueriesInSuite (
62- suiteFile ,
63- getOnDiskWorkspaceFolders ( ) ,
61+ const sourceResults = await runSingleFlowQuery (
62+ "source" ,
63+ queriesByBasename [ "CaptureSourceModels.ql" ] ,
64+ 2 ,
65+ options ,
66+ ) ;
67+ if ( sourceResults ) {
68+ await onResults ( sourceResults ) ;
69+ }
70+
71+ const neutralResults = await runSingleFlowQuery (
72+ "neutral" ,
73+ queriesByBasename [ "CaptureNeutralModels.ql" ] ,
74+ 3 ,
75+ options ,
6476 ) ;
77+ if ( neutralResults ) {
78+ await onResults ( neutralResults ) ;
79+ }
6580}
6681
67- async function getModeledMethodsFromFlow (
82+ async function resolveFlowQueries (
83+ cliServer : CodeQLCliServer ,
84+ databaseItem : DatabaseItem ,
85+ ) : Promise < string [ ] > {
86+ const qlpacks = await qlpackOfDatabase ( cliServer , databaseItem ) ;
87+
88+ return await resolveQueries ( cliServer , qlpacks , "flow model generator" , {
89+ "tags contain" : [ "modelgenerator" ] ,
90+ } ) ;
91+ }
92+
93+ async function runSingleFlowQuery (
6894 type : Exclude < ModeledMethodType , "none" > ,
6995 queryPath : string | undefined ,
7096 queryStep : number ,
@@ -77,6 +103,7 @@ async function getModeledMethodsFromFlow(
77103 token,
78104 } : Omit < FlowModelOptions , "onResults" > ,
79105) : Promise < ModeledMethod [ ] > {
106+ // Check that the right query was found
80107 if ( queryPath === undefined ) {
81108 void showAndLogExceptionWithTelemetry (
82109 extLogger ,
@@ -86,45 +113,32 @@ async function getModeledMethodsFromFlow(
86113 return [ ] ;
87114 }
88115
89- const definition = extensiblePredicateDefinitions [ type ] ;
90-
91- const queryRun = queryRunner . createQueryRun (
92- databaseItem . databaseUri . fsPath ,
93- {
94- queryPath,
95- quickEvalPosition : undefined ,
96- quickEvalCountOnly : false ,
97- } ,
98- false ,
99- getOnDiskWorkspaceFolders ( ) ,
100- undefined ,
116+ // Run the query
117+ const completedQuery = await runQuery ( {
118+ cliServer,
119+ queryRunner,
120+ databaseItem,
121+ queryPath,
101122 queryStorageDir,
102- undefined ,
103- undefined ,
104- ) ;
105-
106- const queryResult = await queryRun . evaluate (
107- ( { step, message } ) =>
123+ additionalPacks : getOnDiskWorkspaceFolders ( ) ,
124+ extensionPacks : undefined ,
125+ progress : ( { step, message } ) =>
108126 progress ( {
109127 message : `Generating ${ type } model: ${ message } ` ,
110128 step : queryStep * 1000 + step ,
111129 maxStep : 4000 ,
112130 } ) ,
113131 token,
114- new TeeLogger ( queryRunner . logger , queryRun . outputDir . logPath ) ,
115- ) ;
116- if ( queryResult . resultType !== QueryResultType . SUCCESS ) {
117- void showAndLogExceptionWithTelemetry (
118- extLogger ,
119- telemetryListener ,
120- redactableError `Failed to run ${ basename ( queryPath ) } query: ${
121- queryResult . message ?? "No message"
122- } `,
123- ) ;
132+ } ) ;
133+
134+ if ( ! completedQuery ) {
124135 return [ ] ;
125136 }
126137
127- const bqrsPath = queryResult . outputDir . bqrsPath ;
138+ // Interpret the results
139+ const definition = extensiblePredicateDefinitions [ type ] ;
140+
141+ const bqrsPath = completedQuery . outputDir . bqrsPath ;
128142
129143 const bqrsInfo = await cliServer . bqrsInfo ( bqrsPath ) ;
130144 if ( bqrsInfo [ "result-sets" ] . length !== 1 ) {
@@ -154,55 +168,3 @@ async function getModeledMethodsFromFlow(
154168 } )
155169 ) ;
156170}
157-
158- export async function generateFlowModel ( {
159- onResults,
160- ...options
161- } : FlowModelOptions ) {
162- const queries = await resolveQueries ( options . cliServer , options . databaseItem ) ;
163-
164- const queriesByBasename : Record < string , string > = { } ;
165- for ( const query of queries ) {
166- queriesByBasename [ basename ( query ) ] = query ;
167- }
168-
169- const summaryResults = await getModeledMethodsFromFlow (
170- "summary" ,
171- queriesByBasename [ "CaptureSummaryModels.ql" ] ,
172- 0 ,
173- options ,
174- ) ;
175- if ( summaryResults ) {
176- await onResults ( summaryResults ) ;
177- }
178-
179- const sinkResults = await getModeledMethodsFromFlow (
180- "sink" ,
181- queriesByBasename [ "CaptureSinkModels.ql" ] ,
182- 1 ,
183- options ,
184- ) ;
185- if ( sinkResults ) {
186- await onResults ( sinkResults ) ;
187- }
188-
189- const sourceResults = await getModeledMethodsFromFlow (
190- "source" ,
191- queriesByBasename [ "CaptureSourceModels.ql" ] ,
192- 2 ,
193- options ,
194- ) ;
195- if ( sourceResults ) {
196- await onResults ( sourceResults ) ;
197- }
198-
199- const neutralResults = await getModeledMethodsFromFlow (
200- "neutral" ,
201- queriesByBasename [ "CaptureNeutralModels.ql" ] ,
202- 3 ,
203- options ,
204- ) ;
205- if ( neutralResults ) {
206- await onResults ( neutralResults ) ;
207- }
208- }
0 commit comments