mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-31 00:10:04 +08:00
debt - reduce explicit any usage (#269814)
This commit is contained in:
10
.github/prompts/no-any.prompt.md
vendored
Normal file
10
.github/prompts/no-any.prompt.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
mode: agent
|
||||
description: 'Remove any usage of the any type in TypeScript files'
|
||||
---
|
||||
|
||||
I am trying to minimize the usage of `any` types in our TypeScript codebase.
|
||||
Find usages of the TypeScript `any` type in this file and replace it with the right type based on usages in the file.
|
||||
|
||||
You are NOT allowed to disable ESLint rules or add `// @ts-ignore` comments to the code.
|
||||
You are NOT allowed to add more `any` types to the code.
|
||||
@@ -187,6 +187,7 @@ export default tseslint.config(
|
||||
'src/vs/base/browser/ui/scrollbar/**',
|
||||
'src/vs/base/browser/ui/widget.ts',
|
||||
'src/vs/base/common/extpath.ts',
|
||||
'src/vs/base/common/fuzzyScorer.ts',
|
||||
'src/vs/base/common/glob.ts',
|
||||
'src/vs/base/common/path.ts',
|
||||
'src/vs/base/common/stream.ts',
|
||||
@@ -201,30 +202,32 @@ export default tseslint.config(
|
||||
'src/vs/base/common/uriTransformer.ts',
|
||||
'src/vs/base/common/worker/webWorker.ts',
|
||||
'src/vs/base/node/pfs.ts',
|
||||
'src/vs/base/node/unc.ts',
|
||||
'src/vs/base/parts/contextmenu/**',
|
||||
'src/vs/editor/browser/**',
|
||||
'src/vs/editor/common/**',
|
||||
// 'src/vs/base/parts/ipc/**',
|
||||
// 'src/vs/base/parts/sandbox/**',
|
||||
'src/vs/base/parts/sandbox/**',
|
||||
'src/vs/base/parts/storage/**',
|
||||
'src/vs/platform/auxiliaryWindow/**',
|
||||
// 'src/vs/platform/backup/**',
|
||||
// 'src/vs/platform/editor/**',
|
||||
// 'src/vs/platform/environment/**',
|
||||
// 'src/vs/platform/files/**',
|
||||
// 'src/vs/platform/ipc/**',
|
||||
// 'src/vs/platform/launch/**',
|
||||
// 'src/vs/platform/lifecycle/**',
|
||||
// 'src/vs/platform/menubar/**',
|
||||
// 'src/vs/platform/native/**',
|
||||
// 'src/vs/platform/sharedProcess/**',
|
||||
// 'src/vs/platform/state/**',
|
||||
// 'src/vs/platform/storage/**',
|
||||
// 'src/vs/platform/utilityProcess/**',
|
||||
// 'src/vs/platform/window/**',
|
||||
// 'src/vs/platform/windows/**',
|
||||
// 'src/vs/platform/workspace/**',
|
||||
// 'src/vs/platform/workspaces/**',
|
||||
'src/vs/platform/backup/**',
|
||||
'src/vs/platform/editor/**',
|
||||
'src/vs/platform/environment/**',
|
||||
'src/vs/platform/dialogs/**',
|
||||
'src/vs/platform/files/**',
|
||||
'src/vs/platform/ipc/**',
|
||||
'src/vs/platform/launch/**',
|
||||
'src/vs/platform/lifecycle/**',
|
||||
'src/vs/platform/menubar/**',
|
||||
'src/vs/platform/native/**',
|
||||
'src/vs/platform/sharedProcess/**',
|
||||
'src/vs/platform/state/**',
|
||||
'src/vs/platform/storage/**',
|
||||
'src/vs/platform/utilityProcess/**',
|
||||
'src/vs/platform/window/**',
|
||||
'src/vs/platform/windows/**',
|
||||
'src/vs/platform/workspace/**',
|
||||
'src/vs/platform/workspaces/**',
|
||||
'src/bootstrap-cli.ts',
|
||||
'src/bootstrap-esm.ts',
|
||||
'src/bootstrap-fork.ts',
|
||||
@@ -243,7 +246,7 @@ export default tseslint.config(
|
||||
'src/vs/workbench/services/contextmenu/**',
|
||||
'src/vs/workbench/services/dialogs/**',
|
||||
'src/vs/workbench/services/editor/**',
|
||||
// 'src/vs/workbench/services/environment/**',
|
||||
'src/vs/workbench/services/environment/**',
|
||||
'src/vs/workbench/services/files/**',
|
||||
'src/vs/workbench/services/filesConfiguration/**',
|
||||
'src/vs/workbench/services/history/**',
|
||||
@@ -254,19 +257,22 @@ export default tseslint.config(
|
||||
'src/vs/workbench/services/notification/**',
|
||||
'src/vs/workbench/services/path/**',
|
||||
'src/vs/workbench/services/progress/**',
|
||||
// 'src/vs/workbench/services/storage/**',
|
||||
// 'src/vs/workbench/services/textfile/**',
|
||||
// 'src/vs/workbench/services/textmodelResolver/**',
|
||||
// 'src/vs/workbench/services/untitled/**',
|
||||
// 'src/vs/workbench/services/utilityProcess/**',
|
||||
// 'src/vs/workbench/services/views/**',
|
||||
// 'src/vs/workbench/services/workingCopy/**',
|
||||
// 'src/vs/workbench/services/workspaces/**',
|
||||
// 'src/vs/workbench/common/**',
|
||||
'src/vs/workbench/services/storage/**',
|
||||
'src/vs/workbench/services/textfile/**',
|
||||
'src/vs/workbench/services/textmodelResolver/**',
|
||||
'src/vs/workbench/services/untitled/**',
|
||||
'src/vs/workbench/services/utilityProcess/**',
|
||||
'src/vs/workbench/services/views/**',
|
||||
'src/vs/workbench/services/workingCopy/**',
|
||||
'src/vs/workbench/services/workspaces/**',
|
||||
'src/vs/workbench/common/**',
|
||||
// 'src/vs/workbench/browser/**',
|
||||
// 'src/vs/workbench/electron-browser/**',
|
||||
// 'src/vs/workbench/contrib/files/**',
|
||||
'src/vs/workbench/electron-browser/**',
|
||||
'src/vs/workbench/contrib/files/**',
|
||||
'src/vs/workbench/contrib/chat/browser/chatSetup.ts',
|
||||
'src/vs/workbench/contrib/chat/browser/chatStatus.ts',
|
||||
],
|
||||
ignores: ['**/*.test.ts', '**/*.integrationTest.ts'],
|
||||
languageOptions: {
|
||||
parser: tseslint.parser,
|
||||
},
|
||||
|
||||
@@ -184,9 +184,9 @@ function configureCrashReporter(): void {
|
||||
const crashReporterProcessType = process.env['VSCODE_CRASH_REPORTER_PROCESS_TYPE'];
|
||||
if (crashReporterProcessType) {
|
||||
try {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error
|
||||
if (process['crashReporter'] && typeof process['crashReporter'].addExtraParameter === 'function' /* Electron only */) {
|
||||
//@ts-ignore
|
||||
//@ts-expect-error
|
||||
process['crashReporter'].addExtraParameter('processType', crashReporterProcessType);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -88,7 +88,7 @@ perf.mark('code/didStartCrashReporter');
|
||||
// to ensure that no 'logs' folder is created on disk at a
|
||||
// location outside of the portable directory
|
||||
// (https://github.com/microsoft/vscode/issues/56651)
|
||||
if (portable && portable.isPortable) {
|
||||
if (portable.isPortable) {
|
||||
app.setAppLogsPath(path.join(userDataPath, 'logs'));
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ if (shouldSpawnCli) {
|
||||
perf.mark('code/server/firstWebSocket');
|
||||
}
|
||||
const remoteExtensionHostAgentServer = await getRemoteExtensionHostAgentServer();
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
return remoteExtensionHostAgentServer.handleUpgrade(req, socket);
|
||||
});
|
||||
server.on('error', async (err) => {
|
||||
|
||||
@@ -359,14 +359,14 @@ export interface IPathWithLineAndColumn {
|
||||
export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn {
|
||||
const segments = rawPath.split(':'); // C:\file.txt:<line>:<column>
|
||||
|
||||
let path: string | undefined = undefined;
|
||||
let line: number | undefined = undefined;
|
||||
let column: number | undefined = undefined;
|
||||
let path: string | undefined;
|
||||
let line: number | undefined;
|
||||
let column: number | undefined;
|
||||
|
||||
for (const segment of segments) {
|
||||
const segmentAsNumber = Number(segment);
|
||||
if (!isNumber(segmentAsNumber)) {
|
||||
path = !!path ? [path, segment].join(':') : segment; // a colon can well be part of a path (e.g. C:\...)
|
||||
path = path ? [path, segment].join(':') : segment; // a colon can well be part of a path (e.g. C:\...)
|
||||
} else if (line === undefined) {
|
||||
line = segmentAsNumber;
|
||||
} else if (column === undefined) {
|
||||
|
||||
@@ -508,7 +508,7 @@ function toRegExp(pattern: string): ParsedStringPattern {
|
||||
|
||||
return typeof path === 'string' && regExp.test(path) ? pattern : null;
|
||||
};
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ async function rimrafMove(path: string, moveToPath = randomPath(tmpdir())): Prom
|
||||
}
|
||||
|
||||
// Delete but do not return as promise
|
||||
rimrafUnlink(moveToPath).catch(error => {/* ignore */ });
|
||||
rimrafUnlink(moveToPath).catch(() => {/* ignore */ });
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
@@ -113,7 +113,7 @@ async function readdir(path: string, options?: { withFileTypes: true }): Promise
|
||||
if (error.code === 'ENOENT' && isWindows && isRootOrDriveLetter(path)) {
|
||||
try {
|
||||
return await doReaddir(`${path}.`, options);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -268,7 +268,7 @@ export namespace SymlinkSupport {
|
||||
if (!lstats.isSymbolicLink()) {
|
||||
return { stat: lstats };
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
/* ignore - use stat() instead */
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ export namespace SymlinkSupport {
|
||||
const { stat, symbolicLink } = await SymlinkSupport.stat(path);
|
||||
|
||||
return stat.isFile() && symbolicLink?.dangling !== true;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore, path might not exist
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ export namespace SymlinkSupport {
|
||||
const { stat, symbolicLink } = await SymlinkSupport.stat(path);
|
||||
|
||||
return stat.isDirectory() && symbolicLink?.dangling !== true;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore, path might not exist
|
||||
}
|
||||
|
||||
@@ -542,7 +542,7 @@ async function renameWithRetry(source: string, target: string, startTime: number
|
||||
if (!stat.isFile()) {
|
||||
abortRetry = true; // if target is not a file, EPERM error may be raised and we should not attempt to retry
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
@@ -601,7 +601,7 @@ async function doCopy(source: string, target: string, payload: ICopyPayload): Pr
|
||||
if (payload.options.preserveSymlinks) {
|
||||
try {
|
||||
return await doCopySymlink(source, target, payload);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// in any case of an error fallback to normal copy via dereferencing
|
||||
}
|
||||
}
|
||||
@@ -713,7 +713,7 @@ export async function realcase(path: string, token?: CancellationToken): Promise
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// silently ignore error
|
||||
}
|
||||
|
||||
@@ -727,7 +727,7 @@ async function realpath(path: string): Promise<string> {
|
||||
// drives to be resolved to their target on Windows
|
||||
// https://github.com/microsoft/vscode/issues/118562
|
||||
return await promisify(fs.realpath)(path);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
|
||||
// We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization
|
||||
// we now do a similar normalization and then try again if we can access the path with read
|
||||
@@ -748,7 +748,7 @@ async function realpath(path: string): Promise<string> {
|
||||
export function realpathSync(path: string): string {
|
||||
try {
|
||||
return fs.realpathSync(path);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
|
||||
// We hit an error calling fs.realpathSync(). Since fs.realpathSync() is doing some path normalization
|
||||
// we now do a similar normalization and then try again if we can access the path with read
|
||||
|
||||
@@ -12,13 +12,12 @@ export function getUNCHostAllowlist(): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
function processUNCHostAllowlist(): Set<string> {
|
||||
function processUNCHostAllowlist(): Set<string> | undefined {
|
||||
|
||||
// The property `process.uncHostAllowlist` is not available in official node.js
|
||||
// releases, only in our own builds, so we have to probe for availability
|
||||
|
||||
// eslint-disable-next-line local/code-no-any-casts
|
||||
return (process as any).uncHostAllowlist;
|
||||
return (process as unknown as { uncHostAllowlist?: Set<string> }).uncHostAllowlist;
|
||||
}
|
||||
|
||||
export function addUNCHostToAllowlist(allowedHost: string | string[]): void {
|
||||
@@ -91,8 +90,7 @@ export function disableUNCAccessRestrictions(): void {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line local/code-no-any-casts
|
||||
(process as any).restrictUNCAccess = false;
|
||||
(process as unknown as { restrictUNCAccess?: boolean }).restrictUNCAccess = false;
|
||||
}
|
||||
|
||||
export function isUNCAccessRestrictionsDisabled(): boolean {
|
||||
@@ -100,6 +98,5 @@ export function isUNCAccessRestrictionsDisabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line local/code-no-any-casts
|
||||
return (process as any).restrictUNCAccess === false;
|
||||
return (process as unknown as { restrictUNCAccess?: boolean }).restrictUNCAccess === false;
|
||||
}
|
||||
|
||||
@@ -1107,7 +1107,7 @@ export namespace ProxyChannel {
|
||||
|
||||
export function fromService<TContext>(service: unknown, disposables: DisposableStore, options?: ICreateServiceChannelOptions): IServerChannel<TContext> {
|
||||
const handler = service as { [key: string]: unknown };
|
||||
const disableMarshalling = options && options.disableMarshalling;
|
||||
const disableMarshalling = options?.disableMarshalling;
|
||||
|
||||
// Buffer any event that should be supported by
|
||||
// iterating over all property keys and finding them
|
||||
@@ -1184,7 +1184,7 @@ export namespace ProxyChannel {
|
||||
}
|
||||
|
||||
export function toService<T extends object>(channel: IChannel, options?: ICreateProxyServiceOptions): T {
|
||||
const disableMarshalling = options && options.disableMarshalling;
|
||||
const disableMarshalling = options?.disableMarshalling;
|
||||
|
||||
return new Proxy({}, {
|
||||
get(_target: T, propKey: PropertyKey) {
|
||||
|
||||
@@ -93,7 +93,7 @@ export class Client implements IChannelClient, IDisposable {
|
||||
readonly onDidProcessExit = this._onDidProcessExit.event;
|
||||
|
||||
constructor(private modulePath: string, private options: IIPCOptions) {
|
||||
const timeout = options && options.timeout ? options.timeout : 60000;
|
||||
const timeout = options.timeout || 60000;
|
||||
this.disposeDelayer = new Delayer<void>(timeout);
|
||||
this.child = null;
|
||||
this._client = null;
|
||||
@@ -174,24 +174,24 @@ export class Client implements IChannelClient, IDisposable {
|
||||
|
||||
private get client(): IPCClient {
|
||||
if (!this._client) {
|
||||
const args = this.options && this.options.args ? this.options.args : [];
|
||||
const args = this.options.args || [];
|
||||
const forkOpts: ForkOptions = Object.create(null);
|
||||
|
||||
forkOpts.env = { ...deepClone(process.env), 'VSCODE_PARENT_PID': String(process.pid) };
|
||||
|
||||
if (this.options && this.options.env) {
|
||||
if (this.options.env) {
|
||||
forkOpts.env = { ...forkOpts.env, ...this.options.env };
|
||||
}
|
||||
|
||||
if (this.options && this.options.freshExecArgv) {
|
||||
if (this.options.freshExecArgv) {
|
||||
forkOpts.execArgv = [];
|
||||
}
|
||||
|
||||
if (this.options && typeof this.options.debug === 'number') {
|
||||
if (typeof this.options.debug === 'number') {
|
||||
forkOpts.execArgv = ['--nolazy', '--inspect=' + this.options.debug];
|
||||
}
|
||||
|
||||
if (this.options && typeof this.options.debugBrk === 'number') {
|
||||
if (typeof this.options.debugBrk === 'number') {
|
||||
forkOpts.execArgv = ['--nolazy', '--inspect-brk=' + this.options.debugBrk];
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ export class Client implements IChannelClient, IDisposable {
|
||||
});
|
||||
|
||||
const sender = this.options.useQueue ? createQueuedSender(this.child) : this.child;
|
||||
const send = (r: VSBuffer) => this.child && this.child.connected && sender.send((<Buffer>r.buffer).toString('base64'));
|
||||
const send = (r: VSBuffer) => this.child?.connected && sender.send((<Buffer>r.buffer).toString('base64'));
|
||||
const onMessage = onMessageEmitter.event;
|
||||
const protocol = { send, onMessage };
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class Protocol implements IMessagePassingProtocol {
|
||||
constructor(private port: MessagePortMain) {
|
||||
this.onMessage = Event.fromNodeEventEmitter<VSBuffer>(this.port, 'message', (e: MessageEvent) => {
|
||||
if (e.data) {
|
||||
return VSBuffer.wrap(e.data);
|
||||
return VSBuffer.wrap(e.data as Uint8Array);
|
||||
}
|
||||
return VSBuffer.alloc(0);
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ export function upgradeToISocket(req: http.IncomingMessage, socket: Socket, {
|
||||
skipWebSocketFrames?: boolean;
|
||||
disableWebSocketCompression?: boolean;
|
||||
}): NodeSocket | WebSocketNodeSocket | undefined {
|
||||
if (req.headers['upgrade'] === undefined || req.headers['upgrade'].toLowerCase() !== 'websocket') {
|
||||
if (req.headers.upgrade === undefined || req.headers.upgrade.toLowerCase() !== 'websocket') {
|
||||
socket.end('HTTP/1.1 400 Bad Request');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export interface MessagePortMain extends NodeJS.EventEmitter {
|
||||
* Sends a message from the port, and optionally, transfers ownership of objects to
|
||||
* other browsing contexts.
|
||||
*/
|
||||
postMessage(message: any, transfer?: MessagePortMain[]): void;
|
||||
postMessage(message: unknown, transfer?: MessagePortMain[]): void;
|
||||
/**
|
||||
* Starts the sending of messages queued on the port. Messages will be queued until
|
||||
* this method is called.
|
||||
@@ -40,7 +40,7 @@ export interface MessagePortMain extends NodeJS.EventEmitter {
|
||||
}
|
||||
|
||||
export interface MessageEvent {
|
||||
data: any;
|
||||
data: unknown;
|
||||
ports: MessagePortMain[];
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export interface ParentPort extends NodeJS.EventEmitter {
|
||||
/**
|
||||
* Sends a message from the process to its parent.
|
||||
*/
|
||||
postMessage(message: any): void;
|
||||
postMessage(message: unknown): void;
|
||||
}
|
||||
|
||||
export interface UtilityNodeJSProcess extends NodeJS.Process {
|
||||
|
||||
@@ -349,7 +349,7 @@ export class Storage extends Disposable implements IStorage {
|
||||
// the DB is not healthy.
|
||||
try {
|
||||
await this.doFlush(0 /* as soon as possible */);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
|
||||
}
|
||||
|
||||
// DELETE
|
||||
if (toDelete && toDelete.size) {
|
||||
if (toDelete?.size) {
|
||||
const keysChunks: (string[])[] = [];
|
||||
keysChunks.push([]); // seed with initial empty chunk
|
||||
|
||||
@@ -291,7 +291,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
|
||||
await fs.promises.unlink(path);
|
||||
try {
|
||||
await Promises.rename(this.toBackupPath(path), path, false /* no retry */);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
|
||||
@@ -474,7 +474,7 @@
|
||||
const importMapScript = document.createElement('script');
|
||||
importMapScript.type = 'importmap';
|
||||
importMapScript.setAttribute('nonce', '0c6a828f1297');
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
importMapScript.textContent = ttp?.createScript(importMapSrc) ?? importMapSrc;
|
||||
window.document.head.appendChild(importMapScript);
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ export async function main(argv: string[]): Promise<void> {
|
||||
// Check for readonly status and chmod if so if we are told so
|
||||
let targetMode: number = 0;
|
||||
let restoreMode = false;
|
||||
if (!!args['file-chmod']) {
|
||||
if (args['file-chmod']) {
|
||||
targetMode = statSync(target).mode;
|
||||
if (!(targetMode & 0o200 /* File mode indicating writable by owner */)) {
|
||||
chmodSync(target, targetMode | 0o200);
|
||||
|
||||
@@ -247,7 +247,7 @@ class CliMain extends Disposable {
|
||||
const appenders: ITelemetryAppender[] = [];
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
if (productService.aiConfig?.ariaKey) {
|
||||
appenders.push(new OneDataSystemAppender(requestService, isInternal, 'monacoworkbench', null, productService.aiConfig.ariaKey));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ export interface IFolderBackupInfo extends IBaseBackupInfo {
|
||||
}
|
||||
|
||||
export function isFolderBackupInfo(curr: IWorkspaceBackupInfo | IFolderBackupInfo): curr is IFolderBackupInfo {
|
||||
return curr && curr.hasOwnProperty('folderUri');
|
||||
return curr?.hasOwnProperty('folderUri');
|
||||
}
|
||||
|
||||
export function isWorkspaceBackupInfo(curr: IWorkspaceBackupInfo | IFolderBackupInfo): curr is IWorkspaceBackupInfo {
|
||||
return curr && curr.hasOwnProperty('workspace');
|
||||
return curr?.hasOwnProperty('workspace');
|
||||
}
|
||||
|
||||
@@ -347,11 +347,11 @@ export class BackupMainService implements IBackupMainService {
|
||||
if (backupSchemaChildren.length > 0) {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// invalid folder
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// backup path does not exist
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export function deserializeWorkspaceInfos(serializedBackupWorkspaces: ISerialize
|
||||
}
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// ignore URI parsing exceptions
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export function deserializeFolderInfos(serializedBackupWorkspaces: ISerializedBa
|
||||
}
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// ignore URI parsing exceptions
|
||||
}
|
||||
|
||||
|
||||
@@ -586,7 +586,7 @@ flakySuite('BackupMainService', () => {
|
||||
try {
|
||||
await fs.promises.mkdir(path.join(folderBackupPath, Schemas.file), { recursive: true });
|
||||
await fs.promises.mkdir(path.join(workspaceBackupPath, Schemas.untitled), { recursive: true });
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// ignore - folder might exist already
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export class TestDialogService implements IDialogService {
|
||||
|
||||
constructor(
|
||||
private defaultConfirmResult: IConfirmationResult | undefined = undefined,
|
||||
private defaultPromptResult: IPromptResult<any> | undefined = undefined
|
||||
private defaultPromptResult: IPromptResult<unknown> | undefined = undefined
|
||||
) { }
|
||||
|
||||
private confirmResult: IConfirmationResult | undefined = undefined;
|
||||
@@ -40,7 +40,7 @@ export class TestDialogService implements IDialogService {
|
||||
prompt<T>(prompt: IPrompt<T>): Promise<IPromptResult<T>>;
|
||||
async prompt<T>(prompt: IPrompt<T> | IPromptWithCustomCancel<T>): Promise<IPromptResult<T> | IPromptResultWithCancel<T>> {
|
||||
if (this.defaultPromptResult) {
|
||||
return this.defaultPromptResult;
|
||||
return this.defaultPromptResult as IPromptResult<T>;
|
||||
}
|
||||
const promptButtons: IPromptBaseButton<T>[] = [...(prompt.buttons ?? [])];
|
||||
if (prompt.cancelButton && typeof prompt.cancelButton !== 'string' && typeof prompt.cancelButton !== 'boolean') {
|
||||
|
||||
@@ -214,7 +214,7 @@ export abstract class AbstractNativeEnvironmentService implements INativeEnviron
|
||||
const result: [string, string][] = [];
|
||||
for (const entry of this.args.log || []) {
|
||||
const matches = EXTENSION_IDENTIFIER_WITH_LOG_REGEX.exec(entry);
|
||||
if (matches && matches[1] && matches[2]) {
|
||||
if (matches?.[1] && matches[2]) {
|
||||
result.push([matches[1], matches[2]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,8 +261,8 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
const alias: { [key: string]: string } = {};
|
||||
const stringOptions: string[] = ['_'];
|
||||
const booleanOptions: string[] = [];
|
||||
const globalOptions: OptionDescriptions<any> = {};
|
||||
let command: Subcommand<any> | undefined = undefined;
|
||||
const globalOptions: Record<string, Option<'boolean'> | Option<'string'> | Option<'string[]'>> = {};
|
||||
let command: Subcommand<Record<string, unknown>> | undefined = undefined;
|
||||
for (const optionId in options) {
|
||||
const o = options[optionId];
|
||||
if (o.type === 'subcommand') {
|
||||
@@ -291,13 +291,13 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
}
|
||||
}
|
||||
if (command && firstPossibleCommand) {
|
||||
const options = globalOptions;
|
||||
const options: Record<string, Option<'boolean'> | Option<'string'> | Option<'string[]'> | Subcommand<Record<string, unknown>>> = globalOptions;
|
||||
for (const optionId in command.options) {
|
||||
options[optionId] = command.options[optionId];
|
||||
}
|
||||
const newArgs = args.filter(a => a !== firstPossibleCommand);
|
||||
const reporter = errorReporter.getSubcommandReporter ? errorReporter.getSubcommandReporter(firstPossibleCommand) : undefined;
|
||||
const subcommandOptions = parseArgs(newArgs, options, reporter);
|
||||
const subcommandOptions = parseArgs(newArgs, options as OptionDescriptions<Record<string, unknown>>, reporter);
|
||||
// eslint-disable-next-line local/code-no-dangerous-type-assertions
|
||||
return <T>{
|
||||
[firstPossibleCommand]: subcommandOptions,
|
||||
@@ -309,8 +309,8 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
// remove aliases to avoid confusion
|
||||
const parsedArgs = minimist(args, { string: stringOptions, boolean: booleanOptions, alias });
|
||||
|
||||
const cleanedArgs: any = {};
|
||||
const remainingArgs: any = parsedArgs;
|
||||
const cleanedArgs: Record<string, unknown> = {};
|
||||
const remainingArgs: Record<string, unknown> = parsedArgs;
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/58177, https://github.com/microsoft/vscode/issues/106617
|
||||
cleanedArgs._ = parsedArgs._.map(arg => String(arg)).filter(arg => arg.length > 0);
|
||||
@@ -347,8 +347,8 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
val = [val];
|
||||
}
|
||||
if (!o.allowEmptyValue) {
|
||||
const sanitized = val.filter((v: string) => v.length > 0);
|
||||
if (sanitized.length !== val.length) {
|
||||
const sanitized = (val as string[]).filter((v: string) => v.length > 0);
|
||||
if (sanitized.length !== (val as string[]).length) {
|
||||
errorReporter.onEmptyValue(optionId);
|
||||
val = sanitized.length > 0 ? sanitized : undefined;
|
||||
}
|
||||
@@ -356,7 +356,7 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
} else if (o.type === 'string') {
|
||||
if (Array.isArray(val)) {
|
||||
val = val.pop(); // take the last
|
||||
errorReporter.onMultipleValues(optionId, val);
|
||||
errorReporter.onMultipleValues(optionId, val as string);
|
||||
} else if (!val && !o.allowEmptyValue) {
|
||||
errorReporter.onEmptyValue(optionId);
|
||||
val = undefined;
|
||||
@@ -375,10 +375,10 @@ export function parseArgs<T>(args: string[], options: OptionDescriptions<T>, err
|
||||
errorReporter.onUnknownOption(key);
|
||||
}
|
||||
|
||||
return cleanedArgs;
|
||||
return cleanedArgs as T;
|
||||
}
|
||||
|
||||
function formatUsage(optionId: string, option: Option<any>) {
|
||||
function formatUsage(optionId: string, option: Option<'boolean'> | Option<'string'> | Option<'string[]'>) {
|
||||
let args = '';
|
||||
if (option.args) {
|
||||
if (Array.isArray(option.args)) {
|
||||
@@ -394,10 +394,10 @@ function formatUsage(optionId: string, option: Option<any>) {
|
||||
}
|
||||
|
||||
// exported only for testing
|
||||
export function formatOptions(options: OptionDescriptions<any>, columns: number): string[] {
|
||||
export function formatOptions(options: OptionDescriptions<unknown> | Record<string, Option<'boolean'> | Option<'string'> | Option<'string[]'>>, columns: number): string[] {
|
||||
const usageTexts: [string, string][] = [];
|
||||
for (const optionId in options) {
|
||||
const o = options[optionId];
|
||||
const o = options[optionId as keyof typeof options] as Option<'boolean'> | Option<'string'> | Option<'string[]'>;
|
||||
const usageText = formatUsage(optionId, o);
|
||||
usageTexts.push([usageText, o.description!]);
|
||||
}
|
||||
@@ -443,7 +443,7 @@ function wrapText(text: string, columns: number): string[] {
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function buildHelpMessage(productName: string, executableName: string, version: string, options: OptionDescriptions<any>, capabilities?: { noPipe?: boolean; noInputFiles?: boolean; isChat?: boolean }): string {
|
||||
export function buildHelpMessage(productName: string, executableName: string, version: string, options: OptionDescriptions<unknown> | Record<string, Option<'boolean'> | Option<'string'> | Option<'string[]'> | Subcommand<Record<string, unknown>>>, capabilities?: { noPipe?: boolean; noInputFiles?: boolean; isChat?: boolean }): string {
|
||||
const columns = (process.stdout).isTTY && (process.stdout).columns || 80;
|
||||
const inputFiles = capabilities?.noInputFiles ? '' : capabilities?.isChat ? ` [${localize('cliPrompt', 'prompt')}]` : ` [${localize('paths', 'paths')}...]`;
|
||||
const subcommand = capabilities?.isChat ? ' chat' : '';
|
||||
@@ -456,18 +456,19 @@ export function buildHelpMessage(productName: string, executableName: string, ve
|
||||
help.push(buildStdinMessage(executableName, capabilities?.isChat));
|
||||
help.push('');
|
||||
}
|
||||
const optionsByCategory: { [P in keyof typeof helpCategories]?: OptionDescriptions<any> } = {};
|
||||
const optionsByCategory: { [P in keyof typeof helpCategories]?: Record<string, Option<'boolean'> | Option<'string'> | Option<'string[]'>> } = {};
|
||||
const subcommands: { command: string; description: string }[] = [];
|
||||
for (const optionId in options) {
|
||||
const o = options[optionId];
|
||||
const o = options[optionId as keyof typeof options] as Option<'boolean'> | Option<'string'> | Option<'string[]'> | Subcommand<Record<string, unknown>>;
|
||||
if (o.type === 'subcommand') {
|
||||
if (o.description) {
|
||||
subcommands.push({ command: optionId, description: o.description });
|
||||
}
|
||||
} else if (o.description && o.cat) {
|
||||
let optionsByCat = optionsByCategory[o.cat];
|
||||
const cat = o.cat as keyof typeof helpCategories;
|
||||
let optionsByCat = optionsByCategory[cat];
|
||||
if (!optionsByCat) {
|
||||
optionsByCategory[o.cat] = optionsByCat = {};
|
||||
optionsByCategory[cat] = optionsByCat = {};
|
||||
}
|
||||
optionsByCat[optionId] = o;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { resolveTerminalEncoding } from '../../../base/node/terminalEncoding.js'
|
||||
export function hasStdinWithoutTty() {
|
||||
try {
|
||||
return !process.stdin.isTTY; // Via https://twitter.com/MylesBorins/status/782009479382626304
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Windows workaround for https://github.com/nodejs/node/issues/11656
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -308,7 +308,7 @@ export class HTMLFileSystemProvider extends Disposable implements IFileSystemPro
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line local/code-no-any-casts
|
||||
// eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any
|
||||
const observer = new (globalThis as any).FileSystemObserver((records: FileSystemObserverRecord[]) => {
|
||||
if (disposables.isDisposed) {
|
||||
return;
|
||||
|
||||
@@ -221,58 +221,46 @@ export class IndexedDBFileSystemProvider extends Disposable implements IFileSyst
|
||||
}
|
||||
|
||||
async readdir(resource: URI): Promise<DirEntry[]> {
|
||||
try {
|
||||
const entry = (await this.getFiletree()).read(resource.path);
|
||||
if (!entry) {
|
||||
// Dirs aren't saved to disk, so empty dirs will be lost on reload.
|
||||
// Thus we have two options for what happens when you try to read a dir and nothing is found:
|
||||
// - Throw FileSystemProviderErrorCode.FileNotFound
|
||||
// - Return []
|
||||
// We choose to return [] as creating a dir then reading it (even after reload) should not throw an error.
|
||||
return [];
|
||||
}
|
||||
if (entry.type !== FileType.Directory) {
|
||||
throw ERR_FILE_NOT_DIR;
|
||||
}
|
||||
else {
|
||||
return [...entry.children.entries()].map(([name, node]) => [name, node.type]);
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
const entry = (await this.getFiletree()).read(resource.path);
|
||||
if (!entry) {
|
||||
// Dirs aren't saved to disk, so empty dirs will be lost on reload.
|
||||
// Thus we have two options for what happens when you try to read a dir and nothing is found:
|
||||
// - Throw FileSystemProviderErrorCode.FileNotFound
|
||||
// - Return []
|
||||
// We choose to return [] as creating a dir then reading it (even after reload) should not throw an error.
|
||||
return [];
|
||||
}
|
||||
if (entry.type !== FileType.Directory) {
|
||||
throw ERR_FILE_NOT_DIR;
|
||||
}
|
||||
else {
|
||||
return [...entry.children.entries()].map(([name, node]) => [name, node.type]);
|
||||
}
|
||||
}
|
||||
|
||||
async readFile(resource: URI): Promise<Uint8Array> {
|
||||
try {
|
||||
const result = await this.indexedDB.runInTransaction(this.store, 'readonly', objectStore => objectStore.get(resource.path));
|
||||
if (result === undefined) {
|
||||
throw ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
const buffer = result instanceof Uint8Array ? result : isString(result) ? VSBuffer.fromString(result).buffer : undefined;
|
||||
if (buffer === undefined) {
|
||||
throw ERR_UNKNOWN_INTERNAL(`IndexedDB entry at "${resource.path}" in unexpected format`);
|
||||
}
|
||||
|
||||
// update cache
|
||||
const fileTree = await this.getFiletree();
|
||||
fileTree.add(resource.path, { type: 'file', size: buffer.byteLength });
|
||||
|
||||
return buffer;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
const result = await this.indexedDB.runInTransaction(this.store, 'readonly', objectStore => objectStore.get(resource.path));
|
||||
if (result === undefined) {
|
||||
throw ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
const buffer = result instanceof Uint8Array ? result : isString(result) ? VSBuffer.fromString(result).buffer : undefined;
|
||||
if (buffer === undefined) {
|
||||
throw ERR_UNKNOWN_INTERNAL(`IndexedDB entry at "${resource.path}" in unexpected format`);
|
||||
}
|
||||
|
||||
// update cache
|
||||
const fileTree = await this.getFiletree();
|
||||
fileTree.add(resource.path, { type: 'file', size: buffer.byteLength });
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
async writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void> {
|
||||
try {
|
||||
const existing = await this.stat(resource).catch(() => undefined);
|
||||
if (existing?.type === FileType.Directory) {
|
||||
throw ERR_FILE_IS_DIR;
|
||||
}
|
||||
await this.bulkWrite([[resource, content]]);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
const existing = await this.stat(resource).catch(() => undefined);
|
||||
if (existing?.type === FileType.Directory) {
|
||||
throw ERR_FILE_IS_DIR;
|
||||
}
|
||||
await this.bulkWrite([[resource, content]]);
|
||||
}
|
||||
|
||||
async rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void> {
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
export namespace WebFileSystemAccess {
|
||||
|
||||
export function supported(obj: any & Window): boolean {
|
||||
if (typeof obj?.showDirectoryPicker === 'function') {
|
||||
export function supported(obj: typeof globalThis): boolean {
|
||||
if (typeof (obj as typeof globalThis & { showDirectoryPicker?: unknown })?.showDirectoryPicker === 'function') {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ export namespace WebFileSystemAccess {
|
||||
|
||||
export namespace WebFileSystemObserver {
|
||||
|
||||
export function supported(obj: any & Window): boolean {
|
||||
return typeof obj?.FileSystemObserver === 'function';
|
||||
export function supported(obj: typeof globalThis): boolean {
|
||||
return typeof (obj as typeof globalThis & { FileSystemObserver?: unknown })?.FileSystemObserver === 'function';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,3 +85,10 @@ export interface FileSystemObserverRecord {
|
||||
*/
|
||||
readonly relativePathMovedFrom?: string[];
|
||||
}
|
||||
|
||||
export declare class FileSystemObserver {
|
||||
|
||||
constructor(callback: (records: FileSystemObserverRecord[], observer: FileSystemObserver) => void);
|
||||
|
||||
observe(handle: FileSystemHandle, options?: { recursive: boolean }): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ import { localize } from '../../../nls.js';
|
||||
import { createFileSystemProviderError, IFileAtomicReadOptions, IFileDeleteOptions, IFileOpenOptions, IFileOverwriteOptions, IFileReadStreamOptions, FileSystemProviderCapabilities, FileSystemProviderError, FileSystemProviderErrorCode, FileType, IFileWriteOptions, IFileSystemProviderWithFileAtomicReadCapability, IFileSystemProviderWithFileCloneCapability, IFileSystemProviderWithFileFolderCopyCapability, IFileSystemProviderWithFileReadStreamCapability, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithOpenReadWriteCloseCapability, isFileOpenForWriteOptions, IStat, FilePermission, IFileSystemProviderWithFileAtomicWriteCapability, IFileSystemProviderWithFileAtomicDeleteCapability, IFileChange, IFileSystemProviderWithFileRealpathCapability } from '../common/files.js';
|
||||
import { readFileIntoStream } from '../common/io.js';
|
||||
import { AbstractNonRecursiveWatcherClient, AbstractUniversalWatcherClient, ILogMessage } from '../common/watcher.js';
|
||||
import { ILogService } from '../../log/common/log.js';
|
||||
import { AbstractDiskFileSystemProvider, IDiskFileSystemProviderOptions } from '../common/diskFileSystemProvider.js';
|
||||
import { AbstractDiskFileSystemProvider } from '../common/diskFileSystemProvider.js';
|
||||
import { UniversalWatcherClient } from './watcher/watcherClient.js';
|
||||
import { NodeJSWatcherClient } from './watcher/nodejs/nodejsClient.js';
|
||||
|
||||
@@ -39,13 +38,6 @@ export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider imple
|
||||
|
||||
private static TRACE_LOG_RESOURCE_LOCKS = false; // not enabled by default because very spammy
|
||||
|
||||
constructor(
|
||||
logService: ILogService,
|
||||
options?: IDiskFileSystemProviderOptions
|
||||
) {
|
||||
super(logService, options);
|
||||
}
|
||||
|
||||
//#region File Capabilities
|
||||
|
||||
readonly onDidChangeCapabilities = Event.None;
|
||||
|
||||
@@ -33,37 +33,37 @@ export abstract class AbstractDiskFileSystemProviderChannel<T> extends Disposabl
|
||||
super();
|
||||
}
|
||||
|
||||
call(ctx: T, command: string, arg?: any): Promise<any> {
|
||||
call<TResult>(ctx: T, command: string, args: unknown[]): Promise<TResult> {
|
||||
const uriTransformer = this.getUriTransformer(ctx);
|
||||
|
||||
switch (command) {
|
||||
case 'stat': return this.stat(uriTransformer, arg[0]);
|
||||
case 'realpath': return this.realpath(uriTransformer, arg[0]);
|
||||
case 'readdir': return this.readdir(uriTransformer, arg[0]);
|
||||
case 'open': return this.open(uriTransformer, arg[0], arg[1]);
|
||||
case 'close': return this.close(arg[0]);
|
||||
case 'read': return this.read(arg[0], arg[1], arg[2]);
|
||||
case 'readFile': return this.readFile(uriTransformer, arg[0], arg[1]);
|
||||
case 'write': return this.write(arg[0], arg[1], arg[2], arg[3], arg[4]);
|
||||
case 'writeFile': return this.writeFile(uriTransformer, arg[0], arg[1], arg[2]);
|
||||
case 'rename': return this.rename(uriTransformer, arg[0], arg[1], arg[2]);
|
||||
case 'copy': return this.copy(uriTransformer, arg[0], arg[1], arg[2]);
|
||||
case 'cloneFile': return this.cloneFile(uriTransformer, arg[0], arg[1]);
|
||||
case 'mkdir': return this.mkdir(uriTransformer, arg[0]);
|
||||
case 'delete': return this.delete(uriTransformer, arg[0], arg[1]);
|
||||
case 'watch': return this.watch(uriTransformer, arg[0], arg[1], arg[2], arg[3]);
|
||||
case 'unwatch': return this.unwatch(arg[0], arg[1]);
|
||||
case 'stat': return this.stat(uriTransformer, args[0] as UriComponents) as Promise<TResult>;
|
||||
case 'realpath': return this.realpath(uriTransformer, args[0] as UriComponents) as Promise<TResult>;
|
||||
case 'readdir': return this.readdir(uriTransformer, args[0] as UriComponents) as Promise<TResult>;
|
||||
case 'open': return this.open(uriTransformer, args[0] as UriComponents, args[1] as IFileOpenOptions) as Promise<TResult>;
|
||||
case 'close': return this.close(args[0] as number) as Promise<TResult>;
|
||||
case 'read': return this.read(args[0] as number, args[1] as number, args[2] as number) as Promise<TResult>;
|
||||
case 'readFile': return this.readFile(uriTransformer, args[0] as UriComponents, args[1] as IFileAtomicReadOptions) as Promise<TResult>;
|
||||
case 'write': return this.write(args[0] as number, args[1] as number, args[2] as VSBuffer, args[3] as number, args[4] as number) as Promise<TResult>;
|
||||
case 'writeFile': return this.writeFile(uriTransformer, args[0] as UriComponents, args[1] as VSBuffer, args[2] as IFileWriteOptions) as Promise<TResult>;
|
||||
case 'rename': return this.rename(uriTransformer, args[0] as UriComponents, args[1] as UriComponents, args[2] as IFileOverwriteOptions) as Promise<TResult>;
|
||||
case 'copy': return this.copy(uriTransformer, args[0] as UriComponents, args[1] as UriComponents, args[2] as IFileOverwriteOptions) as Promise<TResult>;
|
||||
case 'cloneFile': return this.cloneFile(uriTransformer, args[0] as UriComponents, args[1] as UriComponents) as Promise<TResult>;
|
||||
case 'mkdir': return this.mkdir(uriTransformer, args[0] as UriComponents) as Promise<TResult>;
|
||||
case 'delete': return this.delete(uriTransformer, args[0] as UriComponents, args[1] as IFileDeleteOptions) as Promise<TResult>;
|
||||
case 'watch': return this.watch(uriTransformer, args[0] as string, args[1] as number, args[2] as UriComponents, args[3] as IWatchOptions) as Promise<TResult>;
|
||||
case 'unwatch': return this.unwatch(args[0] as string, args[1] as number) as Promise<TResult>;
|
||||
}
|
||||
|
||||
throw new Error(`IPC Command ${command} not found`);
|
||||
}
|
||||
|
||||
listen(ctx: T, event: string, arg: any): Event<any> {
|
||||
listen<TResult>(ctx: T, event: string, args: unknown[]): Event<TResult> {
|
||||
const uriTransformer = this.getUriTransformer(ctx);
|
||||
|
||||
switch (event) {
|
||||
case 'fileChange': return this.onFileChange(uriTransformer, arg[0]);
|
||||
case 'readFileStream': return this.onReadFileStream(uriTransformer, arg[0], arg[1]);
|
||||
case 'fileChange': return this.onFileChange(uriTransformer, args[0] as string) as Event<TResult>;
|
||||
case 'readFileStream': return this.onReadFileStream(uriTransformer, args[0] as URI, args[1] as IFileReadStreamOptions) as Event<TResult>;
|
||||
}
|
||||
|
||||
throw new Error(`Unknown event ${event}`);
|
||||
|
||||
@@ -151,7 +151,7 @@ export class NodeJSWatcher extends BaseWatcher implements INonRecursiveWatcher {
|
||||
requestsForCorrelation.set(path, request);
|
||||
}
|
||||
|
||||
return Array.from(mapCorrelationtoRequests.values()).map(requests => Array.from(requests.values())).flat();
|
||||
return Array.from(mapCorrelationtoRequests.values()).flatMap(requests => Array.from(requests.values()));
|
||||
}
|
||||
|
||||
override async setVerboseLogging(enabled: boolean): Promise<void> {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { createDecorator, IInstantiationService, ServiceIdentifier } from '../..
|
||||
import { IMainProcessService } from '../common/mainProcessService.js';
|
||||
import { IRemoteService } from '../common/services.js';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type ChannelClientCtor<T> = { new(channel: IChannel, ...args: any[]): T };
|
||||
type Remote = { getChannel(channelName: string): IChannel };
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ export class LaunchMainService implements ILaunchMainService {
|
||||
};
|
||||
|
||||
// Special case extension development
|
||||
if (!!args.extensionDevelopmentPath) {
|
||||
if (args.extensionDevelopmentPath) {
|
||||
await this.windowsMainService.openExtensionDevelopmentHostWindow(args.extensionDevelopmentPath, baseConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -528,17 +528,17 @@ export class Menubar extends Disposable {
|
||||
menu.append(this.createMenuItem(item.label, item.id, false, item.checked));
|
||||
}
|
||||
} else {
|
||||
menu.append(this.createMenuItem(item.label, item.id, item.enabled === false ? false : true, !!item.checked));
|
||||
menu.append(this.createMenuItem(item.label, item.id, item.enabled !== false, !!item.checked));
|
||||
}
|
||||
} else {
|
||||
menu.append(this.createMenuItem(item.label, item.id, item.enabled === false ? false : true, !!item.checked));
|
||||
menu.append(this.createMenuItem(item.label, item.id, item.enabled !== false, !!item.checked));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setMenuById(menu: Menu, menuId: string): void {
|
||||
if (this.menubarMenus && this.menubarMenus[menuId]) {
|
||||
if (this.menubarMenus?.[menuId]) {
|
||||
this.setMenu(menu, this.menubarMenus[menuId].items);
|
||||
}
|
||||
}
|
||||
@@ -586,7 +586,7 @@ export class Menubar extends Disposable {
|
||||
return !!(event.triggeredByAccelerator || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey);
|
||||
}
|
||||
|
||||
private createRoleMenuItem(label: string, commandId: string, role: any): MenuItem {
|
||||
private createRoleMenuItem(label: string, commandId: string, role: 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteAndMatchStyle' | 'delete' | 'selectAll' | 'reload' | 'forceReload' | 'toggleDevTools' | 'resetZoom' | 'zoomIn' | 'zoomOut' | 'toggleSpellChecker' | 'togglefullscreen' | 'window' | 'minimize' | 'close' | 'help' | 'about' | 'services' | 'hide' | 'hideOthers' | 'unhide' | 'quit' | 'showSubstitutions' | 'toggleSmartQuotes' | 'toggleSmartDashes' | 'toggleTextReplacement' | 'startSpeaking' | 'stopSpeaking' | 'zoom' | 'front' | 'appMenu' | 'fileMenu' | 'editMenu' | 'viewMenu' | 'shareMenu' | 'recentDocuments' | 'toggleTabBar' | 'selectNextTab' | 'selectPreviousTab' | 'showAllTabs' | 'mergeAllWindows' | 'clearRecentDocuments' | 'moveTabToNewWindow' | 'windowMenu'): MenuItem {
|
||||
const options: MenuItemConstructorOptions = {
|
||||
label: this.mnemonicLabel(label),
|
||||
role,
|
||||
@@ -674,25 +674,18 @@ export class Menubar extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private createMenuItem(label: string, commandId: string | string[], enabled?: boolean, checked?: boolean): MenuItem;
|
||||
private createMenuItem(label: string, click: () => void, enabled?: boolean, checked?: boolean): MenuItem;
|
||||
private createMenuItem(arg1: string, arg2: any, arg3?: boolean, arg4?: boolean): MenuItem {
|
||||
const label = this.mnemonicLabel(arg1);
|
||||
const click: () => void = (typeof arg2 === 'function') ? arg2 : (menuItem: MenuItem & IMenuItemWithKeybinding, win: BrowserWindow, event: KeyboardEvent) => {
|
||||
private createMenuItem(labelOpt: string, commandId: string, enabledOpt?: boolean, checkedOpt?: boolean): MenuItem {
|
||||
const label = this.mnemonicLabel(labelOpt);
|
||||
const click = (menuItem: MenuItem & IMenuItemWithKeybinding, window: BaseWindow | undefined, event: KeyboardEvent) => {
|
||||
const userSettingsLabel = menuItem ? menuItem.userSettingsLabel : null;
|
||||
let commandId = arg2;
|
||||
if (Array.isArray(arg2)) {
|
||||
commandId = this.isOptionClick(event) ? arg2[1] : arg2[0]; // support alternative action if we got multiple action Ids and the option key was pressed while invoking
|
||||
}
|
||||
|
||||
if (userSettingsLabel && event.triggeredByAccelerator) {
|
||||
this.runActionInRenderer({ type: 'keybinding', userSettingsLabel });
|
||||
} else {
|
||||
this.runActionInRenderer({ type: 'commandId', commandId });
|
||||
}
|
||||
};
|
||||
const enabled = typeof arg3 === 'boolean' ? arg3 : this.windowsMainService.getWindowCount() > 0;
|
||||
const checked = typeof arg4 === 'boolean' ? arg4 : false;
|
||||
const enabled = typeof enabledOpt === 'boolean' ? enabledOpt : this.windowsMainService.getWindowCount() > 0;
|
||||
const checked = typeof checkedOpt === 'boolean' ? checkedOpt : false;
|
||||
|
||||
const options: MenuItemConstructorOptions = {
|
||||
label,
|
||||
@@ -705,13 +698,6 @@ export class Menubar extends Disposable {
|
||||
options.checked = checked;
|
||||
}
|
||||
|
||||
let commandId: string | undefined;
|
||||
if (typeof arg2 === 'string') {
|
||||
commandId = arg2;
|
||||
} else if (Array.isArray(arg2)) {
|
||||
commandId = arg2[0];
|
||||
}
|
||||
|
||||
if (isMacintosh) {
|
||||
|
||||
// Add role for special case menu items
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ProxyChannel } from '../../../base/parts/ipc/common/ipc.js';
|
||||
import { IMainProcessService } from '../../ipc/common/mainProcessService.js';
|
||||
import { INativeHostService } from './native.js';
|
||||
|
||||
// @ts-ignore: interface is implemented via proxy
|
||||
// @ts-expect-error: interface is implemented via proxy
|
||||
export class NativeHostService implements INativeHostService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
@@ -148,11 +148,12 @@ export class SharedProcess extends Disposable {
|
||||
this.utilityProcess = this._register(new UtilityProcess(this.logService, NullTelemetryService, this.lifecycleMainService));
|
||||
|
||||
// Install a log listener for very early shared process warnings and errors
|
||||
this.utilityProcessLogListener = this.utilityProcess.onMessage((e: any) => {
|
||||
if (typeof e.warning === 'string') {
|
||||
this.logService.warn(e.warning);
|
||||
} else if (typeof e.error === 'string') {
|
||||
this.logService.error(e.error);
|
||||
this.utilityProcessLogListener = this.utilityProcess.onMessage(e => {
|
||||
const logValue = e as { warning?: unknown; error?: unknown };
|
||||
if (typeof logValue.warning === 'string') {
|
||||
this.logService.warn(logValue.warning);
|
||||
} else if (typeof logValue.error === 'string') {
|
||||
this.logService.error(logValue.error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -131,10 +131,6 @@ export class ApplicationStorageDatabaseClient extends BaseProfileAwareStorageDat
|
||||
|
||||
export class ProfileStorageDatabaseClient extends BaseProfileAwareStorageDatabaseClient {
|
||||
|
||||
constructor(channel: IChannel, profile: UriDto<IUserDataProfile>) {
|
||||
super(channel, profile);
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
|
||||
// The profile storage database is shared across all instances of
|
||||
|
||||
@@ -71,6 +71,7 @@ export class StorageDatabaseChannel extends Disposable implements IServerChannel
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
listen(_: unknown, event: string, arg: IBaseSerializableStorageRequest): Event<any> {
|
||||
switch (event) {
|
||||
case 'onDidChangeStorage': {
|
||||
@@ -98,6 +99,7 @@ export class StorageDatabaseChannel extends Disposable implements IServerChannel
|
||||
|
||||
//#endregion
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async call(_: unknown, command: string, arg: IBaseSerializableStorageRequest): Promise<any> {
|
||||
const profile = arg.profile ? revive<IUserDataProfile>(arg.profile) : undefined;
|
||||
const workspace = reviveIdentifier(arg.workspace);
|
||||
@@ -134,6 +136,7 @@ export class StorageDatabaseChannel extends Disposable implements IServerChannel
|
||||
if (typeof path === 'string') {
|
||||
return this.storageMainService.isUsed(path);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -310,14 +310,6 @@ class BaseProfileAwareStorageMain extends BaseStorageMain {
|
||||
|
||||
export class ProfileStorageMain extends BaseProfileAwareStorageMain {
|
||||
|
||||
constructor(
|
||||
profile: IUserDataProfile,
|
||||
options: IStorageMainOptions,
|
||||
logService: ILogService,
|
||||
fileService: IFileService
|
||||
) {
|
||||
super(profile, options, logService, fileService);
|
||||
}
|
||||
}
|
||||
|
||||
export class ApplicationStorageMain extends BaseProfileAwareStorageMain {
|
||||
|
||||
@@ -261,8 +261,8 @@ export class UtilityProcess extends Disposable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private createEnv(configuration: IUtilityProcessConfiguration): { [key: string]: any } {
|
||||
const env: { [key: string]: any } = configuration.env ? { ...configuration.env } : { ...deepClone(process.env) };
|
||||
private createEnv(configuration: IUtilityProcessConfiguration): NodeJS.ProcessEnv {
|
||||
const env: NodeJS.ProcessEnv = configuration.env ? { ...configuration.env } : { ...deepClone(process.env) };
|
||||
|
||||
// Apply supported environment variables from config
|
||||
env['VSCODE_ESM_ENTRYPOINT'] = configuration.entryPoint;
|
||||
|
||||
@@ -395,7 +395,7 @@ export interface INativeOpenFileRequest extends IOpenFileRequest {
|
||||
export interface INativeRunActionInWindowRequest {
|
||||
readonly id: string;
|
||||
readonly from: 'menu' | 'touchbar' | 'mouse';
|
||||
readonly args?: any[];
|
||||
readonly args?: unknown[];
|
||||
}
|
||||
|
||||
export interface INativeRunKeybindingInWindowRequest {
|
||||
@@ -471,7 +471,7 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native
|
||||
* https://github.com/electron/electron/blob/master/docs/api/web-contents.md#contentssetzoomlevellevel
|
||||
*/
|
||||
export function zoomLevelToZoomFactor(zoomLevel = 0): number {
|
||||
return Math.pow(1.2, zoomLevel);
|
||||
return 1.2 ** zoomLevel;
|
||||
}
|
||||
|
||||
export const DEFAULT_EMPTY_WINDOW_SIZE = { width: 1200, height: 800 } as const;
|
||||
|
||||
@@ -77,8 +77,8 @@ export interface ICodeWindow extends IBaseWindow {
|
||||
|
||||
getBounds(): electron.Rectangle;
|
||||
|
||||
send(channel: string, ...args: any[]): void;
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void;
|
||||
send(channel: string, ...args: unknown[]): void;
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: unknown[]): void;
|
||||
|
||||
updateTouchBar(items: ISerializableCommandAction[][]): void;
|
||||
|
||||
|
||||
@@ -902,7 +902,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
|
||||
|
||||
// Unresponsive
|
||||
if (type === WindowError.UNRESPONSIVE) {
|
||||
if (this.isExtensionDevelopmentHost || this.isExtensionTestHost || (this._win && this._win.webContents && this._win.webContents.isDevToolsOpened())) {
|
||||
if (this.isExtensionDevelopmentHost || this.isExtensionTestHost || this._win?.webContents?.isDevToolsOpened()) {
|
||||
// TODO@electron Workaround for https://github.com/microsoft/vscode/issues/56994
|
||||
// In certain cases the window can report unresponsiveness because a breakpoint was hit
|
||||
// and the process is stopped executing. The most typical cases are:
|
||||
@@ -1473,7 +1473,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
|
||||
this._win?.close();
|
||||
}
|
||||
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void {
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: unknown[]): void {
|
||||
if (this.isReady) {
|
||||
this.send(channel, ...args);
|
||||
} else {
|
||||
@@ -1485,7 +1485,7 @@ export class CodeWindow extends BaseWindow implements ICodeWindow {
|
||||
}
|
||||
}
|
||||
|
||||
send(channel: string, ...args: any[]): void {
|
||||
send(channel: string, ...args: unknown[]): void {
|
||||
if (this._win) {
|
||||
if (this._win.isDestroyed() || this._win.webContents.isDestroyed()) {
|
||||
this.logService.warn(`Sending IPC message to channel '${channel}' for window that is destroyed`);
|
||||
|
||||
@@ -42,9 +42,9 @@ export interface IWindowsMainService {
|
||||
|
||||
openExistingWindow(window: ICodeWindow, openConfig: IOpenConfiguration): void;
|
||||
|
||||
sendToFocused(channel: string, ...args: any[]): void;
|
||||
sendToOpeningWindow(channel: string, ...args: any[]): void;
|
||||
sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void;
|
||||
sendToFocused(channel: string, ...args: unknown[]): void;
|
||||
sendToOpeningWindow(channel: string, ...args: unknown[]): void;
|
||||
sendToAll(channel: string, payload?: unknown, windowIdsToIgnore?: number[]): void;
|
||||
|
||||
getWindows(): ICodeWindow[];
|
||||
getWindowCount(): number;
|
||||
|
||||
@@ -389,7 +389,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
// Otherwise, find a good window based on open params
|
||||
else {
|
||||
const focusLastActive = this.windowsStateHandler.state.lastActiveWindow && !openConfig.forceEmpty && !openConfig.cli._.length && !openConfig.cli['file-uri'] && !openConfig.cli['folder-uri'] && !(openConfig.urisToOpen && openConfig.urisToOpen.length);
|
||||
const focusLastActive = this.windowsStateHandler.state.lastActiveWindow && !openConfig.forceEmpty && !openConfig.cli._.length && !openConfig.cli['file-uri'] && !openConfig.cli['folder-uri'] && !openConfig.urisToOpen?.length;
|
||||
let focusLastOpened = true;
|
||||
let focusLastWindow = true;
|
||||
|
||||
@@ -1410,7 +1410,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
cliArgs = cliArgs.filter(path => {
|
||||
const uri = URI.file(path);
|
||||
if (!!findWindowOnWorkspaceOrFolder(this.getWindows(), uri)) {
|
||||
if (findWindowOnWorkspaceOrFolder(this.getWindows(), uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1419,7 +1419,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
folderUris = folderUris.filter(folderUriStr => {
|
||||
const folderUri = this.cliArgToUri(folderUriStr);
|
||||
if (folderUri && !!findWindowOnWorkspaceOrFolder(this.getWindows(), folderUri)) {
|
||||
if (folderUri && findWindowOnWorkspaceOrFolder(this.getWindows(), folderUri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1428,7 +1428,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
|
||||
fileUris = fileUris.filter(fileUriStr => {
|
||||
const fileUri = this.cliArgToUri(fileUriStr);
|
||||
if (fileUri && !!findWindowOnWorkspaceOrFolder(this.getWindows(), fileUri)) {
|
||||
if (fileUri && findWindowOnWorkspaceOrFolder(this.getWindows(), fileUri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1609,7 +1609,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
configuration['disable-extensions'] = currentWindowConfig['disable-extensions'];
|
||||
configuration['disable-extension'] = currentWindowConfig['disable-extension'];
|
||||
}
|
||||
configuration.loggers = configuration.loggers;
|
||||
}
|
||||
|
||||
// Update window identifier and session now
|
||||
@@ -1735,19 +1734,19 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
return getLastFocused(windows);
|
||||
}
|
||||
|
||||
sendToFocused(channel: string, ...args: any[]): void {
|
||||
sendToFocused(channel: string, ...args: unknown[]): void {
|
||||
const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow();
|
||||
|
||||
focusedWindow?.sendWhenReady(channel, CancellationToken.None, ...args);
|
||||
}
|
||||
|
||||
sendToOpeningWindow(channel: string, ...args: any[]): void {
|
||||
sendToOpeningWindow(channel: string, ...args: unknown[]): void {
|
||||
this._register(Event.once(this.onDidSignalReadyWindow)(window => {
|
||||
window.sendWhenReady(channel, CancellationToken.None, ...args);
|
||||
}));
|
||||
}
|
||||
|
||||
sendToAll(channel: string, payload?: any, windowIdsToIgnore?: number[]): void {
|
||||
sendToAll(channel: string, payload?: unknown, windowIdsToIgnore?: number[]): void {
|
||||
for (const window of this.getWindows()) {
|
||||
if (windowIdsToIgnore && windowIdsToIgnore.indexOf(window.id) >= 0) {
|
||||
continue; // do not send if we are instructed to ignore it
|
||||
|
||||
@@ -479,7 +479,7 @@ export function getWindowsStateStoreData(windowsState: IWindowsState): IWindowsS
|
||||
function serializeWindowState(windowState: IWindowState): ISerializedWindowState {
|
||||
return {
|
||||
workspaceIdentifier: windowState.workspace && { id: windowState.workspace.id, configURIPath: windowState.workspace.configPath.toString() },
|
||||
folder: windowState.folderUri && windowState.folderUri.toString(),
|
||||
folder: windowState.folderUri?.toString(),
|
||||
backupPath: windowState.backupPath,
|
||||
remoteAuthority: windowState.remoteAuthority,
|
||||
uiState: windowState.uiState
|
||||
|
||||
@@ -30,7 +30,7 @@ suite('WindowsFinder', () => {
|
||||
};
|
||||
|
||||
const testWorkspaceFolders = toWorkspaceFolders([{ path: join(fixturesFolder, 'vscode_workspace_1_folder') }, { path: join(fixturesFolder, 'vscode_workspace_2_folder') }], testWorkspace.configPath, extUriBiasedIgnorePathCase);
|
||||
const localWorkspaceResolver = async (workspace: any) => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : undefined; };
|
||||
const localWorkspaceResolver = async (workspace: IWorkspaceIdentifier) => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : undefined; };
|
||||
|
||||
function createTestCodeWindow(options: { lastFocusTime: number; openedFolderUri?: URI; openedWorkspace?: IWorkspaceIdentifier }): ICodeWindow {
|
||||
return new class implements ICodeWindow {
|
||||
@@ -64,8 +64,8 @@ suite('WindowsFinder', () => {
|
||||
focus(options?: { mode: FocusMode }): void { throw new Error('Method not implemented.'); }
|
||||
close(): void { throw new Error('Method not implemented.'); }
|
||||
getBounds(): Electron.Rectangle { throw new Error('Method not implemented.'); }
|
||||
send(channel: string, ...args: any[]): void { throw new Error('Method not implemented.'); }
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void { throw new Error('Method not implemented.'); }
|
||||
send(channel: string, ...args: unknown[]): void { throw new Error('Method not implemented.'); }
|
||||
sendWhenReady(channel: string, token: CancellationToken, ...args: unknown[]): void { throw new Error('Method not implemented.'); }
|
||||
toggleFullScreen(): void { throw new Error('Method not implemented.'); }
|
||||
setRepresentedFilename(name: string): void { throw new Error('Method not implemented.'); }
|
||||
getRepresentedFilename(): string | undefined { throw new Error('Method not implemented.'); }
|
||||
@@ -75,7 +75,7 @@ suite('WindowsFinder', () => {
|
||||
serializeWindowState(): IWindowState { throw new Error('Method not implemented'); }
|
||||
updateWindowControls(options: { height?: number | undefined; backgroundColor?: string | undefined; foregroundColor?: string | undefined }): void { throw new Error('Method not implemented.'); }
|
||||
notifyZoomLevel(level: number): void { throw new Error('Method not implemented.'); }
|
||||
matches(webContents: any): boolean { throw new Error('Method not implemented.'); }
|
||||
matches(webContents: Electron.WebContents): boolean { throw new Error('Method not implemented.'); }
|
||||
dispose(): void { }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -316,16 +316,22 @@ interface ISerializedRecentlyOpened {
|
||||
|
||||
export type RecentlyOpenedStorageData = object;
|
||||
|
||||
function isSerializedRecentWorkspace(data: any): data is ISerializedRecentWorkspace {
|
||||
return data.workspace && typeof data.workspace === 'object' && typeof data.workspace.id === 'string' && typeof data.workspace.configPath === 'string';
|
||||
function isSerializedRecentWorkspace(data: unknown): data is ISerializedRecentWorkspace {
|
||||
const candidate = data as ISerializedRecentWorkspace | undefined;
|
||||
|
||||
return typeof candidate?.workspace === 'object' && typeof candidate.workspace.id === 'string' && typeof candidate.workspace.configPath === 'string';
|
||||
}
|
||||
|
||||
function isSerializedRecentFolder(data: any): data is ISerializedRecentFolder {
|
||||
return typeof data.folderUri === 'string';
|
||||
function isSerializedRecentFolder(data: unknown): data is ISerializedRecentFolder {
|
||||
const candidate = data as ISerializedRecentFolder | undefined;
|
||||
|
||||
return typeof candidate?.folderUri === 'string';
|
||||
}
|
||||
|
||||
function isSerializedRecentFile(data: any): data is ISerializedRecentFile {
|
||||
return typeof data.fileUri === 'string';
|
||||
function isSerializedRecentFile(data: unknown): data is ISerializedRecentFile {
|
||||
const candidate = data as ISerializedRecentFile | undefined;
|
||||
|
||||
return typeof candidate?.fileUri === 'string';
|
||||
}
|
||||
|
||||
export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefined, logService: ILogService): IRecentlyOpened {
|
||||
|
||||
@@ -169,7 +169,7 @@ function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||
const withPorts = (ports: MessagePortMain[]) => {
|
||||
const port = ports[0];
|
||||
const onMessage = new BufferedEmitter<VSBuffer>();
|
||||
port.on('message', (e) => onMessage.fire(VSBuffer.wrap(e.data)));
|
||||
port.on('message', (e) => onMessage.fire(VSBuffer.wrap(e.data as Uint8Array)));
|
||||
port.on('close', () => {
|
||||
onTerminate('renderer closed the MessagePort');
|
||||
});
|
||||
|
||||
@@ -389,7 +389,7 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
|
||||
const fromCommandsRegistry = CommandsRegistry.getCommand(commandId);
|
||||
|
||||
if (fromCommandsRegistry && fromCommandsRegistry.metadata?.description) {
|
||||
if (fromCommandsRegistry?.metadata?.description) {
|
||||
return { title: typeof fromCommandsRegistry.metadata.description === 'string' ? fromCommandsRegistry.metadata.description : fromCommandsRegistry.metadata.description.value };
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { localize, localize2 } from '../../../nls.js';
|
||||
import { IWindowOpenable } from '../../../platform/window/common/window.js';
|
||||
import { IDialogService } from '../../../platform/dialogs/common/dialogs.js';
|
||||
import { MenuRegistry, MenuId, Action2, registerAction2, IAction2Options } from '../../../platform/actions/common/actions.js';
|
||||
import { MenuRegistry, MenuId, Action2, registerAction2 } from '../../../platform/actions/common/actions.js';
|
||||
import { KeyChord, KeyCode, KeyMod } from '../../../base/common/keyCodes.js';
|
||||
import { IsMainWindowFullscreenContext } from '../../common/contextkeys.js';
|
||||
import { IsMacNativeContext, IsDevelopmentContext, IsWebContext, IsIOSContext } from '../../../platform/contextkey/common/contextkeys.js';
|
||||
@@ -62,10 +62,6 @@ abstract class BaseOpenRecentAction extends Action2 {
|
||||
tooltip: localize('dirtyRecentlyOpenedWorkspace', "Workspace With Unsaved Files"),
|
||||
};
|
||||
|
||||
constructor(desc: Readonly<IAction2Options>) {
|
||||
super(desc);
|
||||
}
|
||||
|
||||
protected abstract isQuickNavigate(): boolean;
|
||||
|
||||
override async run(accessor: ServicesAccessor): Promise<void> {
|
||||
|
||||
@@ -241,8 +241,8 @@ CommandsRegistry.registerCommand({
|
||||
const commandService = accessor.get(ICommandService);
|
||||
|
||||
const commandOptions: IOpenEmptyWindowOptions = {
|
||||
forceReuseWindow: options && options.reuseWindow,
|
||||
remoteAuthority: options && options.remoteAuthority
|
||||
forceReuseWindow: options?.reuseWindow,
|
||||
remoteAuthority: options?.remoteAuthority
|
||||
};
|
||||
|
||||
return commandService.executeCommand('_files.newWindow', commandOptions);
|
||||
|
||||
@@ -31,7 +31,7 @@ import { IBaseActionViewItemOptions } from '../../base/browser/ui/actionbar/acti
|
||||
* layout(), focus(), dispose(). During use of the workbench, a composite will often receive a setVisible,
|
||||
* layout and focus call, but only one create and dispose call.
|
||||
*/
|
||||
export abstract class Composite extends Component implements IComposite {
|
||||
export abstract class Composite<MementoType extends object = object> extends Component<MementoType> implements IComposite {
|
||||
|
||||
private readonly _onTitleAreaUpdate = this._register(new Emitter<void>());
|
||||
readonly onTitleAreaUpdate = this._onTitleAreaUpdate.event;
|
||||
|
||||
@@ -470,7 +470,7 @@ export class CompositeDragAndDropObserver extends Disposable {
|
||||
private readDragData(type: ViewType): CompositeDragAndDropData | undefined {
|
||||
if (this.transferData.hasData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype)) {
|
||||
const data = this.transferData.getData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype);
|
||||
if (data && data[0]) {
|
||||
if (data?.[0]) {
|
||||
return new CompositeDragAndDropData(type, data[0].id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { VIEWPANE_FILTER_ACTION } from './parts/views/viewPane.js';
|
||||
import { IBoundarySashes } from '../../base/browser/ui/sash/sash.js';
|
||||
import { IBaseActionViewItemOptions } from '../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
|
||||
export abstract class PaneComposite extends Composite implements IPaneComposite {
|
||||
export abstract class PaneComposite<MementoType extends object = object> extends Composite<MementoType> implements IPaneComposite {
|
||||
|
||||
private viewPaneContainer?: ViewPaneContainer;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export interface ILayoutContentResult {
|
||||
* Parts are layed out in the workbench and have their own layout that
|
||||
* arranges an optional title and mandatory content area to show content.
|
||||
*/
|
||||
export abstract class Part extends Component implements ISerializableView {
|
||||
export abstract class Part<MementoType extends object = object> extends Component<MementoType> implements ISerializableView {
|
||||
|
||||
private _dimension: Dimension | undefined;
|
||||
get dimension(): Dimension | undefined { return this._dimension; }
|
||||
@@ -265,7 +265,7 @@ export interface IMultiWindowPart {
|
||||
readonly element: HTMLElement;
|
||||
}
|
||||
|
||||
export abstract class MultiWindowParts<T extends IMultiWindowPart> extends Component {
|
||||
export abstract class MultiWindowParts<T extends IMultiWindowPart, MementoType extends object = object> extends Component<MementoType> {
|
||||
|
||||
protected readonly _parts = new Set<T>();
|
||||
get parts() { return Array.from(this._parts); }
|
||||
|
||||
@@ -63,12 +63,12 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
|
||||
const activeComposite = this.getActivePaneComposite();
|
||||
|
||||
if (!activeComposite) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const width = activeComposite.getOptimalWidth();
|
||||
if (typeof width !== 'number') {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Math.max(width, 300);
|
||||
|
||||
@@ -71,7 +71,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
|
||||
if (dragData.type === 'view') {
|
||||
const viewToMove = this.viewDescriptorService.getViewDescriptorById(dragData.id)!;
|
||||
if (viewToMove && viewToMove.canMoveView) {
|
||||
if (viewToMove.canMoveView) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewToMove, this.targetContainerLocation, 'dnd');
|
||||
|
||||
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
|
||||
|
||||
@@ -56,7 +56,7 @@ interface CompositeItem {
|
||||
readonly progress: IProgressIndicator;
|
||||
}
|
||||
|
||||
export abstract class CompositePart<T extends Composite> extends Part {
|
||||
export abstract class CompositePart<T extends Composite, MementoType extends object = object> extends Part<MementoType> {
|
||||
|
||||
protected readonly onDidCompositeOpen = this._register(new Emitter<{ composite: IComposite; focus: boolean }>());
|
||||
protected readonly onDidCompositeClose = this._register(new Emitter<IComposite>());
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IWorkbenchLayoutService, Parts } from '../../../services/layout/browser
|
||||
import { GoFilter, IHistoryService } from '../../../services/history/common/history.js';
|
||||
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
|
||||
import { ICommandService } from '../../../../platform/commands/common/commands.js';
|
||||
import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, SelectedEditorsMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, TOGGLE_MAXIMIZE_EDITOR_GROUP, MOVE_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, MOVE_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID as NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID, MOVE_EDITOR_INTO_RIGHT_GROUP, MOVE_EDITOR_INTO_LEFT_GROUP, MOVE_EDITOR_INTO_ABOVE_GROUP, MOVE_EDITOR_INTO_BELOW_GROUP } from './editorCommands.js';
|
||||
import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, SelectedEditorsMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, TOGGLE_MAXIMIZE_EDITOR_GROUP, MOVE_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, MOVE_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID, MOVE_EDITOR_INTO_RIGHT_GROUP, MOVE_EDITOR_INTO_LEFT_GROUP, MOVE_EDITOR_INTO_ABOVE_GROUP, MOVE_EDITOR_INTO_BELOW_GROUP } from './editorCommands.js';
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder, MergeGroupMode } from '../../../services/editor/common/editorGroupsService.js';
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
|
||||
@@ -1276,7 +1276,7 @@ function registerOtherEditorCommands(): void {
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
|
||||
const currentSetting = configurationService.getValue('workbench.editor.enablePreview');
|
||||
const newSetting = currentSetting === true ? false : true;
|
||||
const newSetting = currentSetting !== true;
|
||||
configurationService.updateValue('workbench.editor.enablePreview', newSetting);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -336,6 +336,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
case GroupModelChangeKind.EDITOR_CLOSE:
|
||||
groupActiveEditorPinnedContext.set(this.model.activeEditor ? this.model.isPinned(this.model.activeEditor) : false);
|
||||
groupActiveEditorStickyContext.set(this.model.activeEditor ? this.model.isSticky(this.model.activeEditor) : false);
|
||||
break;
|
||||
case GroupModelChangeKind.EDITOR_OPEN:
|
||||
case GroupModelChangeKind.EDITOR_MOVE:
|
||||
groupActiveEditorFirstContext.set(this.model.isFirst(this.model.activeEditor));
|
||||
@@ -1802,7 +1803,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// However, we only do this unless a custom confirm handler is installed
|
||||
// that may not be fit to be asked a second time right after.
|
||||
if (!editor.closeHandler && !this.shouldConfirmClose(editor)) {
|
||||
return confirmation === ConfirmResult.CANCEL ? true : false;
|
||||
return confirmation === ConfirmResult.CANCEL;
|
||||
}
|
||||
|
||||
// Otherwise, handle accordingly
|
||||
|
||||
@@ -16,7 +16,6 @@ import { URI } from '../../../../base/common/uri.js';
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { isEmptyObject } from '../../../../base/common/types.js';
|
||||
import { DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from './editor.js';
|
||||
import { MementoObject } from '../../../common/memento.js';
|
||||
import { joinPath, IExtUri, isEqual } from '../../../../base/common/resources.js';
|
||||
import { indexOfPath } from '../../../../base/common/extpath.js';
|
||||
import { Disposable, IDisposable } from '../../../../base/common/lifecycle.js';
|
||||
@@ -47,7 +46,7 @@ import { getWindowById } from '../../../../base/browser/dom.js';
|
||||
*
|
||||
* This class is only intended to be subclassed and not instantiated.
|
||||
*/
|
||||
export abstract class EditorPane extends Composite implements IEditorPane {
|
||||
export abstract class EditorPane<MementoType extends object = object> extends Composite<MementoType> implements IEditorPane {
|
||||
|
||||
//#region Events
|
||||
|
||||
@@ -220,7 +219,7 @@ export class EditorMemento<T> extends Disposable implements IEditorMemento<T> {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
private readonly key: string,
|
||||
private readonly memento: MementoObject,
|
||||
private readonly memento: T,
|
||||
private readonly limit: number,
|
||||
private readonly editorGroupService: IEditorGroupsService,
|
||||
private readonly configurationService: ITextResourceConfigurationService
|
||||
@@ -387,7 +386,7 @@ export class EditorMemento<T> extends Disposable implements IEditorMemento<T> {
|
||||
this.cache = new LRUCache<string, MapGroupToMemento<T>>(this.limit);
|
||||
|
||||
// Restore from serialized map state
|
||||
const rawEditorMemento = this.memento[this.key];
|
||||
const rawEditorMemento = this.memento[this.key as keyof T];
|
||||
if (Array.isArray(rawEditorMemento)) {
|
||||
this.cache.fromJSON(rawEditorMemento);
|
||||
}
|
||||
@@ -405,7 +404,7 @@ export class EditorMemento<T> extends Disposable implements IEditorMemento<T> {
|
||||
this.cleanedUp = true;
|
||||
}
|
||||
|
||||
this.memento[this.key] = cache.toJSON();
|
||||
(this.memento as Record<string, unknown>)[this.key] = cache.toJSON();
|
||||
}
|
||||
|
||||
private cleanUp(): void {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget
|
||||
import { ISerializedEditorGroupModel, isSerializedEditorGroupModel } from '../../../common/editor/editorGroupModel.js';
|
||||
import { EditorDropTarget } from './editorDropTarget.js';
|
||||
import { Color } from '../../../../base/common/color.js';
|
||||
import { CenteredViewLayout } from '../../../../base/browser/ui/centered/centeredViewLayout.js';
|
||||
import { CenteredViewLayout, CenteredViewState } from '../../../../base/browser/ui/centered/centeredViewLayout.js';
|
||||
import { onUnexpectedError } from '../../../../base/common/errors.js';
|
||||
import { Parts, IWorkbenchLayoutService, Position } from '../../../services/layout/browser/layoutService.js';
|
||||
import { DeepPartial, assertType } from '../../../../base/common/types.js';
|
||||
@@ -43,6 +43,11 @@ export interface IEditorPartUIState {
|
||||
readonly mostRecentActiveGroups: GroupIdentifier[];
|
||||
}
|
||||
|
||||
interface IEditorPartMemento {
|
||||
'editorpart.state'?: IEditorPartUIState;
|
||||
'editorpart.centeredview'?: CenteredViewState;
|
||||
}
|
||||
|
||||
class GridWidgetView<T extends IView> implements IView {
|
||||
|
||||
readonly element: HTMLElement = $('.grid-view-container');
|
||||
@@ -83,7 +88,7 @@ class GridWidgetView<T extends IView> implements IView {
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
|
||||
export class EditorPart extends Part<IEditorPartMemento> implements IEditorPart, IEditorGroupsView {
|
||||
|
||||
private static readonly EDITOR_PART_UI_STATE_STORAGE_KEY = 'editorpart.state';
|
||||
private static readonly EDITOR_PART_CENTERED_VIEW_STORAGE_KEY = 'editorpart.centeredview';
|
||||
|
||||
@@ -43,7 +43,11 @@ interface IEditorWorkingSetState extends IEditorWorkingSet {
|
||||
readonly auxiliary: IEditorPartsUIState;
|
||||
}
|
||||
|
||||
export class EditorParts extends MultiWindowParts<EditorPart> implements IEditorGroupsService, IEditorPartsView {
|
||||
interface IEditorPartsMemento {
|
||||
'editorparts.state'?: IEditorPartsUIState;
|
||||
}
|
||||
|
||||
export class EditorParts extends MultiWindowParts<EditorPart, IEditorPartsMemento> implements IEditorGroupsService, IEditorPartsView {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
@@ -534,7 +538,7 @@ export class EditorParts extends MultiWindowParts<EditorPart> implements IEditor
|
||||
break;
|
||||
}
|
||||
|
||||
return parts.map(part => part.getGroups(order)).flat();
|
||||
return parts.flatMap(part => part.getGroups(order));
|
||||
}
|
||||
|
||||
return this.mainPart.getGroups(order);
|
||||
|
||||
@@ -305,7 +305,7 @@ class TabFocusMode extends Disposable {
|
||||
|
||||
this.registerListeners();
|
||||
|
||||
const tabFocusModeConfig = configurationService.getValue<boolean>('editor.tabFocusMode') === true ? true : false;
|
||||
const tabFocusModeConfig = configurationService.getValue<boolean>('editor.tabFocusMode') === true;
|
||||
TabFocus.setTabFocusMode(tabFocusModeConfig);
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ class TabFocusMode extends Disposable {
|
||||
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor.tabFocusMode')) {
|
||||
const tabFocusModeConfig = this.configurationService.getValue<boolean>('editor.tabFocusMode') === true ? true : false;
|
||||
const tabFocusModeConfig = this.configurationService.getValue<boolean>('editor.tabFocusMode') === true;
|
||||
TabFocus.setTabFocusMode(tabFocusModeConfig);
|
||||
|
||||
this._onDidChange.fire(tabFocusModeConfig);
|
||||
|
||||
@@ -126,7 +126,7 @@ export abstract class AbstractEditorWithViewState<T extends object> extends Edit
|
||||
|
||||
// new editor: check with workbench.editor.restoreViewState setting
|
||||
if (context?.newInGroup) {
|
||||
return this.textResourceConfigurationService.getValue<boolean>(EditorResourceAccessor.getOriginalUri(input, { supportSideBySide: SideBySideEditor.PRIMARY }), 'workbench.editor.restoreViewState') === false ? false : true /* restore by default */;
|
||||
return this.textResourceConfigurationService.getValue<boolean>(EditorResourceAccessor.getOriginalUri(input, { supportSideBySide: SideBySideEditor.PRIMARY }), 'workbench.editor.restoreViewState') !== false /* restore by default */;
|
||||
}
|
||||
|
||||
// existing editor: always restore viewstate
|
||||
|
||||
@@ -273,7 +273,7 @@ export class EditorsObserver extends Disposable {
|
||||
|
||||
// Remove from key map
|
||||
const map = this.keyMap.get(group.id);
|
||||
if (map && map.delete(key.editor) && map.size === 0) {
|
||||
if (map?.delete(key.editor) && map.size === 0) {
|
||||
this.keyMap.delete(group.id);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
.monaco-workbench .notifications-list-container .notification-list-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: column-reverse; /* the details row appears first in order for better keyboard access to notification buttons */
|
||||
padding: 10px 5px;
|
||||
height: 100%;
|
||||
|
||||
@@ -65,7 +65,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
|
||||
}
|
||||
|
||||
// Last row: source and buttons if we have any
|
||||
if (notification.source || isNonEmptyArray(notification.actions && notification.actions.primary)) {
|
||||
if (notification.source || isNonEmptyArray(notification.actions?.primary)) {
|
||||
expandedHeight += NotificationsListDelegate.ROW_HEIGHT;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export class NotificationsListDelegate implements IListVirtualDelegate<INotifica
|
||||
if (notification.canCollapse) {
|
||||
actions++; // expand/collapse
|
||||
}
|
||||
if (isNonEmptyArray(notification.actions && notification.actions.secondary)) {
|
||||
if (isNonEmptyArray(notification.actions?.secondary)) {
|
||||
actions++; // secondary actions
|
||||
}
|
||||
this.offsetHelper.style.width = `${450 /* notifications container width */ - (10 /* padding */ + 30 /* severity icon */ + (actions * 30) /* actions */ - (Math.max(actions - 1, 0) * 4) /* less padding for actions > 1 */)}px`;
|
||||
|
||||
@@ -324,7 +324,7 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
|
||||
|
||||
else if (dragData.type === 'view') {
|
||||
const viewToMove = this.viewDescriptorService.getViewDescriptorById(dragData.id)!;
|
||||
if (viewToMove && viewToMove.canMoveView) {
|
||||
if (viewToMove.canMoveView) {
|
||||
this.viewDescriptorService.moveViewToLocation(viewToMove, this.location, 'dnd');
|
||||
|
||||
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
|
||||
|
||||
@@ -51,12 +51,12 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
const activeComposite = this.getActivePaneComposite();
|
||||
|
||||
if (!activeComposite) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const width = activeComposite.getOptimalWidth();
|
||||
if (typeof width !== 'number') {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Math.max(width, 300);
|
||||
|
||||
@@ -51,12 +51,12 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
const viewlet = this.getActivePaneComposite();
|
||||
|
||||
if (!viewlet) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const width = viewlet.getOptimalWidth();
|
||||
if (typeof width !== 'number') {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Math.max(width, 300);
|
||||
|
||||
@@ -24,7 +24,7 @@ import { IInstantiationService, ServicesAccessor } from '../../../../platform/in
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { IStorageService, StorageScope } from '../../../../platform/storage/common/storage.js';
|
||||
import { Parts, IWorkbenchLayoutService, ActivityBarPosition, LayoutSettings, EditorActionsLocation, EditorTabsMode } from '../../../services/layout/browser/layoutService.js';
|
||||
import { createActionViewItem, fillInActionBarActions as fillInActionBarActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
|
||||
import { createActionViewItem, fillInActionBarActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
|
||||
import { Action2, IMenu, IMenuService, MenuId, registerAction2 } from '../../../../platform/actions/common/actions.js';
|
||||
import { IContextKey, IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { IHostService } from '../../../services/host/browser/host.js';
|
||||
|
||||
@@ -180,7 +180,7 @@ function commandPreconditions(commandId: string): ContextKeyExpression | undefin
|
||||
const command = CommandsRegistry.getCommand(commandId);
|
||||
if (command) {
|
||||
const commandAction = MenuRegistry.getCommand(command.id);
|
||||
return commandAction && commandAction.precondition;
|
||||
return commandAction?.precondition;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -404,7 +404,7 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
|
||||
async getChildrenBatch(nodes?: ITreeItem[]): Promise<ITreeItem[][]> {
|
||||
let childrenGroups: ITreeItem[][];
|
||||
let checkboxesUpdated: ITreeItem[] = [];
|
||||
if (nodes && nodes.every((node): node is Required<ITreeItem & { children: ITreeItem[] }> => !!node.children)) {
|
||||
if (nodes?.every((node): node is Required<ITreeItem & { children: ITreeItem[] }> => !!node.children)) {
|
||||
childrenGroups = nodes.map(node => node.children);
|
||||
} else {
|
||||
nodes = nodes ?? [self.root];
|
||||
@@ -1331,7 +1331,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer<ITreeItem, FuzzyS
|
||||
const treeItemLabel: ITreeItemLabel | undefined = node.label ? node.label : (resource ? { label: basename(resource) } : undefined);
|
||||
const description = isString(node.description) ? node.description : resource && node.description === true ? this.labelService.getUriLabel(dirname(resource), { relative: true }) : undefined;
|
||||
const label = treeItemLabel ? treeItemLabel.label : undefined;
|
||||
const matches = (treeItemLabel && treeItemLabel.highlights && label) ? treeItemLabel.highlights.map(([start, end]) => {
|
||||
const matches = (treeItemLabel?.highlights && label) ? treeItemLabel.highlights.map(([start, end]) => {
|
||||
if (start < 0) {
|
||||
start = label.length + start;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ class ViewWelcomeController {
|
||||
if (linkedText.nodes.length === 1 && typeof linkedText.nodes[0] !== 'string') {
|
||||
const node = linkedText.nodes[0];
|
||||
const buttonContainer = append(this.element!, $('.button-container'));
|
||||
const button = new Button(buttonContainer, { title: node.title, supportIcons: true, secondary: renderSecondaryButtons && buttonsCount > 0 ? true : false, ...defaultButtonStyles, });
|
||||
const button = new Button(buttonContainer, { title: node.title, supportIcons: true, secondary: !!(renderSecondaryButtons && buttonsCount > 0), ...defaultButtonStyles, });
|
||||
button.label = node.label;
|
||||
button.onDidClick(_ => {
|
||||
this.openerService.open(node.href, { allowCommands: true });
|
||||
|
||||
@@ -288,7 +288,7 @@ class ViewPaneDropOverlay extends Themable {
|
||||
}
|
||||
}
|
||||
|
||||
export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
export class ViewPaneContainer<MementoType extends object = object> extends Component<MementoType> implements IViewPaneContainer {
|
||||
|
||||
readonly viewContainer: ViewContainer;
|
||||
private lastFocusedPane: ViewPane | undefined;
|
||||
@@ -424,7 +424,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {
|
||||
onDragEnter: (e) => {
|
||||
bounds = getOverlayBounds();
|
||||
if (overlay && overlay.disposed) {
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
}
|
||||
},
|
||||
onDragOver: (e) => {
|
||||
if (overlay && overlay.disposed) {
|
||||
if (overlay?.disposed) {
|
||||
overlay = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Memento, MementoObject } from './memento.js';
|
||||
import { Memento } from './memento.js';
|
||||
import { IThemeService, Themable } from '../../platform/theme/common/themeService.js';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from '../../platform/storage/common/storage.js';
|
||||
import { DisposableStore } from '../../base/common/lifecycle.js';
|
||||
import { Event } from '../../base/common/event.js';
|
||||
|
||||
export class Component extends Themable {
|
||||
export class Component<MementoType extends object = object> extends Themable {
|
||||
|
||||
private readonly memento: Memento;
|
||||
private readonly memento: Memento<MementoType>;
|
||||
|
||||
constructor(
|
||||
private readonly id: string,
|
||||
@@ -36,12 +36,12 @@ export class Component extends Themable {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected getMemento(scope: StorageScope, target: StorageTarget): MementoObject {
|
||||
protected getMemento(scope: StorageScope, target: StorageTarget): Partial<MementoType> {
|
||||
return this.memento.getMemento(scope, target);
|
||||
}
|
||||
|
||||
protected reloadMemento(scope: StorageScope): void {
|
||||
return this.memento.reloadMemento(scope);
|
||||
this.memento.reloadMemento(scope);
|
||||
}
|
||||
|
||||
protected onDidChangeMementoValue(scope: StorageScope, disposables: DisposableStore): Event<IStorageValueChangeEvent> {
|
||||
|
||||
@@ -58,8 +58,9 @@ export const Extensions = {
|
||||
ConfigurationMigration: 'base.contributions.configuration.migration'
|
||||
};
|
||||
|
||||
export type ConfigurationValue = { value: any | undefined /* Remove */ };
|
||||
type ConfigurationValue = { value: unknown | undefined /* Remove */ };
|
||||
export type ConfigurationKeyValuePairs = [string, ConfigurationValue][];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ConfigurationMigrationFn = (value: any, valueAccessor: (key: string) => any) => ConfigurationValue | ConfigurationKeyValuePairs | Promise<ConfigurationValue | ConfigurationKeyValuePairs>;
|
||||
export type ConfigurationMigration = { key: string; migrateFn: ConfigurationMigrationFn };
|
||||
|
||||
@@ -115,7 +116,7 @@ export class ConfigurationMigrationWorkbenchContribution extends Disposable impl
|
||||
private async migrateConfigurationsForFolderAndOverride(migration: ConfigurationMigration, resource?: URI): Promise<void> {
|
||||
const inspectData = this.configurationService.inspect(migration.key, { resource });
|
||||
|
||||
const targetPairs: [keyof IConfigurationValue<any>, ConfigurationTarget][] = this.workspaceService.getWorkbenchState() === WorkbenchState.WORKSPACE ? [
|
||||
const targetPairs: [keyof IConfigurationValue<unknown>, ConfigurationTarget][] = this.workspaceService.getWorkbenchState() === WorkbenchState.WORKSPACE ? [
|
||||
['user', ConfigurationTarget.USER],
|
||||
['userLocal', ConfigurationTarget.USER_LOCAL],
|
||||
['userRemote', ConfigurationTarget.USER_REMOTE],
|
||||
@@ -128,7 +129,7 @@ export class ConfigurationMigrationWorkbenchContribution extends Disposable impl
|
||||
['workspace', ConfigurationTarget.WORKSPACE],
|
||||
];
|
||||
for (const [dataKey, target] of targetPairs) {
|
||||
const inspectValue = inspectData[dataKey] as IInspectValue<any> | undefined;
|
||||
const inspectValue = inspectData[dataKey] as IInspectValue<unknown> | undefined;
|
||||
if (!inspectValue) {
|
||||
continue;
|
||||
}
|
||||
@@ -159,10 +160,10 @@ export class ConfigurationMigrationWorkbenchContribution extends Disposable impl
|
||||
}
|
||||
}
|
||||
|
||||
private async runMigration(migration: ConfigurationMigration, dataKey: keyof IConfigurationValue<any>, value: any, resource: URI | undefined, overrideIdentifiers: string[] | undefined): Promise<ConfigurationKeyValuePairs | undefined> {
|
||||
private async runMigration(migration: ConfigurationMigration, dataKey: keyof IConfigurationValue<unknown>, value: unknown, resource: URI | undefined, overrideIdentifiers: string[] | undefined): Promise<ConfigurationKeyValuePairs | undefined> {
|
||||
const valueAccessor = (key: string) => {
|
||||
const inspectData = this.configurationService.inspect(key, { resource });
|
||||
const inspectValue = inspectData[dataKey] as IInspectValue<any> | undefined;
|
||||
const inspectValue = inspectData[dataKey] as IInspectValue<unknown> | undefined;
|
||||
if (!inspectValue) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -271,7 +272,7 @@ export class DynamicWindowConfiguration extends Disposable implements IWorkbench
|
||||
'type': ['string', 'null'],
|
||||
'default': null,
|
||||
'enum': [...this.userDataProfilesService.profiles.map(profile => profile.name), null],
|
||||
'enumItemLabels': [...this.userDataProfilesService.profiles.map(p => ''), localize('active window', "Active Window")],
|
||||
'enumItemLabels': [...this.userDataProfilesService.profiles.map(() => ''), localize('active window', "Active Window")],
|
||||
'description': localize('newWindowProfile', "Specifies the profile to use when opening a new window. If a profile name is provided, the new window will use that profile. If no profile name is provided, the new window will use the profile of the active window or the Default profile if no active window exists."),
|
||||
'scope': ConfigurationScope.APPLICATION,
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
}
|
||||
|
||||
setActive(candidate: EditorInput | undefined): EditorInput | undefined {
|
||||
let result: EditorInput | undefined = undefined;
|
||||
let result: EditorInput | undefined;
|
||||
|
||||
if (!candidate) {
|
||||
this.setGroupActive();
|
||||
@@ -1231,7 +1231,7 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
}
|
||||
|
||||
this.editors = coalesce(data.editors.map((e, index) => {
|
||||
let editor: EditorInput | undefined = undefined;
|
||||
let editor: EditorInput | undefined;
|
||||
|
||||
const editorSerializer = registry.getEditorSerializer(e.id);
|
||||
if (editorSerializer) {
|
||||
|
||||
@@ -198,7 +198,7 @@ export abstract class AbstractResourceEditorInput extends EditorInput implements
|
||||
// resource scheme.
|
||||
|
||||
const defaultSizeLimit = getLargeFileConfirmationLimit(this.resource);
|
||||
let configuredSizeLimit: number | undefined = undefined;
|
||||
let configuredSizeLimit: number | undefined;
|
||||
|
||||
const configuredSizeLimitMb = this.textResourceConfigurationService.inspect<number>(this.resource, null, 'workbench.editorLargeFileConfirmation');
|
||||
if (isConfigured(configuredSizeLimitMb)) {
|
||||
|
||||
@@ -9,13 +9,11 @@ import { onUnexpectedError } from '../../base/common/errors.js';
|
||||
import { DisposableStore } from '../../base/common/lifecycle.js';
|
||||
import { Event } from '../../base/common/event.js';
|
||||
|
||||
export type MementoObject = { [key: string]: any };
|
||||
export class Memento<T extends object> {
|
||||
|
||||
export class Memento {
|
||||
|
||||
private static readonly applicationMementos = new Map<string, ScopedMemento>();
|
||||
private static readonly profileMementos = new Map<string, ScopedMemento>();
|
||||
private static readonly workspaceMementos = new Map<string, ScopedMemento>();
|
||||
private static readonly applicationMementos = new Map<string, ScopedMemento<unknown>>();
|
||||
private static readonly profileMementos = new Map<string, ScopedMemento<unknown>>();
|
||||
private static readonly workspaceMementos = new Map<string, ScopedMemento<unknown>>();
|
||||
|
||||
private static readonly COMMON_PREFIX = 'memento/';
|
||||
|
||||
@@ -25,7 +23,7 @@ export class Memento {
|
||||
this.id = Memento.COMMON_PREFIX + id;
|
||||
}
|
||||
|
||||
getMemento(scope: StorageScope, target: StorageTarget): MementoObject {
|
||||
getMemento(scope: StorageScope, target: StorageTarget): Partial<T> {
|
||||
switch (scope) {
|
||||
case StorageScope.WORKSPACE: {
|
||||
let workspaceMemento = Memento.workspaceMementos.get(this.id);
|
||||
@@ -70,7 +68,7 @@ export class Memento {
|
||||
}
|
||||
|
||||
reloadMemento(scope: StorageScope): void {
|
||||
let memento: ScopedMemento | undefined;
|
||||
let memento: ScopedMemento<unknown> | undefined;
|
||||
switch (scope) {
|
||||
case StorageScope.APPLICATION:
|
||||
memento = Memento.applicationMementos.get(this.id);
|
||||
@@ -101,17 +99,17 @@ export class Memento {
|
||||
}
|
||||
}
|
||||
|
||||
class ScopedMemento {
|
||||
class ScopedMemento<T> {
|
||||
|
||||
private mementoObj: MementoObject;
|
||||
private mementoObj: Partial<T>;
|
||||
|
||||
constructor(private id: string, private scope: StorageScope, private target: StorageTarget, private storageService: IStorageService) {
|
||||
this.mementoObj = this.doLoad();
|
||||
}
|
||||
|
||||
private doLoad(): MementoObject {
|
||||
private doLoad(): Partial<T> {
|
||||
try {
|
||||
return this.storageService.getObject<MementoObject>(this.id, this.scope, {});
|
||||
return this.storageService.getObject(this.id, this.scope, {});
|
||||
} catch (error) {
|
||||
// Seeing reports from users unable to open editors
|
||||
// from memento parsing exceptions. Log the contents
|
||||
@@ -123,7 +121,7 @@ class ScopedMemento {
|
||||
return {};
|
||||
}
|
||||
|
||||
getMemento(): MementoObject {
|
||||
getMemento(): Partial<T> {
|
||||
return this.mementoObj;
|
||||
}
|
||||
|
||||
@@ -131,7 +129,7 @@ class ScopedMemento {
|
||||
|
||||
// Clear old
|
||||
for (const name of Object.getOwnPropertyNames(this.mementoObj)) {
|
||||
delete this.mementoObj[name];
|
||||
delete this.mementoObj[name as keyof Partial<T>];
|
||||
}
|
||||
|
||||
// Assign new
|
||||
|
||||
@@ -736,8 +736,8 @@ export class NotificationViewItem extends Disposable implements INotificationVie
|
||||
return false;
|
||||
}
|
||||
|
||||
const primaryActions = (this._actions && this._actions.primary) || [];
|
||||
const otherPrimaryActions = (other.actions && other.actions.primary) || [];
|
||||
const primaryActions = this._actions?.primary || [];
|
||||
const otherPrimaryActions = other.actions?.primary || [];
|
||||
return equals(primaryActions, otherPrimaryActions, (action, otherAction) => (action.id + action.label) === (otherAction.id + otherAction.label));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,7 +660,7 @@ export interface ITreeView extends IDisposable {
|
||||
|
||||
readonly onDidChangeCheckboxState: Event<readonly ITreeItem[]>;
|
||||
|
||||
readonly container: any | undefined;
|
||||
readonly container: unknown /* HTMLElement */ | undefined;
|
||||
|
||||
// checkboxesChanged is a subset of treeItems
|
||||
refresh(treeItems?: readonly ITreeItem[], checkboxesChanged?: readonly ITreeItem[]): Promise<void>;
|
||||
@@ -685,7 +685,7 @@ export interface ITreeView extends IDisposable {
|
||||
|
||||
setFocus(item?: ITreeItem): void;
|
||||
|
||||
show(container: any): void;
|
||||
show(container: unknown /* HTMLElement */): void;
|
||||
}
|
||||
|
||||
export interface IRevealOptions {
|
||||
|
||||
@@ -48,7 +48,7 @@ export class ChatEditor extends EditorPane {
|
||||
return this._scopedContextKeyService;
|
||||
}
|
||||
|
||||
private _memento: Memento | undefined;
|
||||
private _memento: Memento<IChatViewState> | undefined;
|
||||
private _viewState: IChatViewState | undefined;
|
||||
private dimension = new dom.Dimension(0, 0);
|
||||
|
||||
@@ -169,7 +169,7 @@ export class ChatEditor extends EditorPane {
|
||||
|
||||
private updateModel(model: IChatModel, viewState?: IChatViewState): void {
|
||||
this._memento = new Memento('interactive-session-editor-' + CHAT_PROVIDER_ID, this.storageService);
|
||||
this._viewState = viewState ?? this._memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IChatViewState;
|
||||
this._viewState = viewState ?? this._memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
this.widget.setModel(model, { ...this._viewState });
|
||||
}
|
||||
|
||||
|
||||
@@ -610,7 +610,7 @@ class ChatStatusDashboard extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private runCommandAndClose(commandOrFn: string | Function, ...args: any[]): void {
|
||||
private runCommandAndClose(commandOrFn: string | Function, ...args: unknown[]): void {
|
||||
if (typeof commandOrFn === 'function') {
|
||||
commandOrFn(...args);
|
||||
} else {
|
||||
|
||||
@@ -50,7 +50,7 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
|
||||
get widget(): ChatWidget { return this._widget; }
|
||||
|
||||
private readonly modelDisposables = this._register(new DisposableStore());
|
||||
private memento: Memento;
|
||||
private memento: Memento<IViewPaneState>;
|
||||
private readonly viewState: IViewPaneState;
|
||||
|
||||
private _restoringSession: Promise<void> | undefined;
|
||||
@@ -78,11 +78,11 @@ export class ChatViewPane extends ViewPane implements IViewWelcomeDelegate {
|
||||
|
||||
// View state for the ViewPane is currently global per-provider basically, but some other strictly per-model state will require a separate memento.
|
||||
this.memento = new Memento('interactive-session-view-' + CHAT_PROVIDER_ID, this.storageService);
|
||||
this.viewState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IViewPaneState;
|
||||
this.viewState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
|
||||
if (this.chatOptions.location === ChatAgentLocation.Chat && !this.viewState.hasMigratedCurrentSession) {
|
||||
const editsMemento = new Memento('interactive-session-view-' + CHAT_PROVIDER_ID + `-edits`, this.storageService);
|
||||
const lastEditsState = editsMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IViewPaneState;
|
||||
const editsMemento = new Memento<IViewPaneState>('interactive-session-view-' + CHAT_PROVIDER_ID + `-edits`, this.storageService);
|
||||
const lastEditsState = editsMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
if (lastEditsState.sessionId) {
|
||||
this.logService.trace(`ChatViewPane: last edits session was ${lastEditsState.sessionId}`);
|
||||
if (!this.chatService.isPersistedSessionEmpty(lastEditsState.sessionId)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export interface IChatTodoListService {
|
||||
}
|
||||
|
||||
export class ChatTodoListStorage implements IChatTodoListStorage {
|
||||
private memento: Memento;
|
||||
private memento: Memento<Record<string, IChatTodo[]>>;
|
||||
|
||||
constructor(@IStorageService storageService: IStorageService) {
|
||||
this.memento = new Memento('chat-todo-list', storageService);
|
||||
|
||||
@@ -43,7 +43,7 @@ export interface IChatWidgetHistoryService {
|
||||
}
|
||||
|
||||
interface IChatHistory {
|
||||
history: { [providerId: string]: IChatHistoryEntry[] };
|
||||
history?: { [providerId: string]: IChatHistoryEntry[] };
|
||||
}
|
||||
|
||||
export const ChatInputHistoryMaxEntries = 40;
|
||||
@@ -51,7 +51,7 @@ export const ChatInputHistoryMaxEntries = 40;
|
||||
export class ChatWidgetHistoryService implements IChatWidgetHistoryService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
private memento: Memento;
|
||||
private memento: Memento<IChatHistory>;
|
||||
private viewState: IChatHistory;
|
||||
|
||||
private readonly _onDidClearHistory = new Emitter<void>();
|
||||
@@ -60,8 +60,8 @@ export class ChatWidgetHistoryService implements IChatWidgetHistoryService {
|
||||
constructor(
|
||||
@IStorageService storageService: IStorageService
|
||||
) {
|
||||
this.memento = new Memento('interactive-session', storageService);
|
||||
const loadedState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IChatHistory;
|
||||
this.memento = new Memento<IChatHistory>('interactive-session', storageService);
|
||||
const loadedState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
for (const provider in loadedState.history) {
|
||||
// Migration from old format
|
||||
loadedState.history[provider] = loadedState.history[provider].map(entry => typeof entry === 'string' ? { text: entry } : entry);
|
||||
|
||||
@@ -24,7 +24,7 @@ import { IOpenerService } from '../../../../platform/opener/common/opener.js';
|
||||
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
|
||||
import { CommentsViewFilterFocusContextKey, ICommentsView } from './comments.js';
|
||||
import { CommentsFilters, CommentsFiltersChangeEvent, CommentsSortOrder } from './commentsViewActions.js';
|
||||
import { Memento, MementoObject } from '../../../common/memento.js';
|
||||
import { Memento } from '../../../common/memento.js';
|
||||
import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';
|
||||
import { FilterOptions } from './commentsFilterOptions.js';
|
||||
import { CommentThreadApplicability, CommentThreadState } from '../../../../editor/common/languages.js';
|
||||
@@ -45,6 +45,14 @@ export const CONTEXT_KEY_SOME_COMMENTS_EXPANDED = new RawContextKey<boolean>('co
|
||||
export const CONTEXT_KEY_COMMENT_FOCUSED = new RawContextKey<boolean>('commentsView.commentFocused', false);
|
||||
const VIEW_STORAGE_ID = 'commentsViewState';
|
||||
|
||||
interface CommentsViewState {
|
||||
filter?: string;
|
||||
filterHistory?: string[];
|
||||
showResolved?: boolean;
|
||||
showUnresolved?: boolean;
|
||||
sortBy?: CommentsSortOrder;
|
||||
}
|
||||
|
||||
type CommentsTreeNode = CommentsModel | ResourceWithCommentThreads | CommentNode;
|
||||
|
||||
function createResourceCommentsIterator(model: ICommentsModel): Iterable<ITreeElement<CommentsTreeNode>> {
|
||||
@@ -78,8 +86,8 @@ export class CommentsPanel extends FilterViewPane implements ICommentsView {
|
||||
|
||||
private currentHeight = 0;
|
||||
private currentWidth = 0;
|
||||
private readonly viewState: MementoObject;
|
||||
private readonly stateMemento: Memento;
|
||||
private readonly viewState: CommentsViewState;
|
||||
private readonly stateMemento: Memento<CommentsViewState>;
|
||||
private cachedFilterStats: { total: number; filtered: number } | undefined = undefined;
|
||||
|
||||
readonly onDidChangeVisibility = this.onDidChangeBodyVisibility;
|
||||
@@ -152,15 +160,15 @@ export class CommentsPanel extends FilterViewPane implements ICommentsView {
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IPathService private readonly pathService: IPathService,
|
||||
) {
|
||||
const stateMemento = new Memento(VIEW_STORAGE_ID, storageService);
|
||||
const stateMemento = new Memento<CommentsViewState>(VIEW_STORAGE_ID, storageService);
|
||||
const viewState = stateMemento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
super({
|
||||
...options,
|
||||
filterOptions: {
|
||||
placeholder: nls.localize('comments.filter.placeholder', "Filter (e.g. text, author)"),
|
||||
ariaLabel: nls.localize('comments.filter.ariaLabel', "Filter comments"),
|
||||
history: viewState['filterHistory'] || [],
|
||||
text: viewState['filter'] || '',
|
||||
history: viewState.filterHistory || [],
|
||||
text: viewState.filter || '',
|
||||
focusContextKey: CommentsViewFilterFocusContextKey.key
|
||||
}
|
||||
}, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, hoverService);
|
||||
@@ -171,9 +179,9 @@ export class CommentsPanel extends FilterViewPane implements ICommentsView {
|
||||
this.viewState = viewState;
|
||||
|
||||
this.filters = this._register(new CommentsFilters({
|
||||
showResolved: this.viewState['showResolved'] !== false,
|
||||
showUnresolved: this.viewState['showUnresolved'] !== false,
|
||||
sortBy: this.viewState['sortBy'] ?? CommentsSortOrder.ResourceAscending,
|
||||
showResolved: this.viewState.showResolved !== false,
|
||||
showUnresolved: this.viewState.showUnresolved !== false,
|
||||
sortBy: this.viewState.sortBy ?? CommentsSortOrder.ResourceAscending,
|
||||
}, this.contextKeyService));
|
||||
this.filter = new Filter(new FilterOptions(this.filterWidget.getFilterText(), this.filters.showResolved, this.filters.showUnresolved));
|
||||
|
||||
@@ -189,11 +197,11 @@ export class CommentsPanel extends FilterViewPane implements ICommentsView {
|
||||
}
|
||||
|
||||
override saveState(): void {
|
||||
this.viewState['filter'] = this.filterWidget.getFilterText();
|
||||
this.viewState['filterHistory'] = this.filterWidget.getHistory();
|
||||
this.viewState['showResolved'] = this.filters.showResolved;
|
||||
this.viewState['showUnresolved'] = this.filters.showUnresolved;
|
||||
this.viewState['sortBy'] = this.filters.sortBy;
|
||||
this.viewState.filter = this.filterWidget.getFilterText();
|
||||
this.viewState.filterHistory = this.filterWidget.getHistory();
|
||||
this.viewState.showResolved = this.filters.showResolved;
|
||||
this.viewState.showUnresolved = this.filters.showUnresolved;
|
||||
this.viewState.sortBy = this.filters.sortBy;
|
||||
this.stateMemento.saveMemento();
|
||||
super.saveState();
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@ import { customEditorsExtensionPoint, ICustomEditorsExtensionPoint } from './ext
|
||||
import { RegisteredEditorPriority } from '../../../services/editor/common/editorResolverService.js';
|
||||
import { IExtensionPointUser } from '../../../services/extensions/common/extensionsRegistry.js';
|
||||
|
||||
interface CustomEditorsMemento {
|
||||
editors?: CustomEditorDescriptor[];
|
||||
}
|
||||
|
||||
export class ContributedCustomEditors extends Disposable {
|
||||
|
||||
private static readonly CUSTOM_EDITORS_STORAGE_ID = 'customEditors';
|
||||
private static readonly CUSTOM_EDITORS_ENTRY_ID = 'editors';
|
||||
|
||||
private readonly _editors = new Map<string, CustomEditorInfo>();
|
||||
private readonly _memento: Memento;
|
||||
private readonly _memento: Memento<CustomEditorsMemento>;
|
||||
|
||||
constructor(storageService: IStorageService) {
|
||||
super();
|
||||
|
||||
@@ -45,7 +45,6 @@ import { alert } from '../../../../base/browser/ui/aria/aria.js';
|
||||
import { EXTENSION_CATEGORIES } from '../../../../platform/extensions/common/extensions.js';
|
||||
import { Registry } from '../../../../platform/registry/common/platform.js';
|
||||
import { ILabelService } from '../../../../platform/label/common/label.js';
|
||||
import { MementoObject } from '../../../common/memento.js';
|
||||
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
|
||||
import { IPreferencesService } from '../../../services/preferences/common/preferences.js';
|
||||
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from '../../../common/theme.js';
|
||||
@@ -92,6 +91,10 @@ export const ExtensionsSearchValueContext = new RawContextKey<string>('extension
|
||||
|
||||
const REMOTE_CATEGORY: ILocalizedString = localize2({ key: 'remote', comment: ['Remote as in remote machine'] }, "Remote");
|
||||
|
||||
interface IExtensionsViewletState {
|
||||
'query.value'?: string;
|
||||
}
|
||||
|
||||
export class ExtensionsViewletViewsContribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private readonly container: ViewContainer;
|
||||
@@ -506,7 +509,7 @@ export class ExtensionsViewletViewsContribution extends Disposable implements IW
|
||||
|
||||
}
|
||||
|
||||
export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IExtensionsViewPaneContainer {
|
||||
export class ExtensionsViewPaneContainer extends ViewPaneContainer<IExtensionsViewletState> implements IExtensionsViewPaneContainer {
|
||||
|
||||
private readonly extensionsSearchValueContextKey: IContextKey<string>;
|
||||
private readonly defaultViewsContextKey: IContextKey<boolean>;
|
||||
@@ -534,7 +537,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
private header: HTMLElement | undefined;
|
||||
private searchBox: SuggestEnabledInput | undefined;
|
||||
private notificationContainer: HTMLElement | undefined;
|
||||
private readonly searchViewletState: MementoObject;
|
||||
private readonly searchViewletState: IExtensionsViewletState;
|
||||
private extensionGalleryManifest: IExtensionGalleryManifest | null = null;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -16,7 +16,7 @@ interface RegisteredExternalOpener {
|
||||
}
|
||||
|
||||
interface OpenersMemento {
|
||||
[id: string]: RegisteredExternalOpener;
|
||||
[id: string]: RegisteredExternalOpener | undefined;
|
||||
}
|
||||
|
||||
export class ContributedExternalUriOpenersStore extends Disposable {
|
||||
@@ -24,7 +24,7 @@ export class ContributedExternalUriOpenersStore extends Disposable {
|
||||
private static readonly STORAGE_ID = 'externalUriOpeners';
|
||||
|
||||
private readonly _openers = new Map<string, RegisteredExternalOpener>();
|
||||
private readonly _memento: Memento;
|
||||
private readonly _memento: Memento<OpenersMemento>;
|
||||
private _mementoObject: OpenersMemento;
|
||||
|
||||
constructor(
|
||||
@@ -36,7 +36,9 @@ export class ContributedExternalUriOpenersStore extends Disposable {
|
||||
this._memento = new Memento(ContributedExternalUriOpenersStore.STORAGE_ID, storageService);
|
||||
this._mementoObject = this._memento.getMemento(StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
for (const [id, value] of Object.entries(this._mementoObject || {})) {
|
||||
this.add(id, value.extensionId, { isCurrentlyRegistered: false });
|
||||
if (value) {
|
||||
this.add(id, value.extensionId, { isCurrentlyRegistered: false });
|
||||
}
|
||||
}
|
||||
|
||||
this.invalidateOpenersOnExtensionsChanged();
|
||||
|
||||
@@ -446,7 +446,7 @@ export class ExplorerService implements IExplorerService {
|
||||
if (item === undefined || ignore) {
|
||||
return true;
|
||||
}
|
||||
if (this.revealExcludeMatcher.matches(item.resource, name => !!(item.parent && item.parent.getChild(name)))) {
|
||||
if (this.revealExcludeMatcher.matches(item.resource, name => !!(item.parent?.getChild(name)))) {
|
||||
return false;
|
||||
}
|
||||
const root = item.root;
|
||||
@@ -521,7 +521,7 @@ function doesFileEventAffect(item: ExplorerItem, view: IExplorerView, events: Fi
|
||||
}
|
||||
|
||||
function getRevealExcludes(configuration: IFilesConfiguration): IExpression {
|
||||
const revealExcludes = configuration && configuration.explorer && configuration.explorer.autoRevealExclude;
|
||||
const revealExcludes = configuration?.explorer?.autoRevealExclude;
|
||||
|
||||
if (!revealExcludes) {
|
||||
return {};
|
||||
|
||||
@@ -196,7 +196,7 @@ export class ExplorerViewPaneContainer extends ViewPaneContainer {
|
||||
let delay = 0;
|
||||
|
||||
const config = this.configurationService.getValue<IFilesConfiguration>();
|
||||
if (!!config.workbench?.editor?.enablePreview) {
|
||||
if (config.workbench?.editor?.enablePreview) {
|
||||
// delay open editors view when preview is enabled
|
||||
// to accomodate for the user doing a double click
|
||||
// to pin the editor.
|
||||
|
||||
@@ -78,14 +78,6 @@ export const UPLOAD_LABEL = nls.localize('upload', "Upload...");
|
||||
const CONFIRM_DELETE_SETTING_KEY = 'explorer.confirmDelete';
|
||||
const MAX_UNDO_FILE_SIZE = 5000000; // 5mb
|
||||
|
||||
function onError(notificationService: INotificationService, error: any): void {
|
||||
if (error.message === 'string') {
|
||||
error = error.message;
|
||||
}
|
||||
|
||||
notificationService.error(toErrorMessage(error, false));
|
||||
}
|
||||
|
||||
async function refreshIfSeparator(value: string, explorerService: IExplorerService): Promise<void> {
|
||||
if (value && ((value.indexOf('/') >= 0) || (value.indexOf('\\') >= 0))) {
|
||||
// New input contains separator, multiple resources will get created workaround for #68204
|
||||
@@ -600,7 +592,7 @@ abstract class BaseSaveAllAction extends Action {
|
||||
try {
|
||||
await this.doRun(context);
|
||||
} catch (error) {
|
||||
onError(this.notificationService, error);
|
||||
this.notificationService.error(toErrorMessage(error, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1281,7 +1273,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor, fileList?: Fi
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
onError(notificationService, new Error(nls.localize('fileDeleted', "The file(s) to paste have been deleted or moved since you copied them. {0}", getErrorMessage(e))));
|
||||
notificationService.error(toErrorMessage(new Error(nls.localize('fileDeleted', "The file(s) to paste have been deleted or moved since you copied them. {0}", getErrorMessage(e))), false));
|
||||
} finally {
|
||||
if (pasteShouldMove) {
|
||||
// Cut is done. Make sure to clear cut state.
|
||||
|
||||
@@ -280,7 +280,7 @@ export class BrowserFileUpload {
|
||||
operation.filesTotal += childEntries.length;
|
||||
|
||||
// Split up files from folders to upload
|
||||
const folderTarget = target && target.getChild(entry.name) || undefined;
|
||||
const folderTarget = target?.getChild(entry.name) || undefined;
|
||||
const fileChildEntries: IWebkitDataTransferItemEntry[] = [];
|
||||
const folderChildEntries: IWebkitDataTransferItemEntry[] = [];
|
||||
for (const childEntry of childEntries) {
|
||||
|
||||
@@ -159,7 +159,7 @@ export function getMultiSelectedResources(commandArg: unknown, listService: ILis
|
||||
}
|
||||
|
||||
const result = getResourceForCommand(commandArg, editorSerice, listService);
|
||||
return !!result ? [result] : [];
|
||||
return result ? [result] : [];
|
||||
}
|
||||
|
||||
export function getOpenEditorsViewMultiSelection(accessor: ServicesAccessor): Array<IEditorIdentifier> | undefined {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user