[eslint] Allow `any` in rest parameters.
This enables the `ignoreRestArgs` setting[^1] for the ESLint rule
@typescript-eslint/no-explicit-any, which allows the use of `any`
in rest parameters (which is actually a valid use case for `any`)
and thereby reduces the number of pragmas in the code base where
we need to explicitly silence ESLint about this.
Drive-by-fixes: Refine some uses of `any` that can now be removed, and
refactor the heap snapshot worker proxy to make it easier to read and
type properly.
[^1]: https://typescript-eslint.io/rules/no-explicit-any/#ignorerestargs
Bug: b:319814509, chromium:1172300
Change-Id: I713f1fbf2a91348d422fb567c50d08d870e348cf
Doc: http://go/chrome-devtools:eslint-pain-points-design
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5204645
Reviewed-by: Philip Pfaffe <[email protected]>
Commit-Queue: Benedikt Meurer <[email protected]>
Reviewed-by: Simon Zünd <[email protected]>
diff --git a/.eslintrc.js b/.eslintrc.js
index 6daeb50..a81c7dd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -115,7 +115,12 @@
'@typescript-eslint/naming-convention':
[2, {'selector': 'interface', 'format': ['PascalCase'], 'custom': {'regex': '^I[A-Z]', 'match': false}}],
'@typescript-eslint/explicit-member-accessibility': [0],
- '@typescript-eslint/no-explicit-any': 2,
+ '@typescript-eslint/no-explicit-any': [
+ "error",
+ {
+ "ignoreRestArgs": true
+ }
+ ],
// Closure does not properly typecheck default exports
'import/no-default-export': 2,
diff --git a/front_end/core/common/Object.ts b/front_end/core/common/Object.ts
index 7bb741a..e7fd384 100644
--- a/front_end/core/common/Object.ts
+++ b/front_end/core/common/Object.ts
@@ -115,7 +115,6 @@
}
}
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Constructor = new (...args: any[]) => {};
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
diff --git a/front_end/core/common/Revealer.ts b/front_end/core/common/Revealer.ts
index 036d278..3bcf7ee 100644
--- a/front_end/core/common/Revealer.ts
+++ b/front_end/core/common/Revealer.ts
@@ -153,7 +153,6 @@
}
export interface RevealerRegistration<T> {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
contextTypes: () => Array<abstract new(...any: any[]) => T>;
loadRevealer: () => Promise<Revealer<T>>;
destination?: RevealerDestination;
diff --git a/front_end/models/extensions/ExtensionAPI.ts b/front_end/models/extensions/ExtensionAPI.ts
index 1a01f35..f678096 100644
--- a/front_end/models/extensions/ExtensionAPI.ts
+++ b/front_end/models/extensions/ExtensionAPI.ts
@@ -360,12 +360,7 @@
nextObjectId(): string;
}
- // We cannot use the stronger `unknown` type in place of `any` in the following type definition. The type is used as
- // the right-hand side of `extends` in a few places, which doesn't narrow `unknown`. Without narrowing, overload
- // resolution and meaningful type inference of arguments break, for example.
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- export type Callable = (...args: any) => void;
+ export type Callable = (...args: any[]) => void;
export interface EventSink<ListenerT extends Callable> extends PublicAPI.Chrome.DevTools.EventSink<ListenerT> {
_type: string;
diff --git a/front_end/panels/profiler/HeapSnapshotProxy.ts b/front_end/panels/profiler/HeapSnapshotProxy.ts
index e2ad0bd..4426fde 100644
--- a/front_end/panels/profiler/HeapSnapshotProxy.ts
+++ b/front_end/panels/profiler/HeapSnapshotProxy.ts
@@ -29,8 +29,9 @@
*/
import * as Common from '../../core/common/common.js';
-import type * as HeapSnapshotModel from '../../models/heap_snapshot_model/heap_snapshot_model.js';
import * as i18n from '../../core/i18n/i18n.js';
+import type * as HeapSnapshotModel from '../../models/heap_snapshot_model/heap_snapshot_model.js';
+
import {type ChildrenProvider} from './ChildrenProvider.js';
const UIStrings = {
@@ -91,19 +92,22 @@
this.postMessage({callId: this.nextCallId++, disposition: 'dispose', objectId: objectId});
}
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- evaluateForTest(script: string, callback: (arg0: any) => void): void {
+ evaluateForTest(script: string, callback: (...arg0: any[]) => void): void {
const callId = this.nextCallId++;
this.callbacks.set(callId, callback);
this.postMessage({callId: callId, disposition: 'evaluateForTest', source: script});
}
callFactoryMethod<T extends Object>(
- callback: ((...arg0: unknown[]) => void)|null, objectId: string, methodName: string,
- proxyConstructor: new(...arg1: unknown[]) => T): Object|null {
+ callback: null, objectId: string, methodName: string, proxyConstructor: new(...arg1: any[]) => T,
+ ...methodArguments: any[]): T;
+ callFactoryMethod<T extends Object>(
+ callback: ((...arg0: any[]) => void), objectId: string, methodName: string,
+ proxyConstructor: new(...arg1: any[]) => T, ...methodArguments: any[]): null;
+ callFactoryMethod<T extends Object>(
+ callback: ((...arg0: any[]) => void)|null, objectId: string, methodName: string,
+ proxyConstructor: new(...arg1: any[]) => T, ...methodArguments: any[]): T|null {
const callId = this.nextCallId++;
- const methodArguments = Array.prototype.slice.call(arguments, 4);
const newObjectId = this.nextObjectId++;
if (callback) {
@@ -131,11 +135,9 @@
return new proxyConstructor(this, newObjectId);
}
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- callMethod(callback: (arg0: any) => void, objectId: string, methodName: string): void {
+ callMethod(callback: (...arg0: any[]) => void, objectId: string, methodName: string, ...methodArguments: any[]):
+ void {
const callId = this.nextCallId++;
- const methodArguments = Array.prototype.slice.call(arguments, 3);
if (callback) {
this.callbacks.set(callId, callback);
}
@@ -222,19 +224,6 @@
this.objectId = objectId;
}
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- callWorker(workerMethodName: string, args: any[]): any {
- args.splice(1, 0, this.objectId);
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const worker = (this.worker as any)[workerMethodName];
- if (!worker) {
- throw new Error(`Could not find worker with name ${workerMethodName}.`);
- }
- return worker.apply(this.worker, args);
- }
-
dispose(): void {
this.worker.disposeObject(this.objectId);
}
@@ -243,21 +232,20 @@
this.worker.dispose();
}
- callFactoryMethod<T>(
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- _callback: ((...arg0: any[]) => void)|null, _methodName: string, _proxyConstructor: new(...arg1: any[]) => T,
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/naming-convention
- ..._var_args: any[]): T {
- return this.callWorker('callFactoryMethod', Array.prototype.slice.call(arguments, 0));
+ callFactoryMethod<T extends Object>(methodName: string, proxyConstructor: new(...arg1: any[]) => T, ...args: any[]):
+ T {
+ return this.worker.callFactoryMethod(null, String(this.objectId), methodName, proxyConstructor, ...args);
}
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/naming-convention
- callMethodPromise<T>(_methodName: string, ..._var_args: any[]): Promise<T> {
- const args = Array.prototype.slice.call(arguments);
- return new Promise(resolve => this.callWorker('callMethod', [resolve, ...args]));
+ callFactoryMethodPromise<T extends Object>(
+ methodName: string, proxyConstructor: new(...arg1: any[]) => T, ...args: any[]): Promise<T> {
+ return new Promise(
+ resolve =>
+ this.worker.callFactoryMethod(resolve, String(this.objectId), methodName, proxyConstructor, ...args));
+ }
+
+ callMethodPromise<T>(methodName: string, ...args: any[]): Promise<T> {
+ return new Promise(resolve => this.worker.callMethod(resolve, String(this.objectId), methodName, ...args));
}
}
@@ -278,8 +266,7 @@
async close(): Promise<void> {
await this.callMethodPromise('close');
- const snapshotProxy = await new Promise<HeapSnapshotProxy>(
- resolve => this.callFactoryMethod(resolve, 'buildSnapshot', HeapSnapshotProxy));
+ const snapshotProxy = await this.callFactoryMethodPromise('buildSnapshot', HeapSnapshotProxy);
this.dispose();
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
// @ts-expect-error
@@ -329,32 +316,28 @@
}
createEdgesProvider(nodeIndex: number): HeapSnapshotProviderProxy {
- return this.callFactoryMethod(null, 'createEdgesProvider', HeapSnapshotProviderProxy, nodeIndex);
+ return this.callFactoryMethod('createEdgesProvider', HeapSnapshotProviderProxy, nodeIndex);
}
createRetainingEdgesProvider(nodeIndex: number): HeapSnapshotProviderProxy {
- return this.callFactoryMethod(null, 'createRetainingEdgesProvider', HeapSnapshotProviderProxy, nodeIndex);
+ return this.callFactoryMethod('createRetainingEdgesProvider', HeapSnapshotProviderProxy, nodeIndex);
}
- createAddedNodesProvider(baseSnapshotId: string, className: string): HeapSnapshotProviderProxy|null {
- return this.callFactoryMethod(
- null, 'createAddedNodesProvider', HeapSnapshotProviderProxy, baseSnapshotId, className);
+ createAddedNodesProvider(baseSnapshotId: string, className: string): HeapSnapshotProviderProxy {
+ return this.callFactoryMethod('createAddedNodesProvider', HeapSnapshotProviderProxy, baseSnapshotId, className);
}
- createDeletedNodesProvider(nodeIndexes: number[]): HeapSnapshotProviderProxy|null {
- return this.callFactoryMethod(null, 'createDeletedNodesProvider', HeapSnapshotProviderProxy, nodeIndexes);
+ createDeletedNodesProvider(nodeIndexes: number[]): HeapSnapshotProviderProxy {
+ return this.callFactoryMethod('createDeletedNodesProvider', HeapSnapshotProviderProxy, nodeIndexes);
}
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- createNodesProvider(filter: (arg0: any) => boolean): HeapSnapshotProviderProxy|null {
- return this.callFactoryMethod(null, 'createNodesProvider', HeapSnapshotProviderProxy, filter);
+ createNodesProvider(filter: (...args: any[]) => boolean): HeapSnapshotProviderProxy {
+ return this.callFactoryMethod('createNodesProvider', HeapSnapshotProviderProxy, filter);
}
createNodesProviderForClass(className: string, nodeFilter: HeapSnapshotModel.HeapSnapshotModel.NodeFilter):
- HeapSnapshotProviderProxy|null {
- return this.callFactoryMethod(
- null, 'createNodesProviderForClass', HeapSnapshotProviderProxy, className, nodeFilter);
+ HeapSnapshotProviderProxy {
+ return this.callFactoryMethod('createNodesProviderForClass', HeapSnapshotProviderProxy, className, nodeFilter);
}
allocationTracesTops(): Promise<HeapSnapshotModel.HeapSnapshotModel.SerializedAllocationNode[]> {
diff --git a/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts b/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts
index 509b97a..6ba1af8 100644
--- a/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts
+++ b/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts
@@ -16,7 +16,6 @@
}
}
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Constructor<T extends UI.Widget.Widget> = new (...args: any[]) => T;
export type LegacyWrapper<T extends UI.Widget.Widget, Component extends WrappableComponent<T>> = {
@@ -29,7 +28,6 @@
return new class extends base {
#component: Component;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(..._args: any[]) {
super(/* isWebComponent=*/ true);
this.#component = component;
diff --git a/front_end/ui/legacy/Context.ts b/front_end/ui/legacy/Context.ts
index 0c1e85a..62d979d 100644
--- a/front_end/ui/legacy/Context.ts
+++ b/front_end/ui/legacy/Context.ts
@@ -10,8 +10,6 @@
let contextInstance: Context|undefined;
interface ConstructorFn<T> {
- // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
new(...args: any[]): T;
}
diff --git a/front_end/ui/legacy/ContextMenu.ts b/front_end/ui/legacy/ContextMenu.ts
index e315db1..d2312ed 100644
--- a/front_end/ui/legacy/ContextMenu.ts
+++ b/front_end/ui/legacy/ContextMenu.ts
@@ -698,8 +698,7 @@
}
export interface ProviderRegistration<T> {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- contextTypes: () => Array<abstract new(...any: any) => T>;
+ contextTypes: () => Array<abstract new(...any: any[]) => T>;
loadProvider: () => Promise<Provider<T>>;
experiment?: Root.Runtime.ExperimentName;
}
diff --git a/front_end/ui/legacy/Fragment.ts b/front_end/ui/legacy/Fragment.ts
index 424e90a..91a4071 100644
--- a/front_end/ui/legacy/Fragment.ts
+++ b/front_end/ui/legacy/Fragment.ts
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/* eslint-disable @typescript-eslint/no-explicit-any */
-
function getNodeData(node: Node): string {
return (node as unknown as {
data: string,
@@ -143,6 +141,7 @@
return {template, binds};
}
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
private static render(template: Template, values: any[]): Fragment {
const content = template.template.ownerDocument.importNode(template.template.content, true);
const resultElement = (content.firstChild === content.lastChild ? content.firstChild : content) as Element;
@@ -190,6 +189,7 @@
return result;
}
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
private static nodeForValue(value: any): Node {
if (value instanceof Node) {
return value;