Display query text in "virtual" (readonly) file

This commit is contained in:
shati-patel
2021-12-10 21:57:53 +00:00
committed by Shati Patel
parent 3c73390a44
commit b7f86ae7a9
8 changed files with 65 additions and 31 deletions

View File

@@ -12,7 +12,9 @@ import {
env,
window,
QuickPickItem,
Range
Range,
workspace,
ProviderResult
} from 'vscode';
import { LanguageClient } from 'vscode-languageclient';
import * as os from 'os';
@@ -78,6 +80,7 @@ import { CodeQlStatusBarHandler } from './status-bar';
import { Credentials } from './authentication';
import { RemoteQueriesManager } from './remote-queries/remote-queries-manager';
import { RemoteQuery } from './remote-queries/remote-query';
import { URLSearchParams } from 'url';
/**
* extension.ts
@@ -773,6 +776,8 @@ async function activateWithInstalledDistribution(
void logger.log('Initializing remote queries interface.');
const rqm = new RemoteQueriesManager(ctx, logger, cliServer);
registerTextProvider();
// The "runRemoteQuery" command is internal-only.
ctx.subscriptions.push(
commandRunnerWithProgress('codeQL.runRemoteQuery', async (
@@ -980,3 +985,20 @@ async function initializeLogging(ctx: ExtensionContext): Promise<void> {
}
const checkForUpdatesCommand = 'codeQL.checkForUpdatesToCLI';
/**
* This text provider lets us open readonly files in the editor.
*
* TODO: Consolidate this with the 'codeql' text provider in query-history.ts.
*/
function registerTextProvider() {
workspace.registerTextDocumentContentProvider('remote-query', {
provideTextDocumentContent(
uri: Uri
): ProviderResult<string> {
const params = new URLSearchParams(uri.query);
return params.get('queryText');
},
});
}

View File

@@ -181,6 +181,11 @@ export interface OpenFileMsg {
filePath: string;
}
export interface OpenVirtualFileMsg {
t: 'openVirtualFile';
queryText: string;
}
/**
* Message from the results view to toggle the display of
* query diagnostics.
@@ -369,7 +374,8 @@ export interface ParsedResultSets {
export type FromRemoteQueriesMessage =
| RemoteQueryLoadedMessage
| RemoteQueryErrorMessage
| OpenFileMsg;
| OpenFileMsg
| OpenVirtualFileMsg;
export type ToRemoteQueriesMessage =
| SetRemoteQueryResultMessage;

View File

@@ -32,7 +32,7 @@ export type QueryHistoryItemOptions = {
isQuickQuery?: boolean;
};
const SHOW_QUERY_TEXT_MSG = `\
export const SHOW_QUERY_TEXT_MSG = `\
////////////////////////////////////////////////////////////////////////////////////
// This is the text of the entire query file when it was executed for this query //
// run. The text or dependent libraries may have changed since then. //

View File

@@ -21,6 +21,8 @@ import { RemoteQuery } from './remote-query';
import { RemoteQueryResult as RemoteQueryResultViewModel } from './shared/remote-query-result';
import { AnalysisResult as AnalysisResultViewModel } from './shared/remote-query-result';
import { showAndLogWarningMessage } from '../helpers';
import { URLSearchParams } from 'url';
import { SHOW_QUERY_TEXT_MSG } from '../query-history';
export class RemoteQueriesInterfaceManager {
private panel: WebviewPanel | undefined;
@@ -65,7 +67,7 @@ export class RemoteQueriesInterfaceManager {
queryTitle: query.queryName,
queryFileName: queryFileName,
queryFilePath: query.queryFilePath,
queryTextTmpFilePath: query.queryTextTmpFilePath,
queryText: query.queryText,
totalRepositoryCount: query.repositories.length,
affectedRepositoryCount: affectedRepositories.length,
totalResultCount: totalResultCount,
@@ -142,6 +144,22 @@ export class RemoteQueriesInterfaceManager {
}
}
private async openVirtualFile(text: string) {
try {
const params = new URLSearchParams({
queryText: encodeURIComponent(SHOW_QUERY_TEXT_MSG + text)
});
const uri = Uri.parse(
`remote-query:query-text.ql?${params.toString()}`,
true
);
const doc = await workspace.openTextDocument(uri);
await Window.showTextDocument(doc, { preview: false });
} catch (error) {
void showAndLogWarningMessage('Could not open query text');
}
}
private async handleMsgFromView(
msg: FromRemoteQueriesMessage
): Promise<void> {
@@ -159,6 +177,9 @@ export class RemoteQueriesInterfaceManager {
case 'openFile':
await this.openFile(msg.filePath);
break;
case 'openVirtualFile':
await this.openVirtualFile(msg.queryText);
break;
default:
assertNever(msg);
}

View File

@@ -3,7 +3,7 @@ import { Repository } from './repository';
export interface RemoteQuery {
queryName: string;
queryFilePath: string;
queryTextTmpFilePath: string;
queryText: string;
controllerRepository: Repository;
repositories: Repository[];
executionStartTime: Date;

View File

@@ -467,26 +467,12 @@ async function buildRemoteQueryEntity(
return { owner: owner, name: repo };
});
// Get the query text from query file and save it in a temporary .ql file.
const queryTextTmpFilePath = path.join(tmpDir.name, `tmp-${queryName}`);
const queryText = await fs.readFile(queryFilePath, 'utf8');
await fs.writeFile(
queryTextTmpFilePath, `\
////////////////////////////////////////////////////////////////////////////////////
// This is the text of the entire query file when it was executed for this query //
// run. The text or dependent libraries may have changed since then. //
// //
// To make changes to the query and the dependent libraries, save this file in a //
// suitable, permanent location. //
////////////////////////////////////////////////////////////////////////////////////
${queryText}`
);
return {
queryName,
queryFilePath,
queryTextTmpFilePath,
queryText,
controllerRepository: {
owner: controllerRepoOwner,
name: controllerRepoName,

View File

@@ -2,7 +2,7 @@ export interface RemoteQueryResult {
queryTitle: string;
queryFileName: string;
queryFilePath: string;
queryTextTmpFilePath: string;
queryText: string;
totalRepositoryCount: number;
affectedRepositoryCount: number;
totalResultCount: number;

View File

@@ -13,7 +13,7 @@ const emptyQueryResult: RemoteQueryResult = {
queryTitle: '',
queryFileName: '',
queryFilePath: '',
queryTextTmpFilePath: '',
queryText: '',
totalRepositoryCount: 0,
affectedRepositoryCount: 0,
totalResultCount: 0,
@@ -40,13 +40,6 @@ const AnalysisResultItem = (props: AnalysisResult) => (
</span>
);
function openFile(filePath: string): void {
vscode.postMessage({
t: 'openFile',
filePath
});
}
export function RemoteQueries(): JSX.Element {
const [queryResult, setQueryResult] = useState<RemoteQueryResult>(emptyQueryResult);
@@ -74,11 +67,17 @@ export function RemoteQueries(): JSX.Element {
try {
const openQueryFile = () => {
openFile(queryResult.queryFilePath);
vscode.postMessage({
t: 'openFile',
filePath: queryResult.queryFilePath
});
};
const openQueryTextTmpFile = () => {
openFile(queryResult.queryTextTmpFilePath);
vscode.postMessage({
t: 'openVirtualFile',
queryText: queryResult.queryText
});
};
return <div className="vscode-codeql__remote-queries-view">