Merge pull request #2480 from github/robertbrignull/app-environment

Add EnvironmentContext so common code can do localisation
This commit is contained in:
Robert
2023-06-06 08:44:12 +01:00
committed by GitHub
8 changed files with 57 additions and 14 deletions

View File

@@ -23,6 +23,7 @@ export interface App {
readonly onDidChangeWorkspaceFolders: Event<WorkspaceFoldersChangeEvent>; readonly onDidChangeWorkspaceFolders: Event<WorkspaceFoldersChangeEvent>;
readonly credentials: Credentials; readonly credentials: Credentials;
readonly commands: AppCommandManager; readonly commands: AppCommandManager;
readonly environment: EnvironmentContext;
} }
export enum AppMode { export enum AppMode {
@@ -30,3 +31,7 @@ export enum AppMode {
Development = 2, Development = 2,
Test = 3, Test = 3,
} }
export interface EnvironmentContext {
language: string;
}

View File

@@ -1,5 +1,5 @@
import { basename, dirname, join } from "path"; import { basename, dirname, join } from "path";
import { env } from "vscode"; import { EnvironmentContext } from "./app";
/** /**
* A node in the tree of files. This will be either a `FileTreeDirectory` or a `FileTreeLeaf`. * A node in the tree of files. This will be either a `FileTreeDirectory` or a `FileTreeLeaf`.
@@ -35,6 +35,7 @@ export class FileTreeDirectory<T = undefined> extends FileTreeNode<T> {
constructor( constructor(
_path: string, _path: string,
_name: string, _name: string,
protected readonly env: EnvironmentContext,
private _children: Array<FileTreeNode<T>> = [], private _children: Array<FileTreeNode<T>> = [],
) { ) {
super(_path, _name); super(_path, _name);
@@ -66,7 +67,9 @@ export class FileTreeDirectory<T = undefined> extends FileTreeNode<T> {
this._children.filter( this._children.filter(
(child) => child instanceof FileTreeLeaf || child.children.length > 0, (child) => child instanceof FileTreeLeaf || child.children.length > 0,
); );
this._children.sort((a, b) => a.name.localeCompare(b.name, env.language)); this._children.sort((a, b) =>
a.name.localeCompare(b.name, this.env.language),
);
this._children.forEach((child, i) => { this._children.forEach((child, i) => {
child.finish(); child.finish();
if ( if (
@@ -77,6 +80,7 @@ export class FileTreeDirectory<T = undefined> extends FileTreeNode<T> {
const replacement = new FileTreeDirectory<T>( const replacement = new FileTreeDirectory<T>(
child.children[0].path, child.children[0].path,
`${child.name} / ${child.children[0].name}`, `${child.name} / ${child.children[0].name}`,
this.env,
Array.from(child.children[0].children), Array.from(child.children[0].children),
); );
this._children[i] = replacement; this._children[i] = replacement;
@@ -89,7 +93,11 @@ export class FileTreeDirectory<T = undefined> extends FileTreeNode<T> {
if (existingChild !== undefined) { if (existingChild !== undefined) {
return existingChild as FileTreeDirectory<T>; return existingChild as FileTreeDirectory<T>;
} else { } else {
const newChild = new FileTreeDirectory<T>(join(this.path, name), name); const newChild = new FileTreeDirectory<T>(
join(this.path, name),
name,
this.env,
);
this.addChild(newChild); this.addChild(newChild);
return newChild; return newChild;
} }

View File

@@ -0,0 +1,8 @@
import { env } from "vscode";
import { EnvironmentContext } from "../app";
export class AppEnvironmentContext implements EnvironmentContext {
public get language(): string {
return env.language;
}
}

View File

@@ -1,13 +1,14 @@
import * as vscode from "vscode"; import * as vscode from "vscode";
import { VSCodeCredentials } from "./authentication"; import { VSCodeCredentials } from "./authentication";
import { Disposable } from "../../pure/disposable-object"; import { Disposable } from "../../pure/disposable-object";
import { App, AppMode } from "../app"; import { App, AppMode, EnvironmentContext } from "../app";
import { AppEventEmitter } from "../events"; import { AppEventEmitter } from "../events";
import { extLogger, Logger, queryServerLogger } from "../logging"; import { extLogger, Logger, queryServerLogger } from "../logging";
import { Memento } from "../memento"; import { Memento } from "../memento";
import { VSCodeAppEventEmitter } from "./events"; import { VSCodeAppEventEmitter } from "./events";
import { AppCommandManager, QueryServerCommandManager } from "../commands"; import { AppCommandManager, QueryServerCommandManager } from "../commands";
import { createVSCodeCommandManager } from "./commands"; import { createVSCodeCommandManager } from "./commands";
import { AppEnvironmentContext } from "./environment-context";
export class ExtensionApp implements App { export class ExtensionApp implements App {
public readonly credentials: VSCodeCredentials; public readonly credentials: VSCodeCredentials;
@@ -69,4 +70,8 @@ export class ExtensionApp implements App {
public createEventEmitter<T>(): AppEventEmitter<T> { public createEventEmitter<T>(): AppEventEmitter<T> {
return new VSCodeAppEventEmitter<T>(); return new VSCodeAppEventEmitter<T>();
} }
public get environment(): EnvironmentContext {
return new AppEnvironmentContext();
}
} }

View File

@@ -41,7 +41,10 @@ export class QueryDiscovery
new MultiFileSystemWatcher(), new MultiFileSystemWatcher(),
); );
constructor(app: App, private readonly cliServer: CodeQLCliServer) { constructor(
private readonly app: App,
private readonly cliServer: CodeQLCliServer,
) {
super("Query Discovery", extLogger); super("Query Discovery", extLogger);
this.onDidChangeQueriesEmitter = this.push(app.createEventEmitter<void>()); this.onDidChangeQueriesEmitter = this.push(app.createEventEmitter<void>());
@@ -124,7 +127,11 @@ export class QueryDiscovery
return undefined; return undefined;
} }
const rootDirectory = new FileTreeDirectory<string>(fullPath, name); const rootDirectory = new FileTreeDirectory<string>(
fullPath,
name,
this.app.environment,
);
for (const queryPath of resolvedQueries) { for (const queryPath of resolvedQueries) {
const relativePath = normalize(relative(fullPath, queryPath)); const relativePath = normalize(relative(fullPath, queryPath));
const dirName = dirname(relativePath); const dirName = dirname(relativePath);

View File

@@ -6,6 +6,7 @@ import {
Uri, Uri,
RelativePattern, RelativePattern,
WorkspaceFolder, WorkspaceFolder,
env,
} from "vscode"; } from "vscode";
import { MultiFileSystemWatcher } from "../common/vscode/multi-file-system-watcher"; import { MultiFileSystemWatcher } from "../common/vscode/multi-file-system-watcher";
import { CodeQLCliServer } from "../codeql-cli/cli"; import { CodeQLCliServer } from "../codeql-cli/cli";
@@ -97,7 +98,7 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
private async discoverTests(): Promise<FileTreeDirectory> { private async discoverTests(): Promise<FileTreeDirectory> {
const fullPath = this.workspaceFolder.uri.fsPath; const fullPath = this.workspaceFolder.uri.fsPath;
const name = this.workspaceFolder.name; const name = this.workspaceFolder.name;
const rootDirectory = new FileTreeDirectory(fullPath, name); const rootDirectory = new FileTreeDirectory(fullPath, name, env);
// Don't try discovery on workspace folders that don't exist on the filesystem // Don't try discovery on workspace folders that don't exist on the filesystem
if (await pathExists(fullPath)) { if (await pathExists(fullPath)) {

View File

@@ -1,4 +1,4 @@
import { App, AppMode } from "../../src/common/app"; import { App, AppMode, EnvironmentContext } from "../../src/common/app";
import { AppEvent, AppEventEmitter } from "../../src/common/events"; import { AppEvent, AppEventEmitter } from "../../src/common/events";
import { Memento } from "../../src/common/memento"; import { Memento } from "../../src/common/memento";
import { Disposable } from "../../src/pure/disposable-object"; import { Disposable } from "../../src/pure/disposable-object";
@@ -24,6 +24,7 @@ export function createMockApp({
onDidChangeWorkspaceFolders = jest.fn(), onDidChangeWorkspaceFolders = jest.fn(),
credentials = testCredentialsWithStub(), credentials = testCredentialsWithStub(),
commands = createMockCommandManager(), commands = createMockCommandManager(),
environment = createMockEnvironmentContext(),
}: { }: {
extensionPath?: string; extensionPath?: string;
workspaceStoragePath?: string; workspaceStoragePath?: string;
@@ -34,6 +35,7 @@ export function createMockApp({
onDidChangeWorkspaceFolders?: Event<WorkspaceFoldersChangeEvent>; onDidChangeWorkspaceFolders?: Event<WorkspaceFoldersChangeEvent>;
credentials?: Credentials; credentials?: Credentials;
commands?: AppCommandManager; commands?: AppCommandManager;
environment?: EnvironmentContext;
}): App { }): App {
return { return {
mode: AppMode.Test, mode: AppMode.Test,
@@ -48,6 +50,7 @@ export function createMockApp({
createEventEmitter, createEventEmitter,
credentials, credentials,
commands, commands,
environment,
}; };
} }
@@ -68,3 +71,9 @@ export class MockAppEventEmitter<T> implements AppEventEmitter<T> {
// no-op // no-op
} }
} }
export function createMockEnvironmentContext(): EnvironmentContext {
return {
language: "en-US",
};
}

View File

@@ -1,4 +1,4 @@
import { EventEmitter } from "vscode"; import { EventEmitter, env } from "vscode";
import { import {
FileTreeDirectory, FileTreeDirectory,
FileTreeLeaf, FileTreeLeaf,
@@ -31,8 +31,8 @@ describe("QueryTreeDataProvider", () => {
it("converts FileTreeNode to QueryTreeViewItem", async () => { it("converts FileTreeNode to QueryTreeViewItem", async () => {
const dataProvider = new QueryTreeDataProvider({ const dataProvider = new QueryTreeDataProvider({
queries: [ queries: [
new FileTreeDirectory<string>("dir1", "dir1", [ new FileTreeDirectory<string>("dir1", "dir1", env, [
new FileTreeDirectory<string>("dir1/dir2", "dir2", [ new FileTreeDirectory<string>("dir1/dir2", "dir2", env, [
new FileTreeLeaf<string>( new FileTreeLeaf<string>(
"dir1/dir2/file1", "dir1/dir2/file1",
"file1", "file1",
@@ -45,7 +45,7 @@ describe("QueryTreeDataProvider", () => {
), ),
]), ]),
]), ]),
new FileTreeDirectory<string>("dir3", "dir3", [ new FileTreeDirectory<string>("dir3", "dir3", env, [
new FileTreeLeaf<string>("dir3/file3", "file3", "javascript"), new FileTreeLeaf<string>("dir3/file3", "file3", "javascript"),
]), ]),
], ],
@@ -78,7 +78,7 @@ describe("QueryTreeDataProvider", () => {
const onDidChangeQueriesEmitter = new EventEmitter<void>(); const onDidChangeQueriesEmitter = new EventEmitter<void>();
const queryDiscoverer: QueryDiscoverer = { const queryDiscoverer: QueryDiscoverer = {
queries: [ queries: [
new FileTreeDirectory<string>("dir1", "dir1", [ new FileTreeDirectory<string>("dir1", "dir1", env, [
new FileTreeLeaf<string>("dir1/file1", "file1", "javascript"), new FileTreeLeaf<string>("dir1/file1", "file1", "javascript"),
]), ]),
], ],
@@ -89,7 +89,7 @@ describe("QueryTreeDataProvider", () => {
expect(dataProvider.getChildren().length).toEqual(1); expect(dataProvider.getChildren().length).toEqual(1);
queryDiscoverer.queries?.push( queryDiscoverer.queries?.push(
new FileTreeDirectory<string>("dir2", "dir2", [ new FileTreeDirectory<string>("dir2", "dir2", env, [
new FileTreeLeaf<string>("dir2/file2", "file2", "javascript"), new FileTreeLeaf<string>("dir2/file2", "file2", "javascript"),
]), ]),
); );