Skip to content

Commit 552baa5

Browse files
Merge branch 'main' into robertbrignull/details-multiple-editors
2 parents 6005e3a + 5726244 commit 552baa5

12 files changed

Lines changed: 350 additions & 228 deletions

File tree

extensions/ql-vscode/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [UNRELEASED]
44

5+
## 1.8.10 - 15 August 2023
6+
7+
- Add a code lens to make the `CodeQL: Open Referenced File` command more discoverable. Click the "Open referenced file" prompt in a `.qlref` file to jump to the referenced `.ql` file. [#2704](https://github.com/github/vscode-codeql/pull/2704)
8+
59
## 1.8.9 - 3 August 2023
610

711
- Remove "last updated" information and sorting from variant analysis results view. [#2637](https://github.com/github/vscode-codeql/pull/2637)

extensions/ql-vscode/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "CodeQL for Visual Studio Code",
55
"author": "GitHub",
66
"private": true,
7-
"version": "1.8.10",
7+
"version": "1.8.11",
88
"publisher": "GitHub",
99
"license": "MIT",
1010
"icon": "media/VS-marketplace-CodeQL-icon.png",
@@ -14,7 +14,7 @@
1414
},
1515
"engines": {
1616
"vscode": "^1.67.0",
17-
"node": "^16.13.0",
17+
"node": "^16.17.1",
1818
"npm": ">=7.20.6"
1919
},
2020
"categories": [

extensions/ql-vscode/src/data-extensions-editor/model-details/model-details-data-provider.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,27 @@ export class ModelDetailsDataProvider
3434
return this.onDidChangeTreeDataEmitter.event;
3535
}
3636

37+
/**
38+
* Update the data displayed in the tree view.
39+
*
40+
* Will only trigger an update if the data has changed. This relies on
41+
* object identity, so be sure to not mutate the data passed to this
42+
* method and instead always pass new objects/arrays.
43+
*/
3744
public async setState(
3845
externalApiUsages: ExternalApiUsage[],
3946
databaseItem: DatabaseItem,
4047
): Promise<void> {
41-
this.externalApiUsages = externalApiUsages;
42-
this.databaseItem = databaseItem;
43-
this.sourceLocationPrefix = await this.databaseItem.getSourceLocationPrefix(
44-
this.cliServer,
45-
);
46-
this.onDidChangeTreeDataEmitter.fire();
48+
if (
49+
this.externalApiUsages !== externalApiUsages ||
50+
this.databaseItem !== databaseItem
51+
) {
52+
this.externalApiUsages = externalApiUsages;
53+
this.databaseItem = databaseItem;
54+
this.sourceLocationPrefix =
55+
await this.databaseItem.getSourceLocationPrefix(this.cliServer);
56+
this.onDidChangeTreeDataEmitter.fire();
57+
}
4758
}
4859

4960
getTreeItem(item: ModelDetailsTreeViewItem): TreeItem {

extensions/ql-vscode/src/extension.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ import { TestRunner } from "./query-testing/test-runner";
134134
import { TestManagerBase } from "./query-testing/test-manager-base";
135135
import { NewQueryRunner, QueryRunner, QueryServerClient } from "./query-server";
136136
import { QueriesModule } from "./queries-panel/queries-module";
137+
import { OpenReferencedFileCodeLensProvider } from "./local-queries/open-referenced-file-code-lens-provider";
137138

138139
/**
139140
* extension.ts
@@ -332,10 +333,17 @@ export async function activate(
332333

333334
const app = new ExtensionApp(ctx);
334335

335-
const codelensProvider = new QuickEvalCodeLensProvider();
336+
const quickEvalCodeLensProvider = new QuickEvalCodeLensProvider();
336337
languages.registerCodeLensProvider(
337338
{ scheme: "file", language: "ql" },
338-
codelensProvider,
339+
quickEvalCodeLensProvider,
340+
);
341+
342+
const openReferencedFileCodeLensProvider =
343+
new OpenReferencedFileCodeLensProvider();
344+
languages.registerCodeLensProvider(
345+
{ scheme: "file", pattern: "**/*.qlref" },
346+
openReferencedFileCodeLensProvider,
339347
);
340348

341349
ctx.subscriptions.push(distributionConfigListener);

extensions/ql-vscode/src/local-queries/local-queries.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
CancellationTokenSource,
99
QuickPickItem,
1010
Range,
11+
TabInputText,
1112
Uri,
1213
window,
1314
} from "vscode";
@@ -300,20 +301,18 @@ export class LocalQueries extends DisposableObject {
300301
}
301302

302303
/**
303-
* Gets the current active query.
304-
*
305-
* For now, the "active query" is just whatever query is in the active text editor. Once we have a
306-
* proper "queries" panel, we can provide a way to select the current query there.
304+
* Gets the current active query. This is the query that is open in the active tab.
307305
*/
308306
public async getCurrentQuery(allowLibraryFiles: boolean): Promise<string> {
309-
const editor = window.activeTextEditor;
310-
if (editor === undefined) {
307+
const input = window.tabGroups.activeTabGroup.activeTab?.input;
308+
309+
if (input === undefined || !isTabInputText(input)) {
311310
throw new Error(
312311
"No query was selected. Please select a query and try again.",
313312
);
314313
}
315314

316-
return validateQueryUri(editor.document.uri, allowLibraryFiles);
315+
return validateQueryUri(input.uri, allowLibraryFiles);
317316
}
318317

319318
private async createSkeletonQuery(): Promise<void> {
@@ -581,3 +580,7 @@ export class LocalQueries extends DisposableObject {
581580
: [];
582581
}
583582
}
583+
584+
function isTabInputText(input: any): input is TabInputText {
585+
return input?.uri !== undefined;
586+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {
2+
CodeLensProvider,
3+
TextDocument,
4+
CodeLens,
5+
Command,
6+
Range,
7+
} from "vscode";
8+
9+
export class OpenReferencedFileCodeLensProvider implements CodeLensProvider {
10+
async provideCodeLenses(document: TextDocument): Promise<CodeLens[]> {
11+
const codeLenses: CodeLens[] = [];
12+
13+
// A .qlref file is a file that contains a single line with a path to a .ql file.
14+
if (document.fileName.endsWith(".qlref")) {
15+
const textLine = document.lineAt(0);
16+
const range: Range = new Range(
17+
textLine.range.start.line,
18+
textLine.range.start.character,
19+
textLine.range.start.line,
20+
textLine.range.end.character,
21+
);
22+
23+
const command: Command = {
24+
command: "codeQL.openReferencedFile",
25+
title: `Open referenced file`,
26+
arguments: [document.uri],
27+
};
28+
const codeLens = new CodeLens(range, command);
29+
codeLenses.push(codeLens);
30+
}
31+
32+
return codeLenses;
33+
}
34+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as React from "react";
2+
import { ALERTS_TABLE_NAME } from "../../common/interface-types";
3+
import {
4+
alertExtrasClassName,
5+
toggleDiagnosticsClassName,
6+
} from "./result-table-utils";
7+
8+
interface Props {
9+
selectedTable: string;
10+
problemsViewSelected: boolean;
11+
handleCheckboxChanged: (event: React.ChangeEvent<HTMLInputElement>) => void;
12+
}
13+
14+
export function ProblemsViewCheckbox(props: Props): JSX.Element | null {
15+
const { selectedTable, problemsViewSelected, handleCheckboxChanged } = props;
16+
17+
if (selectedTable !== ALERTS_TABLE_NAME) {
18+
return null;
19+
}
20+
return (
21+
<div className={alertExtrasClassName}>
22+
<div className={toggleDiagnosticsClassName}>
23+
<input
24+
type="checkbox"
25+
id="toggle-diagnostics"
26+
name="toggle-diagnostics"
27+
onChange={handleCheckboxChanged}
28+
checked={problemsViewSelected}
29+
/>
30+
<label htmlFor="toggle-diagnostics">
31+
Show results in Problems view
32+
</label>
33+
</div>
34+
</div>
35+
);
36+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as React from "react";
2+
import { ResultSet } from "../../common/interface-types";
3+
import { tableHeaderItemClassName } from "./result-table-utils";
4+
5+
interface Props {
6+
resultSet?: ResultSet;
7+
}
8+
9+
function getResultCount(resultSet: ResultSet): number {
10+
switch (resultSet.t) {
11+
case "RawResultSet":
12+
return resultSet.schema.rows;
13+
case "InterpretedResultSet":
14+
return resultSet.interpretation.numTotalResults;
15+
}
16+
}
17+
18+
export function ResultCount(props: Props): JSX.Element | null {
19+
if (!props.resultSet) {
20+
return null;
21+
}
22+
23+
const resultCount = getResultCount(props.resultSet);
24+
return (
25+
<span className={tableHeaderItemClassName}>
26+
{resultCount} {resultCount === 1 ? "result" : "results"}
27+
</span>
28+
);
29+
}

0 commit comments

Comments
 (0)