Merge remote-tracking branch 'origin/main' into koesie10/deprecate-lgtm-download

This commit is contained in:
Koen Vlaswinkel
2022-09-13 10:38:52 +02:00
100 changed files with 51583 additions and 2974 deletions

6
.gitattributes vendored
View File

@@ -18,4 +18,8 @@ yarn.lock merge=binary
# https://mirrors.edge.kernel.org/pub/software/scm/git/docs/gitattributes.html
# suggests that this might interleave lines arbitrarily, but empirically
# it keeps added chunks contiguous
CHANGELOG.md merge=union
CHANGELOG.md merge=union
# Mark some JSON files containing test data as generated so they are not included
# as part of diffs or language statistics.
extensions/ql-vscode/src/stories/remote-queries/data/*.json linguist-generated

View File

@@ -22,7 +22,7 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '16.13.0'
node-version: '16.14.0'
- name: Install dependencies
working-directory: extensions/ql-vscode
@@ -82,7 +82,7 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '16.13.0'
node-version: '16.14.0'
- name: Install dependencies
working-directory: extensions/ql-vscode
@@ -139,7 +139,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
version: ['v2.6.3', 'v2.7.6', 'v2.8.5', 'v2.9.4', 'v2.10.3', 'nightly']
version: ['v2.6.3', 'v2.7.6', 'v2.8.5', 'v2.9.4', 'v2.10.4', 'nightly']
env:
CLI_VERSION: ${{ matrix.version }}
NIGHTLY_URL: ${{ needs.find-nightly.outputs.url }}
@@ -151,7 +151,7 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '16.13.0'
node-version: '16.14.0'
- name: Install dependencies
working-directory: extensions/ql-vscode

View File

@@ -22,7 +22,7 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: '16.13.0'
node-version: '16.14.0'
- name: Install dependencies
run: |

8
.vscode/launch.json vendored
View File

@@ -124,6 +124,14 @@
"outFiles": [
"${workspaceRoot}/extensions/ql-vscode/out/**/*.js",
],
},
{
"name": "Launch Storybook",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/extensions/ql-vscode",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "storybook"]
}
]
}

View File

@@ -77,6 +77,20 @@ $ vscode/scripts/code-cli.sh --install-extension dist/vscode-codeql-*.vsix # if
You can use VS Code to debug the extension without explicitly installing it. Just open this directory as a workspace in VS Code, and hit `F5` to start a debugging session.
### Storybook
You can use [Storybook](https://storybook.js.org/) to preview React components outside VSCode. Inside the `extensions/ql-vscode` directory, run:
```shell
npm run storybook
```
Your browser should automatically open to the Storybook UI. Stories live in the `src/stories` directory.
Alternatively, you can start Storybook inside of VSCode. There is a VSCode launch configuration for starting Storybook. It can be found in the debug view.
More information about Storybook can be found inside the **Overview** page once you have launched Storybook.
### Running the unit tests and integration tests that do not require a CLI instance
Unit tests and many integration tests do not require a copy of the CodeQL CLI.

View File

@@ -0,0 +1,2 @@
# Storybook requires this option to be set. See https://github.com/storybookjs/storybook/issues/18298
legacy-peer-deps=true

View File

@@ -1 +1 @@
v16.13.0
v16.14.0

View File

@@ -0,0 +1,19 @@
import type { StorybookConfig } from '@storybook/core-common';
const config: StorybookConfig = {
stories: [
'../src/**/*.stories.mdx',
'../src/**/*.stories.@(js|jsx|ts|tsx)'
],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions'
],
framework: '@storybook/react',
core: {
builder: '@storybook/builder-webpack5'
}
};
module.exports = config;

View File

@@ -0,0 +1,7 @@
import { addons } from '@storybook/addons';
import { themes } from '@storybook/theming';
addons.setConfig({
theme: themes.dark,
enableShortcuts: false,
});

View File

@@ -0,0 +1,37 @@
import { themes } from '@storybook/theming';
import { action } from '@storybook/addon-actions';
// Allow all stories/components to use Codicons
import '@vscode/codicons/dist/codicon.css';
import '../src/stories/vscode-theme.css';
// https://storybook.js.org/docs/react/configure/overview#configure-story-rendering
export const parameters = {
// All props starting with `on` will automatically receive an action as a prop
actions: { argTypesRegex: "^on[A-Z].*" },
// All props matching these names will automatically get the correct control
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
// Use a dark theme to be aligned with VSCode
docs: {
theme: themes.dark,
},
backgrounds: {
default: 'dark',
values: [
{
name: 'dark',
value: '#1e1e1e',
},
],
}
};
(window as any).acquireVsCodeApi = () => ({
postMessage: action('post-vscode-message')
});

View File

@@ -2,8 +2,19 @@
## [UNRELEASED]
- Add ability for users to download databases directly from GitHub. [#1466](https://github.com/github/vscode-codeql/pull/1466)
- Remove ability to download databases from LGTM. [#1467](https://github.com/github/vscode-codeql/pull/1467)
- Removed the ability to manually upgrade databases from the context menu on databases. Databases are non-destructively upgraded automatically so
for most users this was not needed. For advanced users this is still available in the Command Palette. [#1501](https://github.com/github/vscode-codeql/pull/1501)
## 1.6.12 - 1 September 2022
- Add ability for users to download databases directly from GitHub. [#1485](https://github.com/github/vscode-codeql/pull/1485)
- Fix a race condition that could cause a failure to open the evaluator log when running a query. [#1490](https://github.com/github/vscode-codeql/pull/1490)
- Fix an error when running a query with an older version of the CodeQL CLI. [#1490](https://github.com/github/vscode-codeql/pull/1490)
## 1.6.11 - 25 August 2022
No user facing changes.
## 1.6.10 - 9 August 2022

View File

@@ -1,5 +1,5 @@
import * as gulp from 'gulp';
import { compileTypeScript, watchTypeScript, copyViewCss, cleanOutput, watchCss } from './typescript';
import { compileTypeScript, watchTypeScript, cleanOutput } from './typescript';
import { compileTextMateGrammar } from './textmate';
import { copyTestData } from './tests';
import { compileView, watchView } from './webpack';
@@ -10,7 +10,7 @@ export const buildWithoutPackage =
gulp.series(
cleanOutput,
gulp.parallel(
compileTypeScript, compileTextMateGrammar, compileView, copyTestData, copyViewCss
compileTypeScript, compileTextMateGrammar, compileView, copyTestData
)
);
@@ -23,6 +23,5 @@ export {
copyTestData,
injectAppInsightsKey,
compileView,
watchCss
};
export default gulp.series(buildWithoutPackage, injectAppInsightsKey, packageExtension);

View File

@@ -39,13 +39,3 @@ export function compileTypeScript() {
export function watchTypeScript() {
gulp.watch('src/**/*.ts', compileTypeScript);
}
export function watchCss() {
gulp.watch('src/**/*.css', copyViewCss);
}
/** Copy CSS files for the results view into the output directory. */
export function copyViewCss() {
return gulp.src('src/**/view/*.css')
.pipe(gulp.dest('out'));
}

View File

@@ -1,12 +1,11 @@
import * as path from 'path';
import * as webpack from 'webpack';
import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';
export const config: webpack.Configuration = {
mode: 'development',
entry: {
resultsView: './src/view/results.tsx',
compareView: './src/compare/view/Compare.tsx',
remoteQueriesView: './src/remote-queries/view/RemoteQueries.tsx',
webview: './src/view/webview.tsx'
},
output: {
path: path.resolve(__dirname, '..', 'out'),
@@ -31,9 +30,7 @@ export const config: webpack.Configuration = {
{
test: /\.less$/,
use: [
{
loader: 'style-loader'
},
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
@@ -53,17 +50,31 @@ export const config: webpack.Configuration = {
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
MiniCssExtractPlugin.loader,
{
loader: 'css-loader'
}
]
},
{
test: /\.(woff(2)?|ttf|eot)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
// We need this to make Webpack use the correct path for the fonts.
// Without this, the CSS file will use `url([object Module])`
esModule: false
}
},
],
}
]
},
performance: {
hints: false
}
},
plugins: [new MiniCssExtractPlugin()],
};

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
"description": "CodeQL for Visual Studio Code",
"author": "GitHub",
"private": true,
"version": "1.6.11",
"version": "1.6.13",
"publisher": "GitHub",
"license": "MIT",
"icon": "media/VS-marketplace-CodeQL-icon.png",
@@ -288,7 +288,7 @@
"default": "",
"pattern": "^$|^(?:[a-zA-Z0-9]+-)*[a-zA-Z0-9]+/[a-zA-Z0-9-_]+$",
"patternErrorMessage": "Please enter a valid GitHub repository",
"markdownDescription": "[For internal use only] The name of the GitHub repository where you can view the progress and results of the \"Run Variant Analysis\" command. The repository should be of the form `<owner>/<repo>`)."
"markdownDescription": "[For internal use only] The name of the GitHub repository in which the GitHub Actions workflow is run when using the \"Run Variant Analysis\" command. The repository should be of the form `<owner>/<repo>`)."
}
}
},
@@ -724,11 +724,6 @@
"group": "9_qlCommands",
"when": "view == codeQLDatabases"
},
{
"command": "codeQLDatabases.upgradeDatabase",
"group": "9_qlCommands",
"when": "view == codeQLDatabases"
},
{
"command": "codeQLDatabases.renameDatabase",
"group": "9_qlCommands",
@@ -752,7 +747,7 @@
{
"command": "codeQLQueryHistory.removeHistoryItem",
"group": "9_qlCommands",
"when": "viewItem == interpretedResultsItem || viewItem == rawResultsItem || viewItem == remoteResultsItem || viewItem == cancelledResultsItem"
"when": "viewItem == interpretedResultsItem || viewItem == rawResultsItem || viewItem == remoteResultsItem || viewItem == cancelledResultsItem || viewItem == cancelledRemoteResultsItem"
},
{
"command": "codeQLQueryHistory.setLabel",
@@ -827,7 +822,7 @@
{
"command": "codeQLQueryHistory.openOnGithub",
"group": "9_qlCommands",
"when": "viewItem == remoteResultsItem || viewItem == inProgressRemoteResultsItem || viewItem == cancelledResultsItem"
"when": "viewItem == remoteResultsItem || viewItem == inProgressRemoteResultsItem || viewItem == cancelledRemoteResultsItem"
},
{
"command": "codeQLQueryHistory.copyRepoList",
@@ -878,6 +873,10 @@
}
],
"commandPalette": [
{
"command": "codeQL.authenticateToGitHub",
"when": "config.codeQL.canary"
},
{
"command": "codeQL.runQuery",
"when": "resourceLangId == ql && resourceExtname == .ql"
@@ -1184,7 +1183,6 @@
"watch": "npm-run-all -p watch:*",
"watch:extension": "tsc --watch",
"watch:webpack": "gulp watchView",
"watch:css": "gulp watchCss",
"test": "mocha --exit -r ts-node/register test/pure-tests/**/*.ts",
"preintegration": "rm -rf ./out/vscode-tests && gulp",
"integration": "node ./out/vscode-tests/run-integration-tests.js no-workspace,minimal-workspace",
@@ -1192,18 +1190,20 @@
"update-vscode": "node ./node_modules/vscode/bin/install",
"format": "tsfmt -r && eslint src test --ext .ts,.tsx --fix",
"lint": "eslint src test --ext .ts,.tsx --max-warnings=0",
"format-staged": "lint-staged"
"format-staged": "lint-staged",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"dependencies": {
"@octokit/rest": "^18.5.6",
"@octokit/plugin-retry": "^3.0.9",
"@octokit/rest": "^18.5.6",
"@primer/octicons-react": "^16.3.0",
"@primer/react": "^35.0.0",
"@vscode/codicons": "^0.0.31",
"@vscode/webview-ui-toolkit": "^1.0.0",
"@vscode/webview-ui-toolkit": "^1.0.1",
"child-process-promise": "^2.2.1",
"classnames": "~2.2.6",
"d3": "^6.3.1",
"d3": "^7.6.1",
"d3-graphviz": "^2.6.1",
"fs-extra": "^10.0.1",
"glob-promise": "^4.2.2",
@@ -1234,11 +1234,20 @@
"zip-a-folder": "~1.1.3"
},
"devDependencies": {
"@babel/core": "^7.18.13",
"@storybook/addon-actions": "^6.5.10",
"@storybook/addon-essentials": "^6.5.10",
"@storybook/addon-interactions": "^6.5.10",
"@storybook/addon-links": "^6.5.10",
"@storybook/builder-webpack5": "^6.5.10",
"@storybook/manager-webpack5": "^6.5.10",
"@storybook/react": "^6.5.10",
"@storybook/testing-library": "^0.0.13",
"@types/chai": "^4.1.7",
"@types/chai-as-promised": "~7.1.2",
"@types/child-process-promise": "^2.2.1",
"@types/classnames": "~2.2.9",
"@types/d3": "^6.2.0",
"@types/d3": "^7.4.0",
"@types/d3-graphviz": "^2.6.6",
"@types/del": "^4.0.0",
"@types/fs-extra": "^9.0.6",
@@ -1267,17 +1276,21 @@
"@types/unzipper": "~0.10.1",
"@types/vscode": "^1.59.0",
"@types/webpack": "^5.28.0",
"@types/webpack-env": "^1.18.0",
"@types/xml2js": "~0.4.4",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"ansi-colors": "^4.1.1",
"applicationinsights": "^1.8.7",
"babel-loader": "^8.2.5",
"chai": "^4.2.0",
"chai-as-promised": "~7.1.1",
"css-loader": "~3.1.0",
"del": "^6.0.0",
"eslint": "~6.8.0",
"eslint-plugin-react": "~7.19.0",
"eslint-plugin-storybook": "^0.6.4",
"file-loader": "^6.2.0",
"glob": "^7.1.4",
"gulp": "^4.0.2",
"gulp-replace": "^1.1.3",
@@ -1285,6 +1298,7 @@
"gulp-typescript": "^5.0.1",
"husky": "~4.3.8",
"lint-staged": "~10.2.2",
"mini-css-extract-plugin": "^2.6.1",
"mocha": "^10.0.0",
"mocha-sinon": "~2.1.2",
"npm-run-all": "^4.1.5",
@@ -1292,7 +1306,6 @@
"proxyquire": "~2.1.3",
"sinon": "~13.0.1",
"sinon-chai": "~3.5.0",
"style-loader": "~3.3.1",
"through2": "^4.0.2",
"ts-loader": "^8.1.0",
"ts-node": "^10.7.0",

View File

@@ -0,0 +1,118 @@
import {
WebviewPanel,
ExtensionContext,
window as Window,
ViewColumn,
Uri,
WebviewPanelOptions,
WebviewOptions
} from 'vscode';
import * as path from 'path';
import { DisposableObject } from './pure/disposable-object';
import { tmpDir } from './helpers';
import { getHtmlForWebview, WebviewMessage, WebviewView } from './interface-utils';
export type InterfacePanelConfig = {
viewId: string;
title: string;
viewColumn: ViewColumn;
view: WebviewView;
preserveFocus?: boolean;
additionalOptions?: WebviewPanelOptions & WebviewOptions;
}
export abstract class AbstractInterfaceManager<ToMessage extends WebviewMessage, FromMessage extends WebviewMessage> extends DisposableObject {
protected panel: WebviewPanel | undefined;
protected panelLoaded = false;
protected panelLoadedCallBacks: (() => void)[] = [];
constructor(
protected readonly ctx: ExtensionContext
) {
super();
}
protected get isShowingPanel() {
return !!this.panel;
}
protected getPanel(): WebviewPanel {
if (this.panel == undefined) {
const { ctx } = this;
const config = this.getPanelConfig();
this.panel = Window.createWebviewPanel(
config.viewId,
config.title,
{ viewColumn: ViewColumn.Active, preserveFocus: true },
{
enableScripts: true,
enableFindWidget: true,
retainContextWhenHidden: true,
...config.additionalOptions,
localResourceRoots: [
...(config.additionalOptions?.localResourceRoots ?? []),
Uri.file(tmpDir.name),
Uri.file(path.join(ctx.extensionPath, 'out'))
],
}
);
this.push(
this.panel.onDidDispose(
() => {
this.panel = undefined;
this.panelLoaded = false;
this.onPanelDispose();
},
null,
ctx.subscriptions
)
);
this.panel.webview.html = getHtmlForWebview(
ctx,
this.panel.webview,
config.view,
{
allowInlineStyles: true,
}
);
this.push(
this.panel.webview.onDidReceiveMessage(
async (e) => this.onMessage(e),
undefined,
ctx.subscriptions
)
);
}
return this.panel;
}
protected abstract getPanelConfig(): InterfacePanelConfig;
protected abstract onPanelDispose(): void;
protected abstract onMessage(msg: FromMessage): Promise<void>;
protected waitForPanelLoaded(): Promise<void> {
return new Promise((resolve) => {
if (this.panelLoaded) {
resolve();
} else {
this.panelLoadedCallBacks.push(resolve);
}
});
}
protected onWebViewLoaded(): void {
this.panelLoaded = true;
this.panelLoadedCallBacks.forEach((cb) => cb());
this.panelLoadedCallBacks = [];
}
protected postMessage(msg: ToMessage): Thenable<boolean> {
return this.getPanel().webview.postMessage(msg);
}
}

View File

@@ -76,16 +76,27 @@ export class Credentials {
}));
}
async getOctokit(): Promise<Octokit.Octokit> {
/**
* Creates or returns an instance of Octokit.
*
* @param requireAuthentication Whether the Octokit instance needs to be authenticated as user.
* @returns An instance of Octokit.
*/
async getOctokit(requireAuthentication = true): Promise<Octokit.Octokit> {
if (this.octokit) {
return this.octokit;
}
this.octokit = await this.createOctokit(true);
// octokit shouldn't be undefined, since we've set "createIfNone: true".
// The following block is mainly here to prevent a compiler error.
this.octokit = await this.createOctokit(requireAuthentication);
if (!this.octokit) {
throw new Error('Did not initialize Octokit.');
if (requireAuthentication) {
throw new Error('Did not initialize Octokit.');
}
// We don't want to set this in this.octokit because that would prevent
// authenticating when requireCredentials is true.
return new Octokit.Octokit({ retry });
}
return this.octokit;
}

View File

@@ -240,7 +240,7 @@ export class CodeQLCliServer implements Disposable {
/**
* Restart the server when the current command terminates
*/
private restartCliServer(): void {
restartCliServer(): void {
const callback = (): void => {
try {
this.killProcessIfRunning();
@@ -683,7 +683,7 @@ export class CodeQLCliServer implements Disposable {
const subcommandArgs = [
'--format=text',
`--end-summary=${endSummaryPath}`,
'--sourcemap',
...(await this.cliConstraints.supportsSourceMap() ? ['--sourcemap'] : []),
inputPath,
outputPath
];
@@ -1261,9 +1261,17 @@ export class CliVersionConstraint {
/**
* CLI version where database registration was introduced
*/
*/
public static CLI_VERSION_WITH_DB_REGISTRATION = new SemVer('2.4.1');
/**
* CLI version where non destructive upgrades were introduced.
*
* This was landed in multiple parts so this is the version where all necessary feature were supported.
*/
public static CLI_VERSION_WITH_NON_DESTRUCTIVE_UPGRADES = new SemVer('2.4.2');
/**
* CLI version where the `--allow-library-packs` option to `codeql resolve queries` was
* introduced.
@@ -1322,6 +1330,11 @@ export class CliVersionConstraint {
*/
public static CLI_VERSION_WITH_PER_QUERY_EVAL_LOG = new SemVer('2.9.0');
/**
* CLI version that supports the `--sourcemap` option for log generation.
*/
public static CLI_VERSION_WITH_SOURCEMAP = new SemVer('2.10.3');
constructor(private readonly cli: CodeQLCliServer) {
/**/
}
@@ -1354,6 +1367,10 @@ export class CliVersionConstraint {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_DB_REGISTRATION);
}
async supportsNonDestructiveUpgrades(): Promise<boolean> {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_NON_DESTRUCTIVE_UPGRADES);
}
async supportsDatabaseUnbundle() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_DATABASE_UNBUNDLE);
}
@@ -1389,4 +1406,8 @@ export class CliVersionConstraint {
async supportsPerQueryEvalLog() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG);
}
async supportsSourceMap() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_SOURCEMAP);
}
}

View File

@@ -1,14 +1,8 @@
import { DisposableObject } from '../pure/disposable-object';
import {
WebviewPanel,
ExtensionContext,
window as Window,
ViewColumn,
Uri,
} from 'vscode';
import * as path from 'path';
import { tmpDir } from '../helpers';
import {
FromCompareViewMessage,
ToCompareViewMessage,
@@ -17,26 +11,24 @@ import {
import { Logger } from '../logging';
import { CodeQLCliServer } from '../cli';
import { DatabaseManager } from '../databases';
import { getHtmlForWebview, jumpToLocation } from '../interface-utils';
import { jumpToLocation } from '../interface-utils';
import { transformBqrsResultSet, RawResultSet, BQRSInfo } from '../pure/bqrs-cli-types';
import resultsDiff from './resultsDiff';
import { CompletedLocalQueryInfo } from '../query-results';
import { getErrorMessage } from '../pure/helpers-pure';
import { HistoryItemLabelProvider } from '../history-item-label-provider';
import { AbstractInterfaceManager, InterfacePanelConfig } from '../abstract-interface-manager';
interface ComparePair {
from: CompletedLocalQueryInfo;
to: CompletedLocalQueryInfo;
}
export class CompareInterfaceManager extends DisposableObject {
export class CompareInterfaceManager extends AbstractInterfaceManager<ToCompareViewMessage, FromCompareViewMessage> {
private comparePair: ComparePair | undefined;
private panel: WebviewPanel | undefined;
private panelLoaded = false;
private panelLoadedCallBacks: (() => void)[] = [];
constructor(
private ctx: ExtensionContext,
ctx: ExtensionContext,
private databaseManager: DatabaseManager,
private cliServer: CodeQLCliServer,
private logger: Logger,
@@ -45,7 +37,7 @@ export class CompareInterfaceManager extends DisposableObject {
item: CompletedLocalQueryInfo
) => Promise<void>
) {
super();
super(ctx);
}
async showResults(
@@ -103,73 +95,24 @@ export class CompareInterfaceManager extends DisposableObject {
}
}
getPanel(): WebviewPanel {
if (this.panel == undefined) {
const { ctx } = this;
const panel = (this.panel = Window.createWebviewPanel(
'compareView',
'Compare CodeQL Query Results',
{ viewColumn: ViewColumn.Active, preserveFocus: true },
{
enableScripts: true,
enableFindWidget: true,
retainContextWhenHidden: true,
localResourceRoots: [
Uri.file(tmpDir.name),
Uri.file(path.join(this.ctx.extensionPath, 'out')),
],
}
));
this.push(this.panel.onDidDispose(
() => {
this.panel = undefined;
this.comparePair = undefined;
},
null,
ctx.subscriptions
));
const scriptPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/compareView.js')
);
const stylesheetPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/view/resultsView.css')
);
panel.webview.html = getHtmlForWebview(
panel.webview,
scriptPathOnDisk,
[stylesheetPathOnDisk],
false
);
this.push(panel.webview.onDidReceiveMessage(
async (e) => this.handleMsgFromView(e),
undefined,
ctx.subscriptions
));
}
return this.panel;
protected getPanelConfig(): InterfacePanelConfig {
return {
viewId: 'compareView',
title: 'Compare CodeQL Query Results',
viewColumn: ViewColumn.Active,
preserveFocus: true,
view: 'compare',
};
}
private waitForPanelLoaded(): Promise<void> {
return new Promise((resolve) => {
if (this.panelLoaded) {
resolve();
} else {
this.panelLoadedCallBacks.push(resolve);
}
});
protected onPanelDispose(): void {
this.comparePair = undefined;
}
private async handleMsgFromView(
msg: FromCompareViewMessage
): Promise<void> {
protected async onMessage(msg: FromCompareViewMessage): Promise<void> {
switch (msg.t) {
case 'compareViewLoaded':
this.panelLoaded = true;
this.panelLoadedCallBacks.forEach((cb) => cb());
this.panelLoadedCallBacks = [];
this.onWebViewLoaded();
break;
case 'changeCompare':
@@ -186,10 +129,6 @@ export class CompareInterfaceManager extends DisposableObject {
}
}
private postMessage(msg: ToCompareViewMessage): Thenable<boolean> {
return this.getPanel().webview.postMessage(msg);
}
private async findCommonResultSetNames(
from: CompletedLocalQueryInfo,
to: CompletedLocalQueryInfo,

View File

@@ -10,6 +10,8 @@ import {
import { CodeQLCliServer } from './cli';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as Octokit from '@octokit/rest';
import { retry } from '@octokit/plugin-retry';
import { DatabaseManager, DatabaseItem } from './databases';
import {
@@ -76,7 +78,7 @@ export async function promptImportInternetDatabase(
export async function promptImportGithubDatabase(
databaseManager: DatabaseManager,
storagePath: string,
credentials: Credentials,
credentials: Credentials | undefined,
progress: ProgressCallback,
token: CancellationToken,
cli?: CodeQLCliServer
@@ -99,14 +101,15 @@ export async function promptImportGithubDatabase(
throw new Error(`Invalid GitHub repository: ${githubRepo}`);
}
const result = await convertGithubNwoToDatabaseUrl(githubRepo, credentials, progress);
const octokit = credentials ? await credentials.getOctokit(true) : new Octokit.Octokit({ retry });
const result = await convertGithubNwoToDatabaseUrl(githubRepo, octokit, progress);
if (!result) {
return;
}
const { databaseUrl, name, owner } = result;
const octokit = await credentials.getOctokit();
/**
* The 'token' property of the token object returned by `octokit.auth()`.
* The object is undocumented, but looks something like this:
@@ -118,14 +121,9 @@ export async function promptImportGithubDatabase(
* We only need the actual token string.
*/
const octokitToken = (await octokit.auth() as { token: string })?.token;
if (!octokitToken) {
// Just print a generic error message for now. Ideally we could show more debugging info, like the
// octokit object, but that would expose a user token.
throw new Error('Unable to get GitHub token.');
}
const item = await databaseArchiveFetcher(
databaseUrl,
{ 'Accept': 'application/zip', 'Authorization': `Bearer ${octokitToken}` },
{ 'Accept': 'application/zip', 'Authorization': octokitToken ? `Bearer ${octokitToken}` : '' },
databaseManager,
storagePath,
`${owner}/${name}`,
@@ -523,7 +521,7 @@ function convertGitHubUrlToNwo(githubUrl: string): string | undefined {
export async function convertGithubNwoToDatabaseUrl(
githubRepo: string,
credentials: Credentials,
octokit: Octokit.Octokit,
progress: ProgressCallback): Promise<{
databaseUrl: string,
owner: string,
@@ -533,7 +531,6 @@ export async function convertGithubNwoToDatabaseUrl(
const nwo = convertGitHubUrlToNwo(githubRepo) || githubRepo;
const [owner, repo] = nwo.split('/');
const octokit = await credentials.getOctokit();
const response = await octokit.request('GET /repos/:owner/:repo/code-scanning/codeql/databases', { owner, repo });
const languages = response.data.map((db: any) => db.language);

View File

@@ -40,6 +40,7 @@ import {
import { CancellationToken } from 'vscode';
import { asyncFilter, getErrorMessage } from './pure/helpers-pure';
import { Credentials } from './authentication';
import { isCanary } from './config';
type ThemableIconPath = { light: string; dark: string } | string;
@@ -301,7 +302,7 @@ export class DatabaseUI extends DisposableObject {
progress: ProgressCallback,
token: CancellationToken
) => {
const credentials = await this.getCredentials();
const credentials = isCanary() ? await this.getCredentials() : undefined;
await this.handleChooseDatabaseGithub(credentials, progress, token);
},
{
@@ -480,7 +481,7 @@ export class DatabaseUI extends DisposableObject {
};
handleChooseDatabaseGithub = async (
credentials: Credentials,
credentials: Credentials | undefined,
progress: ProgressCallback,
token: CancellationToken
): Promise<DatabaseItem | undefined> => {

View File

@@ -782,7 +782,7 @@ async function activateWithInstalledDistribution(
});
}
if (queryUris.length > 1) {
if (queryUris.length > 1 && !await cliServer.cliConstraints.supportsNonDestructiveUpgrades()) {
// Try to upgrade the current database before running any queries
// so that the user isn't confronted with multiple upgrade
// requests for each query to run.
@@ -938,6 +938,8 @@ async function activateWithInstalledDistribution(
progress: ProgressCallback,
token: CancellationToken
) => {
// We restart the CLI server too, to ensure they are the same version
cliServer.restartCliServer();
await qs.restartQueryServer(progress, token);
void showAndLogInformationMessage('CodeQL Query Server restarted.', {
outputLogger: queryServerLogger,
@@ -970,7 +972,7 @@ async function activateWithInstalledDistribution(
progress: ProgressCallback,
token: CancellationToken
) => {
const credentials = await Credentials.initialize(ctx);
const credentials = isCanary() ? await Credentials.initialize(ctx) : undefined;
await databaseUI.handleChooseDatabaseGithub(credentials, progress, token);
},
{

View File

@@ -4,6 +4,7 @@ import {
Uri,
Location,
Range,
ExtensionContext,
WebviewPanel,
Webview,
workspace,
@@ -111,16 +112,36 @@ export function tryResolveLocation(
}
}
export type WebviewView = 'results' | 'compare' | 'remote-queries';
export interface WebviewMessage {
t: string;
}
/**
* Returns HTML to populate the given webview.
* Uses a content security policy that only loads the given script.
*/
export function getHtmlForWebview(
ctx: ExtensionContext,
webview: Webview,
scriptUriOnDisk: Uri,
stylesheetUrisOnDisk: Uri[],
allowInlineStyles: boolean
view: WebviewView,
{
allowInlineStyles,
}: {
allowInlineStyles?: boolean;
} = {
allowInlineStyles: false,
}
): string {
const scriptUriOnDisk = Uri.file(
ctx.asAbsolutePath('out/webview.js')
);
const stylesheetUrisOnDisk = [
Uri.file(ctx.asAbsolutePath('out/webview.css'))
];
// Convert the on-disk URIs into webview URIs.
const scriptWebviewUri = webview.asWebviewUri(scriptUriOnDisk);
const stylesheetWebviewUris = stylesheetUrisOnDisk.map(stylesheetUriOnDisk =>
@@ -155,7 +176,7 @@ export function getHtmlForWebview(
${stylesheetsHtmlLines.join(` ${os.EOL}`)}
</head>
<body>
<div id=root>
<div id=root data-view="${view}">
</div>
<script nonce="${nonce}" src="${scriptWebviewUri}">
</script>

View File

@@ -1,6 +1,4 @@
import * as path from 'path';
import * as Sarif from 'sarif';
import { DisposableObject } from './pure/disposable-object';
import * as vscode from 'vscode';
import {
Diagnostic,
@@ -14,7 +12,7 @@ import {
import * as cli from './cli';
import { CodeQLCliServer } from './cli';
import { DatabaseEventKind, DatabaseItem, DatabaseManager } from './databases';
import { showAndLogErrorMessage, tmpDir } from './helpers';
import { showAndLogErrorMessage } from './helpers';
import { assertNever, getErrorMessage, getErrorStack } from './pure/helpers-pure';
import {
FromResultsViewMsg,
@@ -40,13 +38,13 @@ import {
WebviewReveal,
fileUriToWebviewUri,
tryResolveLocation,
getHtmlForWebview,
shownLocationDecoration,
shownLocationLineDecoration,
jumpToLocation,
} from './interface-utils';
import { getDefaultResultSetName, ParsedResultSets } from './pure/interface-types';
import { RawResultSet, transformBqrsResultSet, ResultSetSchema } from './pure/bqrs-cli-types';
import { AbstractInterfaceManager, InterfacePanelConfig } from './abstract-interface-manager';
import { PAGE_SIZE } from './config';
import { CompletedLocalQueryInfo } from './query-results';
import { HistoryItemLabelProvider } from './history-item-label-provider';
@@ -122,12 +120,9 @@ function numInterpretedPages(interpretation: Interpretation | undefined): number
return Math.ceil(n / pageSize);
}
export class InterfaceManager extends DisposableObject {
export class InterfaceManager extends AbstractInterfaceManager<IntoResultsViewMsg, FromResultsViewMsg> {
private _displayedQuery?: CompletedLocalQueryInfo;
private _interpretation?: Interpretation;
private _panel: vscode.WebviewPanel | undefined;
private _panelLoaded = false;
private _panelLoadedCallBacks: (() => void)[] = [];
private readonly _diagnosticCollection = languages.createDiagnosticCollection(
'codeql-query-results'
@@ -140,7 +135,7 @@ export class InterfaceManager extends DisposableObject {
public logger: Logger,
private labelProvider: HistoryItemLabelProvider
) {
super();
super(ctx);
this.push(this._diagnosticCollection);
this.push(
vscode.window.onDidChangeTextEditorSelection(
@@ -165,7 +160,7 @@ export class InterfaceManager extends DisposableObject {
this.databaseManager.onDidChangeDatabaseItem(({ kind }) => {
if (kind === DatabaseEventKind.Remove) {
this._diagnosticCollection.clear();
if (this.isShowingPanel()) {
if (this.isShowingPanel) {
void this.postMessage({
t: 'untoggleShowProblems'
});
@@ -179,59 +174,81 @@ export class InterfaceManager extends DisposableObject {
await this.postMessage({ t: 'navigatePath', direction });
}
private isShowingPanel() {
return !!this._panel;
protected getPanelConfig(): InterfacePanelConfig {
return {
viewId: 'resultsView',
title: 'CodeQL Query Results',
viewColumn: this.chooseColumnForWebview(),
preserveFocus: true,
view: 'results',
};
}
// Returns the webview panel, creating it if it doesn't already
// exist.
getPanel(): vscode.WebviewPanel {
if (this._panel == undefined) {
const { ctx } = this;
const webViewColumn = this.chooseColumnForWebview();
const panel = (this._panel = Window.createWebviewPanel(
'resultsView', // internal name
'CodeQL Query Results', // user-visible name
{ viewColumn: webViewColumn, preserveFocus: true },
{
enableScripts: true,
enableFindWidget: true,
retainContextWhenHidden: true,
localResourceRoots: [
vscode.Uri.file(tmpDir.name),
vscode.Uri.file(path.join(this.ctx.extensionPath, 'out'))
]
}
));
protected onPanelDispose(): void {
this._displayedQuery = undefined;
}
this.push(this._panel.onDidDispose(
() => {
this._panel = undefined;
this._displayedQuery = undefined;
this._panelLoaded = false;
},
null,
ctx.subscriptions
));
const scriptPathOnDisk = vscode.Uri.file(
ctx.asAbsolutePath('out/resultsView.js')
);
const stylesheetPathOnDisk = vscode.Uri.file(
ctx.asAbsolutePath('out/view/resultsView.css')
);
panel.webview.html = getHtmlForWebview(
panel.webview,
scriptPathOnDisk,
[stylesheetPathOnDisk],
false
);
this.push(panel.webview.onDidReceiveMessage(
async (e) => this.handleMsgFromView(e),
undefined,
ctx.subscriptions
));
protected async onMessage(msg: FromResultsViewMsg): Promise<void> {
try {
switch (msg.t) {
case 'resultViewLoaded':
this.onWebViewLoaded();
break;
case 'viewSourceFile': {
await jumpToLocation(msg, this.databaseManager, this.logger);
break;
}
case 'toggleDiagnostics': {
if (msg.visible) {
const databaseItem = this.databaseManager.findDatabaseItem(
Uri.parse(msg.databaseUri)
);
if (databaseItem !== undefined) {
await this.showResultsAsDiagnostics(
msg.origResultsPaths,
msg.metadata,
databaseItem
);
}
} else {
// TODO: Only clear diagnostics on the same database.
this._diagnosticCollection.clear();
}
break;
}
case 'changeSort':
await this.changeRawSortState(msg.resultSetName, msg.sortState);
break;
case 'changeInterpretedSort':
await this.changeInterpretedSortState(msg.sortState);
break;
case 'changePage':
if (msg.selectedTable === ALERTS_TABLE_NAME || msg.selectedTable === GRAPH_TABLE_NAME) {
await this.showPageOfInterpretedResults(msg.pageNumber);
}
else {
await this.showPageOfRawResults(
msg.selectedTable,
msg.pageNumber,
// When we are in an unsorted state, we guarantee that
// sortedResultsInfo doesn't have an entry for the current
// result set. Use this to determine whether or not we use
// the sorted bqrs file.
!!this._displayedQuery?.completedQuery.sortedResultsInfo[msg.selectedTable]
);
}
break;
case 'openFile':
await this.openFile(msg.filePath);
break;
default:
assertNever(msg);
}
} catch (e) {
void showAndLogErrorMessage(getErrorMessage(e), {
fullMessage: getErrorStack(e)
});
}
return this._panel;
}
/**
@@ -296,85 +313,6 @@ export class InterfaceManager extends DisposableObject {
await this.showPageOfRawResults(resultSetName, 0, true);
}
private async handleMsgFromView(msg: FromResultsViewMsg): Promise<void> {
try {
switch (msg.t) {
case 'viewSourceFile': {
await jumpToLocation(msg, this.databaseManager, this.logger);
break;
}
case 'toggleDiagnostics': {
if (msg.visible) {
const databaseItem = this.databaseManager.findDatabaseItem(
Uri.parse(msg.databaseUri)
);
if (databaseItem !== undefined) {
await this.showResultsAsDiagnostics(
msg.origResultsPaths,
msg.metadata,
databaseItem
);
}
} else {
// TODO: Only clear diagnostics on the same database.
this._diagnosticCollection.clear();
}
break;
}
case 'resultViewLoaded':
this._panelLoaded = true;
this._panelLoadedCallBacks.forEach((cb) => cb());
this._panelLoadedCallBacks = [];
break;
case 'changeSort':
await this.changeRawSortState(msg.resultSetName, msg.sortState);
break;
case 'changeInterpretedSort':
await this.changeInterpretedSortState(msg.sortState);
break;
case 'changePage':
if (msg.selectedTable === ALERTS_TABLE_NAME || msg.selectedTable === GRAPH_TABLE_NAME) {
await this.showPageOfInterpretedResults(msg.pageNumber);
}
else {
await this.showPageOfRawResults(
msg.selectedTable,
msg.pageNumber,
// When we are in an unsorted state, we guarantee that
// sortedResultsInfo doesn't have an entry for the current
// result set. Use this to determine whether or not we use
// the sorted bqrs file.
!!this._displayedQuery?.completedQuery.sortedResultsInfo[msg.selectedTable]
);
}
break;
case 'openFile':
await this.openFile(msg.filePath);
break;
default:
assertNever(msg);
}
} catch (e) {
void showAndLogErrorMessage(getErrorMessage(e), {
fullMessage: getErrorStack(e)
});
}
}
postMessage(msg: IntoResultsViewMsg): Thenable<boolean> {
return this.getPanel().webview.postMessage(msg);
}
private waitForPanelLoaded(): Promise<void> {
return new Promise((resolve) => {
if (this._panelLoaded) {
resolve();
} else {
this._panelLoadedCallBacks.push(resolve);
}
});
}
/**
* Show query results in webview panel.
* @param fullQuery Evaluation info for the executed query.

View File

@@ -189,7 +189,7 @@ export class HistoryTreeDataProvider extends DisposableObject implements TreeDat
break;
case QueryStatus.Failed:
treeItem.iconPath = this.failedIconPath;
treeItem.contextValue = 'cancelledResultsItem';
treeItem.contextValue = element.t === 'local' ? 'cancelledResultsItem' : 'cancelledRemoteResultsItem';
break;
default:
assertNever(element.status);

View File

@@ -10,6 +10,8 @@ import { RemoteQuery } from './remote-query';
import { RemoteQueryFailureIndexItem, RemoteQueryResultIndex, RemoteQuerySuccessIndexItem } from './remote-query-result-index';
import { getErrorMessage } from '../pure/helpers-pure';
export const RESULT_INDEX_ARTIFACT_NAME = 'result-index';
interface ApiSuccessIndexItem {
nwo: string;
id: string;
@@ -44,7 +46,7 @@ export async function getRemoteQueryIndex(
const artifactsUrlPath = `/repos/${owner}/${repoName}/actions/artifacts`;
const artifactList = await listWorkflowRunArtifacts(credentials, owner, repoName, workflowRunId);
const resultIndexArtifactId = tryGetArtifactIDfromName('result-index', artifactList);
const resultIndexArtifactId = tryGetArtifactIDfromName(RESULT_INDEX_ARTIFACT_NAME, artifactList);
if (!resultIndexArtifactId) {
return undefined;
}
@@ -116,6 +118,27 @@ export async function downloadArtifactFromLink(
return path.join(extractedPath, downloadLink.innerFilePath || '');
}
/**
* Checks whether a specific artifact is present in the list of artifacts of a workflow run.
* @param credentials Credentials for authenticating to the GitHub API.
* @param owner
* @param repo
* @param workflowRunId The ID of the workflow run to get the artifact for.
* @param artifactName The artifact name, as a string.
* @returns A boolean indicating if the artifact is available.
*/
export async function isArtifactAvailable(
credentials: Credentials,
owner: string,
repo: string,
workflowRunId: number,
artifactName: string,
): Promise<boolean> {
const artifactList = await listWorkflowRunArtifacts(credentials, owner, repo, workflowRunId);
return tryGetArtifactIDfromName(artifactName, artifactList) !== undefined;
}
/**
* Downloads the result index artifact and extracts the result index items.
* @param credentials Credentials for authenticating to the GitHub API.

View File

@@ -1,11 +1,10 @@
import {
WebviewPanel,
ExtensionContext,
window as Window,
ViewColumn,
Uri,
workspace,
commands
commands,
} from 'vscode';
import * as path from 'path';
@@ -16,7 +15,6 @@ import {
RemoteQueryDownloadAllAnalysesResultsMessage
} from '../pure/interface-types';
import { Logger } from '../logging';
import { getHtmlForWebview } from '../interface-utils';
import { assertNever } from '../pure/helpers-pure';
import {
AnalysisSummary,
@@ -34,18 +32,17 @@ import { SHOW_QUERY_TEXT_MSG } from '../query-history';
import { AnalysesResultsManager } from './analyses-results-manager';
import { AnalysisResults } from './shared/analysis-result';
import { humanizeUnit } from '../pure/time';
import { AbstractInterfaceManager, InterfacePanelConfig } from '../abstract-interface-manager';
export class RemoteQueriesInterfaceManager {
private panel: WebviewPanel | undefined;
private panelLoaded = false;
export class RemoteQueriesInterfaceManager extends AbstractInterfaceManager<ToRemoteQueriesMessage, FromRemoteQueriesMessage> {
private currentQueryId: string | undefined;
private panelLoadedCallBacks: (() => void)[] = [];
constructor(
private readonly ctx: ExtensionContext,
ctx: ExtensionContext,
private readonly logger: Logger,
private readonly analysesResultsManager: AnalysesResultsManager
) {
super(ctx);
this.panelLoadedCallBacks.push(() => {
void logger.log('Variant analysis results view loaded');
});
@@ -103,111 +100,29 @@ export class RemoteQueriesInterfaceManager {
};
}
getPanel(): WebviewPanel {
if (this.panel == undefined) {
const { ctx } = this;
const panel = (this.panel = Window.createWebviewPanel(
'remoteQueriesView',
'CodeQL Query Results',
{ viewColumn: ViewColumn.Active, preserveFocus: true },
{
enableScripts: true,
enableFindWidget: true,
retainContextWhenHidden: true,
localResourceRoots: [
Uri.file(this.analysesResultsManager.storagePath),
Uri.file(path.join(this.ctx.extensionPath, 'out')),
Uri.file(path.join(this.ctx.extensionPath, 'node_modules/@vscode/codicons/dist')),
],
}
));
this.panel.onDidDispose(
() => {
this.panel = undefined;
this.currentQueryId = undefined;
},
null,
ctx.subscriptions
);
const scriptPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/remoteQueriesView.js')
);
const baseStylesheetUriOnDisk = Uri.file(
ctx.asAbsolutePath('out/remote-queries/view/baseStyles.css')
);
const stylesheetPathOnDisk = Uri.file(
ctx.asAbsolutePath('out/remote-queries/view/remoteQueries.css')
);
// Allows use of the VS Code "codicons" icon set.
// See https://github.com/microsoft/vscode-codicons
const codiconsPathOnDisk = Uri.file(
ctx.asAbsolutePath('node_modules/@vscode/codicons/dist/codicon.css')
);
panel.webview.html = getHtmlForWebview(
panel.webview,
scriptPathOnDisk,
[baseStylesheetUriOnDisk, stylesheetPathOnDisk, codiconsPathOnDisk],
true
);
ctx.subscriptions.push(
panel.webview.onDidReceiveMessage(
async (e) => this.handleMsgFromView(e),
undefined,
ctx.subscriptions
)
);
}
return this.panel;
}
private waitForPanelLoaded(): Promise<void> {
return new Promise((resolve) => {
if (this.panelLoaded) {
resolve();
} else {
this.panelLoadedCallBacks.push(resolve);
protected getPanelConfig(): InterfacePanelConfig {
return {
viewId: 'remoteQueriesView',
title: 'CodeQL Query Results',
viewColumn: ViewColumn.Active,
preserveFocus: true,
view: 'remote-queries',
additionalOptions: {
localResourceRoots: [
Uri.file(this.analysesResultsManager.storagePath)
]
}
});
};
}
private async openFile(filePath: string) {
try {
const textDocument = await workspace.openTextDocument(filePath);
await Window.showTextDocument(textDocument, ViewColumn.One);
} catch (error) {
void showAndLogWarningMessage(`Could not open file: ${filePath}`);
}
protected onPanelDispose(): void {
this.currentQueryId = undefined;
}
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> {
protected async onMessage(msg: FromRemoteQueriesMessage): Promise<void> {
switch (msg.t) {
case 'remoteQueryLoaded':
this.panelLoaded = true;
this.panelLoadedCallBacks.forEach((cb) => cb());
this.panelLoadedCallBacks = [];
this.onWebViewLoaded();
break;
case 'remoteQueryError':
void this.logger.log(
@@ -237,6 +152,31 @@ export class RemoteQueriesInterfaceManager {
}
}
private async openFile(filePath: string) {
try {
const textDocument = await workspace.openTextDocument(filePath);
await Window.showTextDocument(textDocument, ViewColumn.One);
} catch (error) {
void showAndLogWarningMessage(`Could not open file: ${filePath}`);
}
}
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 downloadAnalysisResults(msg: RemoteQueryDownloadAnalysisResultsMessage): Promise<void> {
const queryId = this.currentQueryId;
await this.analysesResultsManager.downloadAnalysisResults(
@@ -261,10 +201,6 @@ export class RemoteQueriesInterfaceManager {
}
}
private postMessage(msg: ToRemoteQueriesMessage): Thenable<boolean> {
return this.getPanel().webview.postMessage(msg);
}
private getDuration(startTime: number, endTime: number): string {
const diffInMs = startTime - endTime;
return humanizeUnit(diffInMs);

View File

@@ -75,6 +75,8 @@ export class RemoteQueriesManager extends DisposableObject {
this.onRemoteQueryAdded = this.remoteQueryAddedEventEmitter.event;
this.onRemoteQueryRemoved = this.remoteQueryRemovedEventEmitter.event;
this.onRemoteQueryStatusUpdate = this.remoteQueryStatusUpdateEventEmitter.event;
this.push(this.interfaceManager);
}
public async rehydrateRemoteQuery(queryId: string, query: RemoteQuery, status: QueryStatus) {
@@ -125,7 +127,7 @@ export class RemoteQueriesManager extends DisposableObject {
if (querySubmission?.query) {
const query = querySubmission.query;
const queryId = this.createQueryId(query.queryName);
const queryId = this.createQueryId();
await this.prepareStorageDirectory(queryId);
await this.storeJsonFile(queryId, 'query.json', query);
@@ -262,11 +264,10 @@ export class RemoteQueriesManager extends DisposableObject {
/**
* Generates a unique id for this query, suitable for determining the storage location for the downloaded query artifacts.
* @param queryName
* @returns
* @returns A unique id for this query.
*/
private createQueryId(queryName: string): string {
return `${queryName}-${nanoid()}`;
private createQueryId(): string {
return nanoid();
}
/**

View File

@@ -1,7 +1,7 @@
import * as vscode from 'vscode';
import { Credentials } from '../authentication';
import { Logger } from '../logging';
import { getWorkflowStatus } from './gh-actions-api-client';
import { getWorkflowStatus, isArtifactAvailable, RESULT_INDEX_ARTIFACT_NAME } from './gh-actions-api-client';
import { RemoteQuery } from './remote-query';
import { RemoteQueryWorkflowResult } from './remote-query-workflow-result';
@@ -42,7 +42,25 @@ export class RemoteQueriesMonitor {
remoteQuery.controllerRepository.name,
remoteQuery.actionsWorkflowRunId);
if (workflowStatus.status !== 'InProgress') {
// Even if the workflow indicates it has completed, artifacts
// might still take a while to become available. So we need to
// check for the artifact before we can declare the workflow
// as having completed.
if (workflowStatus.status === 'CompletedSuccessfully') {
const resultIndexAvailable = await isArtifactAvailable(
credentials,
remoteQuery.controllerRepository.owner,
remoteQuery.controllerRepository.name,
remoteQuery.actionsWorkflowRunId,
RESULT_INDEX_ARTIFACT_NAME
);
if (resultIndexAvailable) {
return workflowStatus;
}
// We don't have a result-index yet, so we'll keep monitoring.
} else if (workflowStatus.status !== 'InProgress') {
return workflowStatus;
}

View File

@@ -217,7 +217,7 @@ export async function runRemoteQuery(
if (!controllerRepo || !REPO_REGEX.test(controllerRepo)) {
void logger.log(controllerRepo ? 'Invalid controller repository name.' : 'No controller repository defined.');
controllerRepo = await window.showInputBox({
title: 'Controller repository in which to display progress and results of variant analysis',
title: 'Controller repository in which to run the GitHub Actions workflow for this variant analysis',
placeHolder: '<owner>/<repo>',
prompt: 'Enter the name of a GitHub repository in the format <owner>/<repo>',
ignoreFocusOut: true,

View File

@@ -1,13 +0,0 @@
module.exports = {
env: {
browser: true
},
extends: [
"plugin:react/recommended"
],
settings: {
react: {
version: 'detect'
}
}
}

View File

@@ -1,18 +0,0 @@
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"target": "es6",
"outDir": "out",
"lib": ["ES2021", "dom"],
"jsx": "react",
"sourceMap": true,
"rootDir": "..",
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true
},
"exclude": ["node_modules"]
}

View File

@@ -32,11 +32,11 @@ import * as messages from './pure/messages';
import { InitialQueryInfo, LocalQueryInfo } from './query-results';
import * as qsClient from './queryserver-client';
import { isQuickQueryPath } from './quick-query';
import { compileDatabaseUpgradeSequence, hasNondestructiveUpgradeCapabilities, upgradeDatabaseExplicit } from './upgrades';
import { compileDatabaseUpgradeSequence, upgradeDatabaseExplicit } from './upgrades';
import { ensureMetadataIsComplete } from './query-results';
import { SELECT_QUERY_NAME } from './contextual/locationFinder';
import { DecodedBqrsChunk } from './pure/bqrs-cli-types';
import { getErrorMessage } from './pure/helpers-pure';
import { asError, getErrorMessage } from './pure/helpers-pure';
import { generateSummarySymbolsFile } from './log-insights/summary-parser';
/**
@@ -207,7 +207,10 @@ export class QueryEvaluationInfo {
logPath: this.evalLogPath,
});
if (await this.hasEvalLog()) {
this.displayHumanReadableLogSummary(queryInfo, qs);
queryInfo.evalLogLocation = this.evalLogPath;
queryInfo.evalLogSummaryLocation = await this.generateHumanReadableLogSummary(qs);
void this.logEndSummary(queryInfo.evalLogSummaryLocation, qs); // Logged asynchrnously
if (config.isCanary()) { // Generate JSON summary for viewer.
await qs.cliServer.generateJsonLogSummary(this.evalLogPath, this.jsonEvalLogSummaryPath);
queryInfo.jsonEvalLogSummaryLocation = this.jsonEvalLogSummaryPath;
@@ -340,25 +343,40 @@ export class QueryEvaluationInfo {
}
/**
* Calls the appropriate CLI command to generate a human-readable log summary
* and logs to the Query Server console and query log file.
* Calls the appropriate CLI command to generate a human-readable log summary.
* @param qs The query server client.
* @returns The path to the log summary, or `undefined` if the summary could not be generated.
*/
displayHumanReadableLogSummary(queryInfo: LocalQueryInfo, qs: qsClient.QueryServerClient): void {
queryInfo.evalLogLocation = this.evalLogPath;
void qs.cliServer.generateLogSummary(this.evalLogPath, this.evalLogSummaryPath, this.evalLogEndSummaryPath)
.then(() => {
queryInfo.evalLogSummaryLocation = this.evalLogSummaryPath;
fs.readFile(this.evalLogEndSummaryPath, (err, buffer) => {
if (err) {
throw new Error(`Could not read structured evaluator log end of summary file at ${this.evalLogEndSummaryPath}.`);
}
void qs.logger.log(' --- Evaluator Log Summary --- ', { additionalLogLocation: this.logPath });
void qs.logger.log(buffer.toString(), { additionalLogLocation: this.logPath });
});
})
.catch(err => {
void showAndLogWarningMessage(`Failed to generate human-readable structured evaluator log summary. Reason: ${err.message}`);
});
private async generateHumanReadableLogSummary(qs: qsClient.QueryServerClient): Promise<string | undefined> {
try {
await qs.cliServer.generateLogSummary(this.evalLogPath, this.evalLogSummaryPath, this.evalLogEndSummaryPath);
return this.evalLogSummaryPath;
} catch (e) {
const err = asError(e);
void showAndLogWarningMessage(`Failed to generate human-readable structured evaluator log summary. Reason: ${err.message}`);
return undefined;
}
}
/**
* Logs the end summary to the Output window and log file.
* @param logSummaryPath Path to the human-readable log summary
* @param qs The query server client.
*/
private async logEndSummary(logSummaryPath: string | undefined, qs: qsClient.QueryServerClient): Promise<void> {
if (logSummaryPath === undefined) {
// Failed to generate the log, so we don't expect an end summary either.
return;
}
try {
const endSummaryContent = await fs.readFile(this.evalLogEndSummaryPath, 'utf-8');
void qs.logger.log(' --- Evaluator Log Summary --- ', { additionalLogLocation: this.logPath });
void qs.logger.log(endSummaryContent, { additionalLogLocation: this.logPath });
} catch (e) {
void showAndLogWarningMessage(`Could not read structured evaluator log end of summary file at ${this.evalLogEndSummaryPath}.`);
}
}
/**
@@ -844,7 +862,7 @@ export async function compileAndRunQueryAgainstDatabase(
let upgradeDir: tmp.DirectoryResult | undefined;
try {
let upgradeQlo;
if (await hasNondestructiveUpgradeCapabilities(qs)) {
if (await qs.cliServer.cliConstraints.supportsNonDestructiveUpgrades()) {
upgradeDir = await tmp.dir({ dir: upgradesTmpDir, unsafeCleanup: true });
upgradeQlo = await compileNonDestructiveUpgrade(qs, upgradeDir, query, qlProgram, dbItem, progress, token);
} else {

View File

@@ -3,7 +3,8 @@ module.exports = {
browser: true
},
extends: [
"plugin:react/recommended"
"plugin:react/recommended",
"plugin:storybook/recommended",
],
settings: {
react: {

View File

@@ -0,0 +1,55 @@
import { Canvas, Meta, Story } from '@storybook/addon-docs';
import { VSCodeButton } from '@vscode/webview-ui-toolkit/react';
import iframeImage from './images/update-css-variables-iframe.png';
import stylesImage from './images/update-css-variables-styles.png';
import bodyImage from './images/update-css-variables-body.png';
<Meta title="Overview" />
Welcome to the Storybook for **CodeQL for Visual Studio Code**! This Storybook contains stories for components and pages in the extension.
### Writing stories
To create new stories, copy an existing story in the `src/stories` directory and modify it to use your component or page. Please note that
you are not able to access any VSCode specific APIs or receive messages from VSCode so an ideal component would use generic props. The
`vscode.postMessage` API is mocked but no message will be sent.
You are able to use all VSCode CSS variables; these are injected into the Storybook preview. However, only the Dark+ theme is supported. It
is currently not possible to preview your component in another theme.
For more information about how to write stories and how to add controls, please see the
[Storybook documentation](https://storybook.js.org/docs/react/writing-stories/introduction).
### WebView UI Toolkit
As much as possible, we try to make use of the [WebView UI Toolkit](https://github.com/microsoft/vscode-webview-ui-toolkit). The Storybook
for the WebView UI Toolkit can be found [here](https://microsoft.github.io/vscode-webview-ui-toolkit/).
### Updating VSCode CSS variables
The VSCode CSS variables that are injected into the Storybook preview are defined in the `src/stories/vscode-theme.css` file. They need to be
updated manually if new variables are added to VSCode. It can also be updated if you would like to manually preview a different theme. To update
these variables, follow these steps:
1. Make sure you have selected the correct theme. If you want to use a variable which is currently not available and will be committed, please
select the **Dark+** theme. You can use **Preferences: Color Theme** in the *Command Palette* to select the theme.
2. Open a WebView in VSCode (for example the results of a query)
3. Open the *Command Palette* (Ctrl/Cmd+Shift+P)
4. Select **Developer: Open WebView Developer Tools**
5. Now, you will need to find the `<html>` element in the lowest-level `<iframe>`. See the image below:
<img src={iframeImage} />
6. Once you have selected the `<html>` element as in the image above, click on **Show All Properties (... more)** (see image below). This will
expand all CSS variables.
<img src={stylesImage} />
7. Copy all variables to the `src/stories/vscode-theme.css` file.
8. Now, select the `<body>` element which is a direct child of the `<html>` element.
9. This time, you do not need to copy the variables. Instead, copy the styles on the `<body>` element to the `src/stories/vscode-theme.css` file.
See the image below for which styles need to be copied.
<img src={bodyImage} />

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

View File

@@ -0,0 +1,50 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import AnalysisAlertResult from '../../view/remote-queries/AnalysisAlertResult';
import type { AnalysisAlert } from '../../remote-queries/shared/analysis-result';
export default {
title: 'Analysis Alert Result',
component: AnalysisAlertResult,
} as ComponentMeta<typeof AnalysisAlertResult>;
const Template: ComponentStory<typeof AnalysisAlertResult> = (args) => (
<AnalysisAlertResult {...args} />
);
export const Warning = Template.bind({});
const warningAlert: AnalysisAlert = {
message: {
tokens: [
{
t: 'text',
text: 'This is an empty block.'
}
]
},
shortDescription: 'This is an empty block.',
fileLink: {
fileLinkPrefix: 'https://github.com/expressjs/express/blob/33e8dc303af9277f8a7e4f46abfdcb5e72f6797b',
filePath: 'test/app.options.js'
},
severity: 'Warning',
codeSnippet: {
startLine: 10,
endLine: 14,
text: ' app.del(\'/\', function(){});\n app.get(\'/users\', function(req, res){});\n app.put(\'/users\', function(req, res){});\n\n request(app)\n'
},
highlightedRegion: {
startLine: 12,
startColumn: 41,
endLine: 12,
endColumn: 43
},
codeFlows: []
};
Warning.args = {
alert: warningAlert,
};

View File

@@ -0,0 +1,121 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { ThemeProvider } from '@primer/react';
import CodePaths from '../../view/remote-queries/CodePaths';
import type { CodeFlow } from '../../remote-queries/shared/analysis-result';
export default {
title: 'Code Paths',
component: CodePaths,
decorators: [
(Story) => (
<ThemeProvider colorMode="auto">
<Story />
</ThemeProvider>
)
]
} as ComponentMeta<typeof CodePaths>;
const Template: ComponentStory<typeof CodePaths> = (args) => (
<CodePaths {...args} />
);
export const PowerShell = Template.bind({});
const codeFlows: CodeFlow[] = [
{
'threadFlows': [
{
fileLink: {
fileLinkPrefix: 'https://github.com/PowerShell/PowerShell/blob/450d884668ca477c6581ce597958f021fac30bff',
filePath: 'src/System.Management.Automation/help/UpdatableHelpSystem.cs'
},
codeSnippet: {
startLine: 1260,
endLine: 1260,
text: ' string extractPath = Path.Combine(destination, entry.FullName);'
},
highlightedRegion: {
startLine: 1260,
startColumn: 72,
endLine: 1260,
endColumn: 86,
},
message: {
tokens: [
{
t: 'text',
text: 'access to property FullName : String'
}
]
}
},
{
fileLink: {
fileLinkPrefix: 'https://github.com/PowerShell/PowerShell/blob/450d884668ca477c6581ce597958f021fac30bff',
filePath: 'src/System.Management.Automation/help/UpdatableHelpSystem.cs'
},
codeSnippet: {
startLine: 1260,
endLine: 1260,
text: ' string extractPath = Path.Combine(destination, entry.FullName);'
},
highlightedRegion: {
startLine: 1260,
startColumn: 46,
endLine: 1260,
endColumn: 87,
},
message: {
tokens: [
{
t: 'text',
text: 'call to method Combine : String'
}
]
}
},
{
fileLink: {
fileLinkPrefix: 'https://github.com/PowerShell/PowerShell/blob/450d884668ca477c6581ce597958f021fac30bff',
filePath: 'src/System.Management.Automation/help/UpdatableHelpSystem.cs'
},
codeSnippet: {
startLine: 1261,
endLine: 1261,
text: ' entry.ExtractToFile(extractPath);'
},
highlightedRegion: {
startLine: 1261,
startColumn: 45,
endLine: 1261,
endColumn: 56,
},
message: {
tokens: [
{
t: 'text',
text: 'access to local variable extractPath'
}
]
}
}
]
}
];
PowerShell.args = {
codeFlows: codeFlows,
ruleDescription: 'ZipSlip vulnerability',
message: {
tokens: [
{
type: 'text',
t: 'This zip file may have a dangerous path'
}
]
},
severity: 'Warning',
};

View File

@@ -0,0 +1,27 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import DownloadButtonComponent from '../../view/remote-queries/DownloadButton';
export default {
title: 'Download Button',
component: DownloadButtonComponent,
argTypes: {
onClick: {
action: 'clicked',
table: {
disable: true,
},
},
}
} as ComponentMeta<typeof DownloadButtonComponent>;
const Template: ComponentStory<typeof DownloadButtonComponent> = (args) => (
<DownloadButtonComponent {...args} />
);
export const DownloadButton = Template.bind({});
DownloadButton.args = {
text: 'Download',
};

View File

@@ -0,0 +1,13 @@
import React from 'react';
import { ComponentMeta } from '@storybook/react';
import DownloadSpinnerComponent from '../../view/remote-queries/DownloadSpinner';
export default {
title: 'Download Spinner',
component: DownloadSpinnerComponent,
} as ComponentMeta<typeof DownloadSpinnerComponent>;
export const DownloadSpinner = <DownloadSpinnerComponent />;

View File

@@ -0,0 +1,48 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import FileCodeSnippet from '../../view/remote-queries/FileCodeSnippet';
export default {
title: 'File Code Snippet',
component: FileCodeSnippet
} as ComponentMeta<typeof FileCodeSnippet>;
const Template: ComponentStory<typeof FileCodeSnippet> = (args) => (
<FileCodeSnippet {...args} />
);
export const WithCodeSnippet = Template.bind({});
WithCodeSnippet.args = {
fileLink: {
fileLinkPrefix: 'https://github.com/PowerShell/PowerShell/blob/450d884668ca477c6581ce597958f021fac30bff',
filePath: 'src/System.Management.Automation/help/UpdatableHelpSystem.cs'
},
codeSnippet: {
startLine: 1261,
endLine: 1261,
text: ' entry.ExtractToFile(extractPath);'
},
highlightedRegion: {
startLine: 1261,
startColumn: 45,
endLine: 1261,
endColumn: 56,
},
message: {
tokens: [
{
t: 'text',
text: 'access to local variable extractPath'
}
]
},
severity: 'Warning',
};
export const WithoutCodeSnippet = Template.bind({});
WithoutCodeSnippet.args = {
...WithCodeSnippet.args,
codeSnippet: undefined,
};

View File

@@ -0,0 +1,20 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import LastUpdatedComponent from '../../view/remote-queries/LastUpdated';
export default {
title: 'Last Updated',
component: LastUpdatedComponent,
} as ComponentMeta<typeof LastUpdatedComponent>;
const Template: ComponentStory<typeof LastUpdatedComponent> = (args) => (
<LastUpdatedComponent {...args} />
);
export const LastUpdated = Template.bind({});
LastUpdated.args = {
lastUpdated: -3_600_000, // 1 hour ago
};

View File

@@ -0,0 +1,24 @@
import React, { useEffect } from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { RemoteQueries } from '../../view/remote-queries/RemoteQueries';
import remoteQueryResult from './data/remoteQueryResultMessage.json';
import analysesResults from './data/analysesResultsMessage.json';
export default {
title: 'MRVA/Remote Queries',
component: RemoteQueries
} as ComponentMeta<typeof RemoteQueries>;
const Template: ComponentStory<typeof RemoteQueries> = () => {
useEffect(() => {
window.postMessage(remoteQueryResult);
window.postMessage(analysesResults);
});
return <RemoteQueries />;
};
export const Top10JavaScript = Template.bind({});

View File

@@ -0,0 +1,25 @@
import React, { useState } from 'react';
import { ComponentMeta } from '@storybook/react';
import RepositoriesSearchComponent from '../../view/remote-queries/RepositoriesSearch';
export default {
title: 'Repositories Search',
component: RepositoriesSearchComponent,
argTypes: {
filterValue: {
control: {
disable: true,
},
},
}
} as ComponentMeta<typeof RepositoriesSearchComponent>;
export const RepositoriesSearch = () => {
const [filterValue, setFilterValue] = useState('');
return (
<RepositoriesSearchComponent filterValue={filterValue} setFilterValue={setFilterValue} />
);
};

View File

@@ -0,0 +1,34 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import StarCountComponent from '../../view/remote-queries/StarCount';
export default {
title: 'Star Count',
component: StarCountComponent,
} as ComponentMeta<typeof StarCountComponent>;
const Template: ComponentStory<typeof StarCountComponent> = (args) => (
<StarCountComponent {...args} />
);
export const LessThan1000 = Template.bind({});
LessThan1000.args = {
starCount: 100,
};
export const MoreThan1000 = Template.bind({});
MoreThan1000.args = {
starCount: 7532,
};
export const MoreThan10000 = Template.bind({});
MoreThan10000.args = {
starCount: 65287,
};
export const MoreThan100000 = Template.bind({});
MoreThan100000.args = {
starCount: 1234234,
};

View File

@@ -0,0 +1,29 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import TextButtonComponent from '../../view/remote-queries/TextButton';
export default {
title: 'Text Button',
component: TextButtonComponent,
argTypes: {
onClick: {
action: 'clicked',
table: {
disable: true,
},
},
}
} as ComponentMeta<typeof TextButtonComponent>;
const Template: ComponentStory<typeof TextButtonComponent> = (args) => (
<TextButtonComponent {...args} />
);
export const TextButton = Template.bind({});
TextButton.args = {
children: 'Show more',
size: 'x-small',
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
{
"t": "setRemoteQueryResult",
"queryResult": {
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j",
"queryTitle": "Empty block",
"queryFileName": "example.ql",
"queryFilePath": "/home/octocat/vscode-codeql-starter/codeql-custom-queries-javascript/example.ql",
"queryText": "/**\n * @name Empty block\n * @kind problem\n * @problem.severity warning\n * @id javascript/example/empty-block\n */\n\nimport javascript\n\nfrom BlockStmt b\nwhere b.getNumStmt() = 0\nselect b, \"This is an empty block.\"\n",
"language": "javascript",
"workflowRunUrl": "https://github.com/octocat/octo-repo/actions/runs/2955404400",
"totalRepositoryCount": 10,
"affectedRepositoryCount": 10,
"totalResultCount": 16338,
"executionTimestamp": "30 Aug at 0:14 pm",
"executionDuration": "1 minute",
"analysisSummaries": [
{
"nwo": "angular/angular",
"databaseSha": "a360309f31afa97c4268a94fbd6a5108362a7182",
"resultCount": 8436,
"downloadLink": {
"id": "346232925",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232925",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "5.67 MB",
"starCount": 83537,
"lastUpdated": -1066284
},
{
"nwo": "babel/babel",
"databaseSha": "0f62c58c79830cfe0afb26161e96e0e1b0482c01",
"resultCount": 5502,
"downloadLink": {
"id": "346232926",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232926",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "3.80 MB",
"starCount": 41292,
"lastUpdated": -1600284
},
{
"nwo": "facebook/react",
"databaseSha": "e25648b0a89eab6f82bea2c2a1ef90866ac82b33",
"resultCount": 1205,
"downloadLink": {
"id": "346232919",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232919",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "905.24 KB",
"starCount": 194007,
"lastUpdated": -379284
},
{
"nwo": "facebook/jest",
"databaseSha": "187566a70aa4b6aa5f74952b504bbeddb5854aef",
"resultCount": 643,
"downloadLink": {
"id": "346232921",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232921",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "441.60 KB",
"starCount": 39987,
"lastUpdated": -113284
},
{
"nwo": "facebook/create-react-app",
"databaseSha": "f34d88e30c7d8be7181f728d1abc4fd8d5cd07d3",
"resultCount": 198,
"downloadLink": {
"id": "346232928",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232928",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "132.28 KB",
"starCount": 96698,
"lastUpdated": -126284
},
{
"nwo": "vuejs/vue",
"databaseSha": "810f6d12edea47cde7f39eaf7ec3ae1b7300d40c",
"resultCount": 140,
"downloadLink": {
"id": "346232920",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232920",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "89.99 KB",
"starCount": 198970,
"lastUpdated": -167284
},
{
"nwo": "lodash/lodash",
"databaseSha": "2da024c3b4f9947a48517639de7560457cd4ec6c",
"resultCount": 108,
"downloadLink": {
"id": "346232927",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232927",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "70.43 KB",
"starCount": 54215,
"lastUpdated": -9080284
},
{
"nwo": "jquery/jquery",
"databaseSha": "d2436df36a4b2ef556907e734a90771f0dbdbcaf",
"resultCount": 67,
"downloadLink": {
"id": "346232922",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232922",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/jquery/jquery",
"fileSize": "45.07 KB",
"starCount": 56629,
"lastUpdated": -23284
},
{
"nwo": "expressjs/express",
"databaseSha": "33e8dc303af9277f8a7e4f46abfdcb5e72f6797b",
"resultCount": 26,
"downloadLink": {
"id": "346232924",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232924",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bulk-builder/bulk-builder",
"fileSize": "16.96 KB",
"starCount": 58125,
"lastUpdated": -236284
},
{
"nwo": "twbs/bootstrap",
"databaseSha": "af1bd974bba7f6e7f90c5ed3f42738bd101926cb",
"resultCount": 13,
"downloadLink": {
"id": "346232923",
"urlPath": "/repos/octocat/octo-repo/actions/artifacts/346232923",
"innerFilePath": "results.sarif",
"queryId": "Empty block-LUzMYbSaBM4Lv6YP8GQ8j"
},
"sourceLocationPrefix": "/home/runner/work/bootstrap/bootstrap",
"fileSize": "8.50 KB",
"starCount": 159230,
"lastUpdated": -1754284
}
],
"analysisFailures": []
}
}

View File

@@ -12,7 +12,9 @@
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true
"experimentalDecorators": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true
},
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,630 @@
/*
* These were copied from VSCode Dark+ theme.
*
* To update these, open a webview in VSCode, open the webview developer tools and find the
* iframe hosting the webview. The <html> element will have a style attribute that contains
* the CSS variables. Copy these to this file.
*/
:root {
--vscode-font-family: -apple-system, BlinkMacSystemFont, sans-serif;
--vscode-font-weight: normal;
--vscode-font-size: 13px;
--vscode-editor-font-family: Menlo, Monaco, "Courier New", monospace;
--vscode-editor-font-weight: normal;
--vscode-editor-font-size: 12px;
--vscode-foreground: #cccccc;
--vscode-disabledForeground: rgba(204, 204, 204, 0.5);
--vscode-errorForeground: #f48771;
--vscode-descriptionForeground: rgba(204, 204, 204, 0.7);
--vscode-icon-foreground: #c5c5c5;
--vscode-focusBorder: #007fd4;
--vscode-textSeparator-foreground: rgba(255, 255, 255, 0.18);
--vscode-textLink-foreground: #3794ff;
--vscode-textLink-activeForeground: #3794ff;
--vscode-textPreformat-foreground: #d7ba7d;
--vscode-textBlockQuote-background: rgba(127, 127, 127, 0.1);
--vscode-textBlockQuote-border: rgba(0, 122, 204, 0.5);
--vscode-textCodeBlock-background: rgba(10, 10, 10, 0.4);
--vscode-widget-shadow: rgba(0, 0, 0, 0.36);
--vscode-input-background: #3c3c3c;
--vscode-input-foreground: #cccccc;
--vscode-inputOption-activeBorder: rgba(0, 122, 204, 0);
--vscode-inputOption-hoverBackground: rgba(90, 93, 94, 0.5);
--vscode-inputOption-activeBackground: rgba(0, 127, 212, 0.4);
--vscode-inputOption-activeForeground: #ffffff;
--vscode-input-placeholderForeground: #a6a6a6;
--vscode-inputValidation-infoBackground: #063b49;
--vscode-inputValidation-infoBorder: #007acc;
--vscode-inputValidation-warningBackground: #352a05;
--vscode-inputValidation-warningBorder: #b89500;
--vscode-inputValidation-errorBackground: #5a1d1d;
--vscode-inputValidation-errorBorder: #be1100;
--vscode-dropdown-background: #3c3c3c;
--vscode-dropdown-foreground: #f0f0f0;
--vscode-dropdown-border: #3c3c3c;
--vscode-checkbox-background: #3c3c3c;
--vscode-checkbox-foreground: #f0f0f0;
--vscode-checkbox-border: #3c3c3c;
--vscode-button-foreground: #ffffff;
--vscode-button-separator: rgba(255, 255, 255, 0.4);
--vscode-button-background: #0e639c;
--vscode-button-hoverBackground: #1177bb;
--vscode-button-secondaryForeground: #ffffff;
--vscode-button-secondaryBackground: #3a3d41;
--vscode-button-secondaryHoverBackground: #45494e;
--vscode-badge-background: #4d4d4d;
--vscode-badge-foreground: #ffffff;
--vscode-scrollbar-shadow: #000000;
--vscode-scrollbarSlider-background: rgba(121, 121, 121, 0.4);
--vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
--vscode-scrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4);
--vscode-progressBar-background: #0e70c0;
--vscode-editorError-foreground: #f14c4c;
--vscode-editorWarning-foreground: #cca700;
--vscode-editorInfo-foreground: #3794ff;
--vscode-editorHint-foreground: rgba(238, 238, 238, 0.7);
--vscode-sash-hoverBorder: #007fd4;
--vscode-editor-background: #1e1e1e;
--vscode-editor-foreground: #d4d4d4;
--vscode-editorStickyScroll-background: #1e1e1e;
--vscode-editorStickyScrollHover-background: #2a2d2e;
--vscode-editorWidget-background: #252526;
--vscode-editorWidget-foreground: #cccccc;
--vscode-editorWidget-border: #454545;
--vscode-quickInput-background: #252526;
--vscode-quickInput-foreground: #cccccc;
--vscode-quickInputTitle-background: rgba(255, 255, 255, 0.1);
--vscode-pickerGroup-foreground: #3794ff;
--vscode-pickerGroup-border: #3f3f46;
--vscode-keybindingLabel-background: rgba(128, 128, 128, 0.17);
--vscode-keybindingLabel-foreground: #cccccc;
--vscode-keybindingLabel-border: rgba(51, 51, 51, 0.6);
--vscode-keybindingLabel-bottomBorder: rgba(68, 68, 68, 0.6);
--vscode-editor-selectionBackground: #264f78;
--vscode-editor-inactiveSelectionBackground: #3a3d41;
--vscode-editor-selectionHighlightBackground: rgba(173, 214, 255, 0.15);
--vscode-editor-findMatchBackground: #515c6a;
--vscode-editor-findMatchHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-editor-findRangeHighlightBackground: rgba(58, 61, 65, 0.4);
--vscode-searchEditor-findMatchBackground: rgba(234, 92, 0, 0.22);
--vscode-editor-hoverHighlightBackground: rgba(38, 79, 120, 0.25);
--vscode-editorHoverWidget-background: #252526;
--vscode-editorHoverWidget-foreground: #cccccc;
--vscode-editorHoverWidget-border: #454545;
--vscode-editorHoverWidget-statusBarBackground: #2c2c2d;
--vscode-editorLink-activeForeground: #4e94ce;
--vscode-editorInlayHint-foreground: rgba(255, 255, 255, 0.8);
--vscode-editorInlayHint-background: rgba(77, 77, 77, 0.6);
--vscode-editorInlayHint-typeForeground: rgba(255, 255, 255, 0.8);
--vscode-editorInlayHint-typeBackground: rgba(77, 77, 77, 0.6);
--vscode-editorInlayHint-parameterForeground: rgba(255, 255, 255, 0.8);
--vscode-editorInlayHint-parameterBackground: rgba(77, 77, 77, 0.6);
--vscode-editorLightBulb-foreground: #ffcc00;
--vscode-editorLightBulbAutoFix-foreground: #75beff;
--vscode-diffEditor-insertedTextBackground: rgba(156, 204, 44, 0.2);
--vscode-diffEditor-removedTextBackground: rgba(255, 0, 0, 0.4);
--vscode-diffEditor-insertedLineBackground: rgba(155, 185, 85, 0.2);
--vscode-diffEditor-removedLineBackground: rgba(255, 0, 0, 0.2);
--vscode-diffEditor-diagonalFill: rgba(204, 204, 204, 0.2);
--vscode-list-focusOutline: #007fd4;
--vscode-list-activeSelectionBackground: #04395e;
--vscode-list-activeSelectionForeground: #ffffff;
--vscode-list-activeSelectionIconForeground: #ffffff;
--vscode-list-inactiveSelectionBackground: #37373d;
--vscode-list-hoverBackground: #2a2d2e;
--vscode-list-dropBackground: #383b3d;
--vscode-list-highlightForeground: #2aaaff;
--vscode-list-focusHighlightForeground: #2aaaff;
--vscode-list-invalidItemForeground: #b89500;
--vscode-list-errorForeground: #f88070;
--vscode-list-warningForeground: #cca700;
--vscode-listFilterWidget-background: #252526;
--vscode-listFilterWidget-outline: rgba(0, 0, 0, 0);
--vscode-listFilterWidget-noMatchesOutline: #be1100;
--vscode-listFilterWidget-shadow: rgba(0, 0, 0, 0.36);
--vscode-list-filterMatchBackground: rgba(234, 92, 0, 0.33);
--vscode-tree-indentGuidesStroke: #585858;
--vscode-tree-tableColumnsBorder: rgba(204, 204, 204, 0.13);
--vscode-tree-tableOddRowsBackground: rgba(204, 204, 204, 0.04);
--vscode-list-deemphasizedForeground: #8c8c8c;
--vscode-quickInputList-focusForeground: #ffffff;
--vscode-quickInputList-focusIconForeground: #ffffff;
--vscode-quickInputList-focusBackground: #04395e;
--vscode-menu-foreground: #cccccc;
--vscode-menu-background: #303031;
--vscode-menu-selectionForeground: #ffffff;
--vscode-menu-selectionBackground: #04395e;
--vscode-menu-separatorBackground: #606060;
--vscode-toolbar-hoverBackground: rgba(90, 93, 94, 0.31);
--vscode-toolbar-activeBackground: rgba(99, 102, 103, 0.31);
--vscode-editor-snippetTabstopHighlightBackground: rgba(124, 124, 124, 0.3);
--vscode-editor-snippetFinalTabstopHighlightBorder: #525252;
--vscode-breadcrumb-foreground: rgba(204, 204, 204, 0.8);
--vscode-breadcrumb-background: #1e1e1e;
--vscode-breadcrumb-focusForeground: #e0e0e0;
--vscode-breadcrumb-activeSelectionForeground: #e0e0e0;
--vscode-breadcrumbPicker-background: #252526;
--vscode-merge-currentHeaderBackground: rgba(64, 200, 174, 0.5);
--vscode-merge-currentContentBackground: rgba(64, 200, 174, 0.2);
--vscode-merge-incomingHeaderBackground: rgba(64, 166, 255, 0.5);
--vscode-merge-incomingContentBackground: rgba(64, 166, 255, 0.2);
--vscode-merge-commonHeaderBackground: rgba(96, 96, 96, 0.4);
--vscode-merge-commonContentBackground: rgba(96, 96, 96, 0.16);
--vscode-editorOverviewRuler-currentContentForeground: rgba(
64,
200,
174,
0.5
);
--vscode-editorOverviewRuler-incomingContentForeground: rgba(
64,
166,
255,
0.5
);
--vscode-editorOverviewRuler-commonContentForeground: rgba(96, 96, 96, 0.4);
--vscode-editorOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49);
--vscode-editorOverviewRuler-selectionHighlightForeground: rgba(
160,
160,
160,
0.8
);
--vscode-minimap-findMatchHighlight: #d18616;
--vscode-minimap-selectionOccurrenceHighlight: #676767;
--vscode-minimap-selectionHighlight: #264f78;
--vscode-minimap-errorHighlight: rgba(255, 18, 18, 0.7);
--vscode-minimap-warningHighlight: #cca700;
--vscode-minimap-foregroundOpacity: #000000;
--vscode-minimapSlider-background: rgba(121, 121, 121, 0.2);
--vscode-minimapSlider-hoverBackground: rgba(100, 100, 100, 0.35);
--vscode-minimapSlider-activeBackground: rgba(191, 191, 191, 0.2);
--vscode-problemsErrorIcon-foreground: #f14c4c;
--vscode-problemsWarningIcon-foreground: #cca700;
--vscode-problemsInfoIcon-foreground: #3794ff;
--vscode-charts-foreground: #cccccc;
--vscode-charts-lines: rgba(204, 204, 204, 0.5);
--vscode-charts-red: #f14c4c;
--vscode-charts-blue: #3794ff;
--vscode-charts-yellow: #cca700;
--vscode-charts-orange: #d18616;
--vscode-charts-green: #89d185;
--vscode-charts-purple: #b180d7;
--vscode-editor-lineHighlightBorder: #282828;
--vscode-editor-rangeHighlightBackground: rgba(255, 255, 255, 0.04);
--vscode-editor-symbolHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-editorCursor-foreground: #aeafad;
--vscode-editorWhitespace-foreground: rgba(227, 228, 226, 0.16);
--vscode-editorIndentGuide-background: #404040;
--vscode-editorIndentGuide-activeBackground: #707070;
--vscode-editorLineNumber-foreground: #858585;
--vscode-editorActiveLineNumber-foreground: #c6c6c6;
--vscode-editorLineNumber-activeForeground: #c6c6c6;
--vscode-editorRuler-foreground: #5a5a5a;
--vscode-editorCodeLens-foreground: #999999;
--vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1);
--vscode-editorBracketMatch-border: #888888;
--vscode-editorOverviewRuler-border: rgba(127, 127, 127, 0.3);
--vscode-editorGutter-background: #1e1e1e;
--vscode-editorUnnecessaryCode-opacity: rgba(0, 0, 0, 0.67);
--vscode-editorGhostText-foreground: rgba(255, 255, 255, 0.34);
--vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6);
--vscode-editorOverviewRuler-errorForeground: rgba(255, 18, 18, 0.7);
--vscode-editorOverviewRuler-warningForeground: #cca700;
--vscode-editorOverviewRuler-infoForeground: #3794ff;
--vscode-editorBracketHighlight-foreground1: #ffd700;
--vscode-editorBracketHighlight-foreground2: #da70d6;
--vscode-editorBracketHighlight-foreground3: #179fff;
--vscode-editorBracketHighlight-foreground4: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-foreground5: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-foreground6: rgba(0, 0, 0, 0);
--vscode-editorBracketHighlight-unexpectedBracket\.foreground: rgba(
255,
18,
18,
0.8
);
--vscode-editorBracketPairGuide-background1: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background2: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background3: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background4: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background5: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-background6: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground1: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground2: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground3: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground4: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground5: rgba(0, 0, 0, 0);
--vscode-editorBracketPairGuide-activeBackground6: rgba(0, 0, 0, 0);
--vscode-editorUnicodeHighlight-border: #bd9b03;
--vscode-editorUnicodeHighlight-background: rgba(189, 155, 3, 0.15);
--vscode-symbolIcon-arrayForeground: #cccccc;
--vscode-symbolIcon-booleanForeground: #cccccc;
--vscode-symbolIcon-classForeground: #ee9d28;
--vscode-symbolIcon-colorForeground: #cccccc;
--vscode-symbolIcon-constantForeground: #cccccc;
--vscode-symbolIcon-constructorForeground: #b180d7;
--vscode-symbolIcon-enumeratorForeground: #ee9d28;
--vscode-symbolIcon-enumeratorMemberForeground: #75beff;
--vscode-symbolIcon-eventForeground: #ee9d28;
--vscode-symbolIcon-fieldForeground: #75beff;
--vscode-symbolIcon-fileForeground: #cccccc;
--vscode-symbolIcon-folderForeground: #cccccc;
--vscode-symbolIcon-functionForeground: #b180d7;
--vscode-symbolIcon-interfaceForeground: #75beff;
--vscode-symbolIcon-keyForeground: #cccccc;
--vscode-symbolIcon-keywordForeground: #cccccc;
--vscode-symbolIcon-methodForeground: #b180d7;
--vscode-symbolIcon-moduleForeground: #cccccc;
--vscode-symbolIcon-namespaceForeground: #cccccc;
--vscode-symbolIcon-nullForeground: #cccccc;
--vscode-symbolIcon-numberForeground: #cccccc;
--vscode-symbolIcon-objectForeground: #cccccc;
--vscode-symbolIcon-operatorForeground: #cccccc;
--vscode-symbolIcon-packageForeground: #cccccc;
--vscode-symbolIcon-propertyForeground: #cccccc;
--vscode-symbolIcon-referenceForeground: #cccccc;
--vscode-symbolIcon-snippetForeground: #cccccc;
--vscode-symbolIcon-stringForeground: #cccccc;
--vscode-symbolIcon-structForeground: #cccccc;
--vscode-symbolIcon-textForeground: #cccccc;
--vscode-symbolIcon-typeParameterForeground: #cccccc;
--vscode-symbolIcon-unitForeground: #cccccc;
--vscode-symbolIcon-variableForeground: #75beff;
--vscode-editorHoverWidget-highlightForeground: #2aaaff;
--vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0;
--vscode-editor-foldBackground: rgba(38, 79, 120, 0.3);
--vscode-editorGutter-foldingControlForeground: #c5c5c5;
--vscode-editor-linkedEditingBackground: rgba(255, 0, 0, 0.3);
--vscode-editor-wordHighlightBackground: rgba(87, 87, 87, 0.72);
--vscode-editor-wordHighlightStrongBackground: rgba(0, 73, 114, 0.72);
--vscode-editorOverviewRuler-wordHighlightForeground: rgba(
160,
160,
160,
0.8
);
--vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(
192,
160,
192,
0.8
);
--vscode-peekViewTitle-background: rgba(55, 148, 255, 0.1);
--vscode-peekViewTitleLabel-foreground: #ffffff;
--vscode-peekViewTitleDescription-foreground: rgba(204, 204, 204, 0.7);
--vscode-peekView-border: #3794ff;
--vscode-peekViewResult-background: #252526;
--vscode-peekViewResult-lineForeground: #bbbbbb;
--vscode-peekViewResult-fileForeground: #ffffff;
--vscode-peekViewResult-selectionBackground: rgba(51, 153, 255, 0.2);
--vscode-peekViewResult-selectionForeground: #ffffff;
--vscode-peekViewEditor-background: #001f33;
--vscode-peekViewEditorGutter-background: #001f33;
--vscode-peekViewResult-matchHighlightBackground: rgba(234, 92, 0, 0.3);
--vscode-peekViewEditor-matchHighlightBackground: rgba(255, 143, 0, 0.6);
--vscode-editorMarkerNavigationError-background: #f14c4c;
--vscode-editorMarkerNavigationError-headerBackground: rgba(241, 76, 76, 0.1);
--vscode-editorMarkerNavigationWarning-background: #cca700;
--vscode-editorMarkerNavigationWarning-headerBackground: rgba(
204,
167,
0,
0.1
);
--vscode-editorMarkerNavigationInfo-background: #3794ff;
--vscode-editorMarkerNavigationInfo-headerBackground: rgba(55, 148, 255, 0.1);
--vscode-editorMarkerNavigation-background: #1e1e1e;
--vscode-editorSuggestWidget-background: #252526;
--vscode-editorSuggestWidget-border: #454545;
--vscode-editorSuggestWidget-foreground: #d4d4d4;
--vscode-editorSuggestWidget-selectedForeground: #ffffff;
--vscode-editorSuggestWidget-selectedIconForeground: #ffffff;
--vscode-editorSuggestWidget-selectedBackground: #04395e;
--vscode-editorSuggestWidget-highlightForeground: #2aaaff;
--vscode-editorSuggestWidget-focusHighlightForeground: #2aaaff;
--vscode-editorSuggestWidgetStatus-foreground: rgba(212, 212, 212, 0.5);
--vscode-tab-activeBackground: #1e1e1e;
--vscode-tab-unfocusedActiveBackground: #1e1e1e;
--vscode-tab-inactiveBackground: #2d2d2d;
--vscode-tab-unfocusedInactiveBackground: #2d2d2d;
--vscode-tab-activeForeground: #ffffff;
--vscode-tab-inactiveForeground: rgba(255, 255, 255, 0.5);
--vscode-tab-unfocusedActiveForeground: rgba(255, 255, 255, 0.5);
--vscode-tab-unfocusedInactiveForeground: rgba(255, 255, 255, 0.25);
--vscode-tab-border: #252526;
--vscode-tab-lastPinnedBorder: rgba(204, 204, 204, 0.2);
--vscode-tab-activeModifiedBorder: #3399cc;
--vscode-tab-inactiveModifiedBorder: rgba(51, 153, 204, 0.5);
--vscode-tab-unfocusedActiveModifiedBorder: rgba(51, 153, 204, 0.5);
--vscode-tab-unfocusedInactiveModifiedBorder: rgba(51, 153, 204, 0.25);
--vscode-editorPane-background: #1e1e1e;
--vscode-editorGroupHeader-tabsBackground: #252526;
--vscode-editorGroupHeader-noTabsBackground: #1e1e1e;
--vscode-editorGroup-border: #444444;
--vscode-editorGroup-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-editorGroup-dropIntoPromptForeground: #cccccc;
--vscode-editorGroup-dropIntoPromptBackground: #252526;
--vscode-sideBySideEditor-horizontalBorder: #444444;
--vscode-sideBySideEditor-verticalBorder: #444444;
--vscode-panel-background: #1e1e1e;
--vscode-panel-border: rgba(128, 128, 128, 0.35);
--vscode-panelTitle-activeForeground: #e7e7e7;
--vscode-panelTitle-inactiveForeground: rgba(231, 231, 231, 0.6);
--vscode-panelTitle-activeBorder: #e7e7e7;
--vscode-panel-dropBorder: #e7e7e7;
--vscode-panelSection-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-panelSectionHeader-background: rgba(128, 128, 128, 0.2);
--vscode-panelSection-border: rgba(128, 128, 128, 0.35);
--vscode-banner-background: #04395e;
--vscode-banner-foreground: #ffffff;
--vscode-banner-iconForeground: #3794ff;
--vscode-statusBar-foreground: #ffffff;
--vscode-statusBar-noFolderForeground: #ffffff;
--vscode-statusBar-background: #007acc;
--vscode-statusBar-noFolderBackground: #68217a;
--vscode-statusBar-focusBorder: #ffffff;
--vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18);
--vscode-statusBarItem-focusBorder: #ffffff;
--vscode-statusBarItem-hoverBackground: rgba(255, 255, 255, 0.12);
--vscode-statusBarItem-compactHoverBackground: rgba(255, 255, 255, 0.2);
--vscode-statusBarItem-prominentForeground: #ffffff;
--vscode-statusBarItem-prominentBackground: rgba(0, 0, 0, 0.5);
--vscode-statusBarItem-prominentHoverBackground: rgba(0, 0, 0, 0.3);
--vscode-statusBarItem-errorBackground: #c72e0f;
--vscode-statusBarItem-errorForeground: #ffffff;
--vscode-statusBarItem-warningBackground: #7a6400;
--vscode-statusBarItem-warningForeground: #ffffff;
--vscode-activityBar-background: #333333;
--vscode-activityBar-foreground: #ffffff;
--vscode-activityBar-inactiveForeground: rgba(255, 255, 255, 0.4);
--vscode-activityBar-activeBorder: #ffffff;
--vscode-activityBar-dropBorder: #ffffff;
--vscode-activityBarBadge-background: #007acc;
--vscode-activityBarBadge-foreground: #ffffff;
--vscode-statusBarItem-remoteBackground: #16825d;
--vscode-statusBarItem-remoteForeground: #ffffff;
--vscode-extensionBadge-remoteBackground: #007acc;
--vscode-extensionBadge-remoteForeground: #ffffff;
--vscode-sideBar-background: #252526;
--vscode-sideBarTitle-foreground: #bbbbbb;
--vscode-sideBar-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-sideBarSectionHeader-background: rgba(0, 0, 0, 0);
--vscode-sideBarSectionHeader-border: rgba(204, 204, 204, 0.2);
--vscode-titleBar-activeForeground: #cccccc;
--vscode-titleBar-inactiveForeground: rgba(204, 204, 204, 0.6);
--vscode-titleBar-activeBackground: #3c3c3c;
--vscode-titleBar-inactiveBackground: rgba(60, 60, 60, 0.6);
--vscode-menubar-selectionForeground: #cccccc;
--vscode-menubar-selectionBackground: rgba(90, 93, 94, 0.31);
--vscode-notifications-foreground: #cccccc;
--vscode-notifications-background: #252526;
--vscode-notificationLink-foreground: #3794ff;
--vscode-notificationCenterHeader-background: #303031;
--vscode-notifications-border: #303031;
--vscode-notificationsErrorIcon-foreground: #f14c4c;
--vscode-notificationsWarningIcon-foreground: #cca700;
--vscode-notificationsInfoIcon-foreground: #3794ff;
--vscode-commandCenter-foreground: #cccccc;
--vscode-commandCenter-activeForeground: #cccccc;
--vscode-commandCenter-activeBackground: rgba(90, 93, 94, 0.31);
--vscode-commandCenter-border: rgba(128, 128, 128, 0.35);
--vscode-editorCommentsWidget-resolvedBorder: rgba(204, 204, 204, 0.5);
--vscode-editorCommentsWidget-unresolvedBorder: #3794ff;
--vscode-editorCommentsWidget-rangeBackground: rgba(55, 148, 255, 0.1);
--vscode-editorCommentsWidget-rangeBorder: rgba(55, 148, 255, 0.4);
--vscode-editorCommentsWidget-rangeActiveBackground: rgba(55, 148, 255, 0.1);
--vscode-editorCommentsWidget-rangeActiveBorder: rgba(55, 148, 255, 0.4);
--vscode-editorGutter-commentRangeForeground: #37373d;
--vscode-debugToolBar-background: #333333;
--vscode-debugIcon-startForeground: #89d185;
--vscode-editor-stackFrameHighlightBackground: rgba(255, 255, 0, 0.2);
--vscode-editor-focusedStackFrameHighlightBackground: rgba(
122,
189,
122,
0.3
);
--vscode-mergeEditor-change\.background: rgba(155, 185, 85, 0.2);
--vscode-mergeEditor-change\.word\.background: rgba(156, 204, 44, 0.2);
--vscode-mergeEditor-conflict\.unhandledUnfocused\.border: rgba(
255,
166,
0,
0.48
);
--vscode-mergeEditor-conflict\.unhandledFocused\.border: #ffa600;
--vscode-mergeEditor-conflict\.handledUnfocused\.border: rgba(
134,
134,
134,
0.29
);
--vscode-mergeEditor-conflict\.handledFocused\.border: rgba(
193,
193,
193,
0.8
);
--vscode-mergeEditor-conflict\.handled\.minimapOverViewRuler: rgba(
173,
172,
168,
0.93
);
--vscode-mergeEditor-conflict\.unhandled\.minimapOverViewRuler: #fcba03;
--vscode-mergeEditor-conflictingLines\.background: rgba(255, 234, 0, 0.28);
--vscode-settings-headerForeground: #e7e7e7;
--vscode-settings-modifiedItemIndicator: #0c7d9d;
--vscode-settings-headerBorder: rgba(128, 128, 128, 0.35);
--vscode-settings-sashBorder: rgba(128, 128, 128, 0.35);
--vscode-settings-dropdownBackground: #3c3c3c;
--vscode-settings-dropdownForeground: #f0f0f0;
--vscode-settings-dropdownBorder: #3c3c3c;
--vscode-settings-dropdownListBorder: #454545;
--vscode-settings-checkboxBackground: #3c3c3c;
--vscode-settings-checkboxForeground: #f0f0f0;
--vscode-settings-checkboxBorder: #3c3c3c;
--vscode-settings-textInputBackground: #3c3c3c;
--vscode-settings-textInputForeground: #cccccc;
--vscode-settings-numberInputBackground: #3c3c3c;
--vscode-settings-numberInputForeground: #cccccc;
--vscode-settings-focusedRowBackground: rgba(42, 45, 46, 0.6);
--vscode-settings-rowHoverBackground: rgba(42, 45, 46, 0.3);
--vscode-settings-focusedRowBorder: rgba(255, 255, 255, 0.12);
--vscode-terminal-foreground: #cccccc;
--vscode-terminal-selectionBackground: #264f78;
--vscode-terminal-inactiveSelectionBackground: #3a3d41;
--vscode-terminalCommandDecoration-defaultBackground: rgba(
255,
255,
255,
0.25
);
--vscode-terminalCommandDecoration-successBackground: #1b81a8;
--vscode-terminalCommandDecoration-errorBackground: #f14c4c;
--vscode-terminalOverviewRuler-cursorForeground: rgba(160, 160, 160, 0.8);
--vscode-terminal-border: rgba(128, 128, 128, 0.35);
--vscode-terminal-findMatchBackground: #515c6a;
--vscode-terminal-findMatchHighlightBackground: rgba(234, 92, 0, 0.33);
--vscode-terminalOverviewRuler-findMatchForeground: rgba(209, 134, 22, 0.49);
--vscode-terminal-dropBackground: rgba(83, 89, 93, 0.5);
--vscode-testing-iconFailed: #f14c4c;
--vscode-testing-iconErrored: #f14c4c;
--vscode-testing-iconPassed: #73c991;
--vscode-testing-runAction: #73c991;
--vscode-testing-iconQueued: #cca700;
--vscode-testing-iconUnset: #848484;
--vscode-testing-iconSkipped: #848484;
--vscode-testing-peekBorder: #f14c4c;
--vscode-testing-peekHeaderBackground: rgba(241, 76, 76, 0.1);
--vscode-testing-message\.error\.decorationForeground: #f14c4c;
--vscode-testing-message\.error\.lineBackground: rgba(255, 0, 0, 0.2);
--vscode-testing-message\.info\.decorationForeground: rgba(
212,
212,
212,
0.5
);
--vscode-welcomePage-tileBackground: #252526;
--vscode-welcomePage-tileHoverBackground: #2c2c2d;
--vscode-welcomePage-tileShadow: rgba(0, 0, 0, 0.36);
--vscode-welcomePage-progress\.background: #3c3c3c;
--vscode-welcomePage-progress\.foreground: #3794ff;
--vscode-debugExceptionWidget-border: #a31515;
--vscode-debugExceptionWidget-background: #420b0d;
--vscode-ports-iconRunningProcessForeground: #369432;
--vscode-statusBar-debuggingBackground: #cc6633;
--vscode-statusBar-debuggingForeground: #ffffff;
--vscode-editor-inlineValuesForeground: rgba(255, 255, 255, 0.5);
--vscode-editor-inlineValuesBackground: rgba(255, 200, 0, 0.2);
--vscode-editorGutter-modifiedBackground: #1b81a8;
--vscode-editorGutter-addedBackground: #487e02;
--vscode-editorGutter-deletedBackground: #f14c4c;
--vscode-minimapGutter-modifiedBackground: #1b81a8;
--vscode-minimapGutter-addedBackground: #487e02;
--vscode-minimapGutter-deletedBackground: #f14c4c;
--vscode-editorOverviewRuler-modifiedForeground: rgba(27, 129, 168, 0.6);
--vscode-editorOverviewRuler-addedForeground: rgba(72, 126, 2, 0.6);
--vscode-editorOverviewRuler-deletedForeground: rgba(241, 76, 76, 0.6);
--vscode-debugIcon-breakpointForeground: #e51400;
--vscode-debugIcon-breakpointDisabledForeground: #848484;
--vscode-debugIcon-breakpointUnverifiedForeground: #848484;
--vscode-debugIcon-breakpointCurrentStackframeForeground: #ffcc00;
--vscode-debugIcon-breakpointStackframeForeground: #89d185;
--vscode-notebook-cellBorderColor: #37373d;
--vscode-notebook-focusedEditorBorder: #007fd4;
--vscode-notebookStatusSuccessIcon-foreground: #89d185;
--vscode-notebookStatusErrorIcon-foreground: #f48771;
--vscode-notebookStatusRunningIcon-foreground: #cccccc;
--vscode-notebook-cellToolbarSeparator: rgba(128, 128, 128, 0.35);
--vscode-notebook-selectedCellBackground: #37373d;
--vscode-notebook-selectedCellBorder: #37373d;
--vscode-notebook-focusedCellBorder: #007fd4;
--vscode-notebook-inactiveFocusedCellBorder: #37373d;
--vscode-notebook-cellStatusBarItemHoverBackground: rgba(255, 255, 255, 0.15);
--vscode-notebook-cellInsertionIndicator: #007fd4;
--vscode-notebookScrollbarSlider-background: rgba(121, 121, 121, 0.4);
--vscode-notebookScrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
--vscode-notebookScrollbarSlider-activeBackground: rgba(191, 191, 191, 0.4);
--vscode-notebook-symbolHighlightBackground: rgba(255, 255, 255, 0.04);
--vscode-notebook-cellEditorBackground: #252526;
--vscode-notebook-editorBackground: #1e1e1e;
--vscode-keybindingTable-headerBackground: rgba(204, 204, 204, 0.04);
--vscode-keybindingTable-rowsBackground: rgba(204, 204, 204, 0.04);
--vscode-scm-providerBorder: #454545;
--vscode-debugTokenExpression-name: #c586c0;
--vscode-debugTokenExpression-value: rgba(204, 204, 204, 0.6);
--vscode-debugTokenExpression-string: #ce9178;
--vscode-debugTokenExpression-boolean: #4e94ce;
--vscode-debugTokenExpression-number: #b5cea8;
--vscode-debugTokenExpression-error: #f48771;
--vscode-debugView-exceptionLabelForeground: #cccccc;
--vscode-debugView-exceptionLabelBackground: #6c2022;
--vscode-debugView-stateLabelForeground: #cccccc;
--vscode-debugView-stateLabelBackground: rgba(136, 136, 136, 0.27);
--vscode-debugView-valueChangedHighlight: #569cd6;
--vscode-debugConsole-infoForeground: #3794ff;
--vscode-debugConsole-warningForeground: #cca700;
--vscode-debugConsole-errorForeground: #f48771;
--vscode-debugConsole-sourceForeground: #cccccc;
--vscode-debugConsoleInputIcon-foreground: #cccccc;
--vscode-debugIcon-pauseForeground: #75beff;
--vscode-debugIcon-stopForeground: #f48771;
--vscode-debugIcon-disconnectForeground: #f48771;
--vscode-debugIcon-restartForeground: #89d185;
--vscode-debugIcon-stepOverForeground: #75beff;
--vscode-debugIcon-stepIntoForeground: #75beff;
--vscode-debugIcon-stepOutForeground: #75beff;
--vscode-debugIcon-continueForeground: #75beff;
--vscode-debugIcon-stepBackForeground: #75beff;
--vscode-extensionButton-prominentBackground: #0e639c;
--vscode-extensionButton-prominentForeground: #ffffff;
--vscode-extensionButton-prominentHoverBackground: #1177bb;
--vscode-extensionIcon-starForeground: #ff8e00;
--vscode-extensionIcon-verifiedForeground: #3794ff;
--vscode-extensionIcon-preReleaseForeground: #1d9271;
--vscode-extensionIcon-sponsorForeground: #d758b3;
--vscode-terminal-ansiBlack: #000000;
--vscode-terminal-ansiRed: #cd3131;
--vscode-terminal-ansiGreen: #0dbc79;
--vscode-terminal-ansiYellow: #e5e510;
--vscode-terminal-ansiBlue: #2472c8;
--vscode-terminal-ansiMagenta: #bc3fbc;
--vscode-terminal-ansiCyan: #11a8cd;
--vscode-terminal-ansiWhite: #e5e5e5;
--vscode-terminal-ansiBrightBlack: #666666;
--vscode-terminal-ansiBrightRed: #f14c4c;
--vscode-terminal-ansiBrightGreen: #23d18b;
--vscode-terminal-ansiBrightYellow: #f5f543;
--vscode-terminal-ansiBrightBlue: #3b8eea;
--vscode-terminal-ansiBrightMagenta: #d670d6;
--vscode-terminal-ansiBrightCyan: #29b8db;
--vscode-terminal-ansiBrightWhite: #e5e5e5;
--vscode-interactive-activeCodeBorder: #3794ff;
--vscode-interactive-inactiveCodeBorder: #37373d;
--vscode-gitDecoration-addedResourceForeground: #81b88b;
--vscode-gitDecoration-modifiedResourceForeground: #e2c08d;
--vscode-gitDecoration-deletedResourceForeground: #c74e39;
--vscode-gitDecoration-renamedResourceForeground: #73c991;
--vscode-gitDecoration-untrackedResourceForeground: #73c991;
--vscode-gitDecoration-ignoredResourceForeground: #8c8c8c;
--vscode-gitDecoration-stageModifiedResourceForeground: #e2c08d;
--vscode-gitDecoration-stageDeletedResourceForeground: #c74e39;
--vscode-gitDecoration-conflictingResourceForeground: #e4676b;
--vscode-gitDecoration-submoduleResourceForeground: #8db9e2;
--vscode-testExplorer-errorDecorationBackground: #5a1d1d;
}
/**
* This is copied in the same way, but from the <body> element
*/
body {
background-color: transparent;
color: var(--vscode-editor-foreground);
font-family: var(--vscode-font-family);
font-weight: var(--vscode-font-weight);
font-size: var(--vscode-font-size);
margin: 0;
padding: 0 20px;
}

View File

@@ -6,7 +6,6 @@ import * as messages from './pure/messages';
import * as qsClient from './queryserver-client';
import * as tmp from 'tmp-promise';
import * as path from 'path';
import * as semver from 'semver';
import { DatabaseItem } from './databases';
/**
@@ -16,16 +15,6 @@ import { DatabaseItem } from './databases';
*/
const MAX_UPGRADE_MESSAGE_LINES = 10;
/**
* Check that we support non-destructive upgrades.
*
* This requires 3 features. The ability to compile an upgrade sequence; The ability to
* run a non-destructive upgrades as a query; the ability to specify a target when
* resolving upgrades. We check for a version of codeql that has all three features.
*/
export async function hasNondestructiveUpgradeCapabilities(qs: qsClient.QueryServerClient): Promise<boolean> {
return semver.gte(await qs.cliServer.getVersion(), '2.4.2');
}
/**
@@ -43,7 +32,7 @@ export async function compileDatabaseUpgradeSequence(
if (dbItem.contents === undefined || dbItem.contents.dbSchemeUri === undefined) {
throw new Error('Database is invalid, and cannot be upgraded.');
}
if (!await hasNondestructiveUpgradeCapabilities(qs)) {
if (!await qs.cliServer.cliConstraints.supportsNonDestructiveUpgrades()) {
throw new Error('The version of codeql is too old to run non-destructive upgrades.');
}
// If possible just compile the upgrade sequence

View File

@@ -1,15 +1,16 @@
import * as React from 'react';
import { useState, useEffect } from 'react';
import * as Rdom from 'react-dom';
import {
ToCompareViewMessage,
SetComparisonsMessage,
} from '../../pure/interface-types';
import CompareSelector from './CompareSelector';
import { vscode } from '../../view/vscode-api';
import { vscode } from '../vscode-api';
import CompareTable from './CompareTable';
import '../results/resultsView.css';
const emptyComparison: SetComparisonsMessage = {
t: 'setComparisons',
stats: {},
@@ -75,10 +76,3 @@ export function Compare(_: Record<string, never>): JSX.Element {
return <div>Error!</div>;
}
}
Rdom.render(
<Compare />,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: 'compareViewLoaded' })
);

View File

@@ -1,11 +1,11 @@
import * as React from 'react';
import { SetComparisonsMessage } from '../../pure/interface-types';
import RawTableHeader from '../../view/RawTableHeader';
import { className } from '../../view/result-table-utils';
import RawTableHeader from '../results/RawTableHeader';
import { className } from '../results/result-table-utils';
import { ResultRow } from '../../pure/bqrs-cli-types';
import RawTableRow from '../../view/RawTableRow';
import { vscode } from '../../view/vscode-api';
import RawTableRow from '../results/RawTableRow';
import { vscode } from '../vscode-api';
interface Props {
comparison: SetComparisonsMessage;

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { Compare } from './Compare';
const definition: WebviewDefinition = {
component: <Compare />,
loadedMessage: 'compareViewLoaded'
};
export default definition;

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { AnalysisAlert } from '../shared/analysis-result';
import { AnalysisAlert } from '../../remote-queries/shared/analysis-result';
import CodePaths from './CodePaths';
import FileCodeSnippet from './FileCodeSnippet';

View File

@@ -4,7 +4,7 @@ import { VSCodeDropdown, VSCodeLink, VSCodeOption, VSCodeTag } from '@vscode/web
import * as React from 'react';
import { ChangeEvent, useRef, useState } from 'react';
import styled from 'styled-components';
import { CodeFlow, AnalysisMessage, ResultSeverity } from '../shared/analysis-result';
import { CodeFlow, AnalysisMessage, ResultSeverity } from '../../remote-queries/shared/analysis-result';
import FileCodeSnippet from './FileCodeSnippet';
import SectionTitle from './SectionTitle';
import VerticalSpace from './VerticalSpace';

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import styled from 'styled-components';
import { CodeSnippet, FileLink, HighlightedRegion, AnalysisMessage, ResultSeverity } from '../shared/analysis-result';
import { CodeSnippet, FileLink, HighlightedRegion, AnalysisMessage, ResultSeverity } from '../../remote-queries/shared/analysis-result';
import VerticalSpace from './VerticalSpace';
import { createRemoteFileRef } from '../../pure/location-link-utils';
import { parseHighlightedLine, shouldHighlightLine } from '../../pure/sarif-utils';

View File

@@ -1,18 +1,17 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import * as Rdom from 'react-dom';
import { Flash, ThemeProvider } from '@primer/react';
import { ToRemoteQueriesMessage } from '../../pure/interface-types';
import { AnalysisSummary, RemoteQueryResult } from '../shared/remote-query-result';
import { MAX_RAW_RESULTS } from '../shared/result-limits';
import { vscode } from '../../view/vscode-api';
import { AnalysisSummary, RemoteQueryResult } from '../../remote-queries/shared/remote-query-result';
import { MAX_RAW_RESULTS } from '../../remote-queries/shared/result-limits';
import { vscode } from '../vscode-api';
import { VSCodeBadge, VSCodeButton } from '@vscode/webview-ui-toolkit/react';
import SectionTitle from './SectionTitle';
import VerticalSpace from './VerticalSpace';
import HorizontalSpace from './HorizontalSpace';
import ViewTitle from './ViewTitle';
import DownloadButton from './DownloadButton';
import { AnalysisResults, getAnalysisResultCount } from '../shared/analysis-result';
import { AnalysisResults, getAnalysisResultCount } from '../../remote-queries/shared/analysis-result';
import DownloadSpinner from './DownloadSpinner';
import CollapsibleItem from './CollapsibleItem';
import { AlertIcon, CodeSquareIcon, FileCodeIcon, RepoIcon, TerminalIcon } from '@primer/octicons-react';
@@ -24,6 +23,9 @@ import SortRepoFilter, { Sort, sorter } from './SortRepoFilter';
import LastUpdated from './LastUpdated';
import RepoListCopyButton from './RepoListCopyButton';
import './baseStyles.css';
import './remoteQueries.css';
const numOfReposInContractedMode = 10;
const emptyQueryResult: RemoteQueryResult = {
@@ -440,10 +442,3 @@ export function RemoteQueries(): JSX.Element {
return <div>There was an error displaying the view.</div>;
}
}
Rdom.render(
<RemoteQueries />,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: 'remoteQueryLoaded' })
);

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import { vscode } from '../../view/vscode-api';
import { RemoteQueryResult } from '../shared/remote-query-result';
import { vscode } from '../vscode-api';
import { RemoteQueryResult } from '../../remote-queries/shared/remote-query-result';
import { CopyIcon } from '@primer/octicons-react';
import { IconButton } from '@primer/react';

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { RemoteQueries } from './RemoteQueries';
const definition: WebviewDefinition = {
component: <RemoteQueries />,
loadedMessage: 'remoteQueryLoaded'
};
export default definition;

View File

@@ -1,9 +1,9 @@
import * as React from 'react';
import { vscode } from './vscode-api';
import { RawResultsSortState, SortDirection } from '../pure/interface-types';
import { vscode } from '../vscode-api';
import { RawResultsSortState, SortDirection } from '../../pure/interface-types';
import { nextSortDirection } from './result-table-utils';
import { Column } from '../pure/bqrs-cli-types';
import { Column } from '../../pure/bqrs-cli-types';
interface Props {
readonly columns: readonly Column[];

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { ResultRow } from '../pure/bqrs-cli-types';
import { ResultRow } from '../../pure/bqrs-cli-types';
import { zebraStripe } from './result-table-utils';
import RawTableValue from './RawTableValue';

View File

@@ -1,7 +1,7 @@
import * as React from 'react';
import { renderLocation } from './result-table-utils';
import { CellValue } from '../pure/bqrs-cli-types';
import { CellValue } from '../../pure/bqrs-cli-types';
interface Props {
value: CellValue;

View File

@@ -1,19 +1,19 @@
import * as path from 'path';
import * as React from 'react';
import * as Sarif from 'sarif';
import * as Keys from '../pure/result-keys';
import * as Keys from '../../pure/result-keys';
import * as octicons from './octicons';
import { className, renderLocation, ResultTableProps, zebraStripe, selectableZebraStripe, jumpToLocation, nextSortDirection, emptyQueryResultsMessage } from './result-table-utils';
import { onNavigation, NavigationEvent } from './results';
import { InterpretedResultSet, SarifInterpretationData } from '../pure/interface-types';
import { InterpretedResultSet, SarifInterpretationData } from '../../pure/interface-types';
import {
parseSarifPlainTextMessage,
parseSarifLocation,
isNoLocation
} from '../pure/sarif-utils';
import { InterpretedResultsSortColumn, SortDirection, InterpretedResultsSortState } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { isWholeFileLoc, isLineColumnLoc } from '../pure/bqrs-utils';
} from '../../pure/sarif-utils';
import { InterpretedResultsSortColumn, SortDirection, InterpretedResultsSortState } from '../../pure/interface-types';
import { vscode } from '../vscode-api';
import { isWholeFileLoc, isLineColumnLoc } from '../../pure/bqrs-utils';
export type PathTableProps = ResultTableProps & { resultSet: InterpretedResultSet<SarifInterpretationData> };
export interface PathTableState {

View File

@@ -1,10 +1,10 @@
import * as React from 'react';
import * as d3 from 'd3';
import { ResultTableProps } from './result-table-utils';
import { InterpretedResultSet, GraphInterpretationData } from '../pure/interface-types';
import { InterpretedResultSet, GraphInterpretationData } from '../../pure/interface-types';
import { graphviz } from 'd3-graphviz';
import { jumpToLocation } from './result-table-utils';
import { tryGetLocationFromString } from '../pure/bqrs-utils';
import { tryGetLocationFromString } from '../../pure/bqrs-utils';
export type GraphProps = ResultTableProps & { resultSet: InterpretedResultSet<GraphInterpretationData> };
const graphClassName = 'vscode-codeql__result-tables-graph';

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { WebviewDefinition } from '../webview-interface';
import { ResultsApp } from './results';
const definition: WebviewDefinition = {
component: <ResultsApp />,
loadedMessage: 'resultViewLoaded'
};
export default definition;

View File

@@ -1,10 +1,10 @@
import * as React from 'react';
import { ResultTableProps, className, emptyQueryResultsMessage } from './result-table-utils';
import { RAW_RESULTS_LIMIT, RawResultsSortState } from '../pure/interface-types';
import { RawTableResultSet } from '../pure/interface-types';
import { RAW_RESULTS_LIMIT, RawResultsSortState } from '../../pure/interface-types';
import { RawTableResultSet } from '../../pure/interface-types';
import RawTableHeader from './RawTableHeader';
import RawTableRow from './RawTableRow';
import { ResultRow } from '../pure/bqrs-cli-types';
import { ResultRow } from '../../pure/bqrs-cli-types';
export type RawTableProps = ResultTableProps & {
resultSet: RawTableResultSet;

View File

@@ -1,11 +1,11 @@
import * as React from 'react';
import { UrlValue, ResolvableLocationValue } from '../pure/bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../pure/bqrs-utils';
import { RawResultsSortState, QueryMetadata, SortDirection } from '../pure/interface-types';
import { assertNever } from '../pure/helpers-pure';
import { ResultSet } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { convertNonPrintableChars } from '../text-utils';
import { UrlValue, ResolvableLocationValue } from '../../pure/bqrs-cli-types';
import { isStringLoc, tryGetResolvableLocation } from '../../pure/bqrs-utils';
import { RawResultsSortState, QueryMetadata, SortDirection } from '../../pure/interface-types';
import { assertNever } from '../../pure/helpers-pure';
import { ResultSet } from '../../pure/interface-types';
import { vscode } from '../vscode-api';
import { convertNonPrintableChars } from '../../text-utils';
export interface ResultTableProps {
resultSet: ResultSet;

View File

@@ -13,7 +13,7 @@ import {
getDefaultResultSetName,
ParsedResultSets,
IntoResultsViewMsg,
} from '../pure/interface-types';
} from '../../pure/interface-types';
import { PathTable } from './alert-table';
import { Graph } from './graph';
import { RawTable } from './raw-results-table';
@@ -25,7 +25,7 @@ import {
alertExtrasClassName,
openFile
} from './result-table-utils';
import { vscode } from './vscode-api';
import { vscode } from '../vscode-api';
const FILE_PATH_REGEX = /^(?:.+[\\/])*(.+)$/;

View File

@@ -1,6 +1,5 @@
import * as React from 'react';
import * as Rdom from 'react-dom';
import { assertNever } from '../pure/helpers-pure';
import { assertNever } from '../../pure/helpers-pure';
import {
DatabaseInfo,
Interpretation,
@@ -13,11 +12,12 @@ import {
ALERTS_TABLE_NAME,
GRAPH_TABLE_NAME,
ParsedResultSets,
} from '../pure/interface-types';
} from '../../pure/interface-types';
import { EventHandlers as EventHandlerList } from './event-handler-list';
import { ResultTables } from './result-tables';
import { ResultSet } from '../pure/interface-types';
import { vscode } from './vscode-api';
import { ResultSet } from '../../pure/interface-types';
import './resultsView.css';
/**
* results.tsx
@@ -72,7 +72,7 @@ export const onNavigation = new EventHandlerList<NavigationEvent>();
/**
* A minimal state container for displaying results.
*/
class App extends React.Component<Record<string, never>, ResultsViewState> {
export class ResultsApp extends React.Component<Record<string, never>, ResultsViewState> {
constructor(props: any) {
super(props);
this.state = {
@@ -302,7 +302,6 @@ class App extends React.Component<Record<string, never>, ResultsViewState> {
componentDidMount(): void {
this.vscodeMessageHandler = this.vscodeMessageHandler.bind(this);
window.addEventListener('message', this.vscodeMessageHandler);
vscode.postMessage({ t: 'resultViewLoaded' });
}
componentWillUnmount(): void {
@@ -319,5 +318,3 @@ class App extends React.Component<Record<string, never>, ResultsViewState> {
: console.error(`Invalid event origin ${origin}`);
}
}
Rdom.render(<App />, document.getElementById('root'));

View File

@@ -0,0 +1,4 @@
export type WebviewDefinition = {
component: JSX.Element,
loadedMessage: 'compareViewLoaded' | 'remoteQueryLoaded' | 'resultViewLoaded';
}

View File

@@ -0,0 +1,36 @@
import * as ReactDOM from 'react-dom';
import { vscode } from './vscode-api';
import { WebviewDefinition } from './webview-interface';
// Allow all views to use Codicons
import '@vscode/codicons/dist/codicon.css';
const render = () => {
const element = document.getElementById('root');
if (!element) {
console.error('Could not find element with id "root"');
return;
}
const viewName = element.dataset.view;
if (!viewName) {
console.error('Could not find view name in data-view attribute');
return;
}
// It's a lot harder to use dynamic imports since those don't import the CSS
// and require a less strict CSP policy
// eslint-disable-next-line @typescript-eslint/no-var-requires
const view: WebviewDefinition = require(`./${viewName}/index.tsx`).default;
ReactDOM.render(
view.component,
document.getElementById('root'),
// Post a message to the extension when fully loaded.
() => vscode.postMessage({ t: view.loadedMessage })
);
};
render();

View File

@@ -44,7 +44,7 @@ const _10MB = _1MB * 10;
// CLI version to test. Hard code the latest as default. And be sure
// to update the env if it is not otherwise set.
const CLI_VERSION = process.env.CLI_VERSION || 'v2.10.3';
const CLI_VERSION = process.env.CLI_VERSION || 'v2.10.4';
process.env.CLI_VERSION = CLI_VERSION;
// Base dir where CLIs will be downloaded into

View File

@@ -6,15 +6,14 @@ import { expect } from 'chai';
import { window } from 'vscode';
import {
convertGithubNwoToDatabaseUrl,
convertLgtmUrlToDatabaseUrl,
looksLikeLgtmUrl,
findDirWithFile,
looksLikeGithubRepo,
} from '../../databaseFetcher';
import { ProgressCallback } from '../../commandRunner';
import * as pq from 'proxyquire';
const proxyquire = pq.noPreserveCache();
import * as Octokit from '@octokit/rest';
describe('databaseFetcher', function() {
// These tests make API calls and may need extra time to complete.
@@ -25,20 +24,16 @@ describe('databaseFetcher', function() {
let quickPickSpy: sinon.SinonStub;
let progressSpy: ProgressCallback;
let mockRequest: sinon.SinonStub;
let mod: any;
const credentials = getMockCredentials(0);
let octokit: Octokit.Octokit;
beforeEach(() => {
sandbox = sinon.createSandbox();
quickPickSpy = sandbox.stub(window, 'showQuickPick');
progressSpy = sandbox.spy();
mockRequest = sandbox.stub();
mod = proxyquire('../../databaseFetcher', {
'./authentication': {
Credentials: credentials,
},
});
octokit = ({
request: mockRequest,
}) as unknown as Octokit.Octokit;
});
afterEach(() => {
@@ -90,11 +85,17 @@ describe('databaseFetcher', function() {
mockRequest.resolves(mockApiResponse);
quickPickSpy.resolves('javascript');
const githubRepo = 'github/codeql';
const { databaseUrl, name, owner } = await mod.convertGithubNwoToDatabaseUrl(
const result = await convertGithubNwoToDatabaseUrl(
githubRepo,
credentials,
octokit,
progressSpy
);
expect(result).not.to.be.undefined;
if (result === undefined) {
return;
}
const { databaseUrl, name, owner } = result;
expect(databaseUrl).to.equal(
'https://api.github.com/repos/github/codeql/code-scanning/codeql/databases/javascript'
@@ -119,7 +120,7 @@ describe('databaseFetcher', function() {
mockRequest.resolves(mockApiResponse);
const githubRepo = 'foo/bar-not-real';
await expect(
mod.convertGithubNwoToDatabaseUrl(githubRepo, credentials, progressSpy)
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy)
).to.be.rejectedWith(/Unable to get database/);
expect(progressSpy).to.have.callCount(0);
});
@@ -133,19 +134,10 @@ describe('databaseFetcher', function() {
mockRequest.resolves(mockApiResponse);
const githubRepo = 'foo/bar-with-no-dbs';
await expect(
mod.convertGithubNwoToDatabaseUrl(githubRepo, credentials, progressSpy)
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy)
).to.be.rejectedWith(/Unable to get database/);
expect(progressSpy).to.have.been.calledOnce;
});
function getMockCredentials(response: any) {
mockRequest = sinon.stub().resolves(response);
return {
getOctokit: () => ({
request: mockRequest,
}),
};
}
});
describe('convertLgtmUrlToDatabaseUrl', () => {

View File

@@ -564,6 +564,11 @@ repository:
keyword: 'query'
name: storage.modifier.query.ql
signature:
match:
keyword: 'signature'
name: storage.modifier.signature.ql
transient:
match:
keyword: 'transient'
@@ -583,8 +588,14 @@ repository:
- include: '#pragma'
- include: '#private'
- include: '#query'
- include: '#signature'
- include: '#transient'
implements:
match:
keyword: 'implements'
name: keyword.other.implements.ql
# A QL comment, regardless of form.
comment:
patterns:
@@ -668,6 +679,19 @@ repository:
- match: '(?#simple-id)'
name: entity.name.type.namespace.ql
# The `implements` clause of a module definition.
implements-clause:
beginPattern: '#implements'
# Ends at the first `{`.
# REVIEW: This could be any token not allowed in a type.
end: '(?= \{ )'
name: meta.block.implements-clause.ql
patterns:
- include: '#non-context-sensitive'
- match: '(?#simple-id)|(?#at-lower-id)'
name: entity.name.type.ql
# A `module` declaration, whether a module definition or an alias declaration.
module-declaration:
# Starts with the `module` keyword.
@@ -677,6 +701,7 @@ repository:
name: meta.block.module-declaration.ql
patterns:
- include: '#module-body'
- include: '#implements-clause'
- include: '#non-context-sensitive'
# Any simple-id within a module head is part of a module name.
- match: '(?#simple-id)'

File diff suppressed because it is too large Load Diff