@@ -6,6 +6,7 @@ import { QueryHistoryConfig } from './config';
66import { QueryWithResults } from './run-queries' ;
77import * as helpers from './helpers' ;
88import { logger } from './logging' ;
9+ import { URLSearchParams } from 'url' ;
910
1011/**
1112 * query-history.ts
@@ -18,9 +19,32 @@ import { logger } from './logging';
1819
1920export type QueryHistoryItemOptions = {
2021 label ?: string ; // user-settable label
21- queryText ?: string ; // stored query for quick query
22+ queryText ?: string ; // text of the selected file
23+ isQuickQuery ?: boolean ;
2224}
2325
26+ const SHOW_QUERY_TEXT_MSG = `\
27+ ////////////////////////////////////////////////////////////////////////////////////
28+ // This is the text of the entire query file when it was executed for this query //
29+ // run. The text or dependent libraries may have changed since then. //
30+ // //
31+ // This buffer is readonly. To re-execute this query, you must open the original //
32+ // query file. //
33+ ////////////////////////////////////////////////////////////////////////////////////
34+
35+ ` ;
36+
37+ const SHOW_QUERY_TEXT_QUICK_EVAL_MSG = `\
38+ ////////////////////////////////////////////////////////////////////////////////////
39+ // This is the Quick Eval selection of the query file when it was executed for //
40+ // this query run. The text or dependent libraries may have changed since then. //
41+ // //
42+ // This buffer is readonly. To re-execute this query, you must open the original //
43+ // query file. //
44+ ////////////////////////////////////////////////////////////////////////////////////
45+
46+ ` ;
47+
2448/**
2549 * Path to icon to display next to a failed query history item.
2650 */
@@ -137,7 +161,7 @@ export class QueryHistoryManager {
137161 const textDocument = await vscode . workspace . openTextDocument ( vscode . Uri . file ( queryHistoryItem . query . program . queryPath ) ) ;
138162 const editor = await vscode . window . showTextDocument ( textDocument , vscode . ViewColumn . One ) ;
139163 const queryText = queryHistoryItem . options . queryText ;
140- if ( queryText !== undefined ) {
164+ if ( queryText !== undefined && queryHistoryItem . options . isQuickQuery ) {
141165 await editor . edit ( edit => edit . replace ( textDocument . validateRange (
142166 new vscode . Range ( 0 , 0 , textDocument . lineCount , 0 ) ) , queryText )
143167 ) ;
@@ -218,6 +242,36 @@ export class QueryHistoryManager {
218242 }
219243 }
220244
245+ async handleShowQueryText ( queryHistoryItem : CompletedQuery ) {
246+ try {
247+ const queryName = queryHistoryItem . queryName . endsWith ( '.ql' ) ? queryHistoryItem . queryName : queryHistoryItem . queryName + '.ql' ;
248+ const params = new URLSearchParams ( {
249+ isQuickEval : String ( ! ! queryHistoryItem . query . quickEvalPosition ) ,
250+ queryText : await this . getQueryText ( queryHistoryItem )
251+ } ) ;
252+ const uri = vscode . Uri . parse ( `codeql:${ queryHistoryItem . query . queryID } -${ queryName } ?${ params . toString ( ) } ` ) ;
253+ const doc = await vscode . workspace . openTextDocument ( uri ) ;
254+ await vscode . window . showTextDocument ( doc , { preview : false } ) ;
255+ } catch ( e ) {
256+ helpers . showAndLogErrorMessage ( e . message ) ;
257+ }
258+ }
259+
260+ async getQueryText ( queryHistoryItem : CompletedQuery ) : Promise < string > {
261+ if ( queryHistoryItem . options . queryText ) {
262+ return queryHistoryItem . options . queryText ;
263+ } else if ( queryHistoryItem . query . quickEvalPosition ) {
264+ // capture all selected lines
265+ const startLine = queryHistoryItem . query . quickEvalPosition . line ;
266+ const endLine = queryHistoryItem . query . quickEvalPosition . endLine ;
267+ const textDocument =
268+ await vscode . workspace . openTextDocument ( queryHistoryItem . query . quickEvalPosition . fileName ) ;
269+ return textDocument . getText ( new vscode . Range ( startLine - 1 , 0 , endLine , 0 ) ) ;
270+ } else {
271+ return '' ;
272+ }
273+ }
274+
221275 constructor (
222276 ctx : ExtensionContext ,
223277 private queryHistoryConfigListener : QueryHistoryConfig ,
@@ -240,12 +294,24 @@ export class QueryHistoryManager {
240294 ctx . subscriptions . push ( vscode . commands . registerCommand ( 'codeQLQueryHistory.removeHistoryItem' , this . handleRemoveHistoryItem . bind ( this ) ) ) ;
241295 ctx . subscriptions . push ( vscode . commands . registerCommand ( 'codeQLQueryHistory.setLabel' , this . handleSetLabel . bind ( this ) ) ) ;
242296 ctx . subscriptions . push ( vscode . commands . registerCommand ( 'codeQLQueryHistory.showQueryLog' , this . handleShowQueryLog . bind ( this ) ) ) ;
297+ ctx . subscriptions . push ( vscode . commands . registerCommand ( 'codeQLQueryHistory.showQueryText' , this . handleShowQueryText . bind ( this ) ) ) ;
243298 ctx . subscriptions . push ( vscode . commands . registerCommand ( 'codeQLQueryHistory.itemClicked' , async ( item ) => {
244299 return this . handleItemClicked ( item ) ;
245300 } ) ) ;
246301 queryHistoryConfigListener . onDidChangeQueryHistoryConfiguration ( ( ) => {
247302 this . treeDataProvider . refresh ( ) ;
248303 } ) ;
304+
305+ // displays query text in a read-only document
306+ vscode . workspace . registerTextDocumentContentProvider ( 'codeql' , {
307+ provideTextDocumentContent ( uri : vscode . Uri ) : vscode . ProviderResult < string > {
308+ const params = new URLSearchParams ( uri . query )
309+
310+ return (
311+ JSON . parse ( params . get ( 'isQuickEval' ) || '' ) ? SHOW_QUERY_TEXT_QUICK_EVAL_MSG : SHOW_QUERY_TEXT_MSG
312+ ) + params . get ( 'queryText' ) ;
313+ }
314+ } ) ;
249315 }
250316
251317 addQuery ( info : QueryWithResults ) : CompletedQuery {
0 commit comments