chore: implement use-using rule (#10798)
This commit is contained in:
parent
085936bd7e
commit
dca327f99f
@ -1,3 +1,6 @@
|
||||
const rulesDirPlugin = require('eslint-plugin-rulesdir');
|
||||
rulesDirPlugin.RULES_DIR = 'tools/eslint/lib';
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
@ -136,10 +139,12 @@ module.exports = {
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/stylistic',
|
||||
],
|
||||
plugins: ['eslint-plugin-tsdoc', 'local'],
|
||||
plugins: ['eslint-plugin-tsdoc', 'rulesdir'],
|
||||
rules: {
|
||||
// Keeps comments formatted.
|
||||
'local/prettier-comments': 'error',
|
||||
'rulesdir/prettier-comments': 'error',
|
||||
// Enforces clean up of used resources.
|
||||
'rulesdir/use-using': 'off',
|
||||
// Brackets keep code readable.
|
||||
curly: ['error', 'all'],
|
||||
// Brackets keep code readable and `return` intentions clear.
|
||||
|
53
package-lock.json
generated
53
package-lock.json
generated
@ -9,7 +9,8 @@
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"test",
|
||||
"test/installation"
|
||||
"test/installation",
|
||||
"tools/eslint"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@actions/core": "1.10.0",
|
||||
@ -45,9 +46,9 @@
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-formatter-codeframe": "7.32.1",
|
||||
"eslint-plugin-import": "2.28.1",
|
||||
"eslint-plugin-local": "1.0.0",
|
||||
"eslint-plugin-mocha": "10.1.0",
|
||||
"eslint-plugin-prettier": "5.0.0",
|
||||
"eslint-plugin-rulesdir": "0.2.2",
|
||||
"eslint-plugin-tsdoc": "0.2.17",
|
||||
"eslint-plugin-unused-imports": "3.0.0",
|
||||
"esprima": "4.0.1",
|
||||
@ -80,6 +81,12 @@
|
||||
"zod": "3.22.2"
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"name": "@puppeteer/eslint",
|
||||
"version": "0.1.0",
|
||||
"extraneous": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
|
||||
@ -1873,6 +1880,10 @@
|
||||
"resolved": "packages/browsers",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@puppeteer/eslint": {
|
||||
"resolved": "tools/eslint",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@puppeteer/ng-schematics": {
|
||||
"resolved": "packages/ng-schematics",
|
||||
"link": true
|
||||
@ -4523,11 +4534,6 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-local": {
|
||||
"version": "1.0.0",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-mocha": {
|
||||
"version": "10.1.0",
|
||||
"dev": true,
|
||||
@ -4622,6 +4628,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-rulesdir": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.2.tgz",
|
||||
"integrity": "sha512-qhBtmrWgehAIQeMDJ+Q+PnOz1DWUZMPeVrI0wE9NZtnpIMFUfh3aPKFYt2saeMSemZRrvUtjWfYwepsC8X+mjQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-tsdoc": {
|
||||
"version": "0.2.17",
|
||||
"dev": true,
|
||||
@ -11191,6 +11206,12 @@
|
||||
"ws": "8.13.0"
|
||||
}
|
||||
},
|
||||
"packages/ts-plugin": {
|
||||
"name": "@puppeteer/ts-plugin",
|
||||
"version": "0.1.0",
|
||||
"extraneous": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"test": {
|
||||
"name": "@puppeteer-test/test",
|
||||
"version": "latest",
|
||||
@ -11205,6 +11226,11 @@
|
||||
"glob": "10.3.3",
|
||||
"mocha": "10.2.0"
|
||||
}
|
||||
},
|
||||
"tools/eslint": {
|
||||
"name": "@puppeteer/eslint",
|
||||
"version": "0.1.0",
|
||||
"license": "Apache-2.0"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@ -12367,6 +12393,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@puppeteer/eslint": {
|
||||
"version": "file:tools/eslint"
|
||||
},
|
||||
"@puppeteer/ng-schematics": {
|
||||
"version": "file:packages/ng-schematics",
|
||||
"requires": {
|
||||
@ -14304,10 +14333,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-local": {
|
||||
"version": "1.0.0",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-mocha": {
|
||||
"version": "10.1.0",
|
||||
"dev": true,
|
||||
@ -14357,6 +14382,12 @@
|
||||
"synckit": "^0.8.5"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-rulesdir": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.2.tgz",
|
||||
"integrity": "sha512-qhBtmrWgehAIQeMDJ+Q+PnOz1DWUZMPeVrI0wE9NZtnpIMFUfh3aPKFYt2saeMSemZRrvUtjWfYwepsC8X+mjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-tsdoc": {
|
||||
"version": "0.2.17",
|
||||
"dev": true,
|
||||
|
@ -22,6 +22,7 @@
|
||||
"lint:prettier": "prettier --check .",
|
||||
"lint": "run-s lint:prettier lint:eslint",
|
||||
"postinstall": "npm run postinstall --workspaces --if-present",
|
||||
"prepare": "npm run prepare --workspaces --if-present",
|
||||
"test-install": "npm run test --workspace @puppeteer-test/installation",
|
||||
"test-types": "tsd -t packages/puppeteer",
|
||||
"test:chrome:headful": "wireit",
|
||||
@ -137,7 +138,7 @@
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-formatter-codeframe": "7.32.1",
|
||||
"eslint-plugin-import": "2.28.1",
|
||||
"eslint-plugin-local": "1.0.0",
|
||||
"eslint-plugin-rulesdir": "0.2.2",
|
||||
"eslint-plugin-mocha": "10.1.0",
|
||||
"eslint-plugin-prettier": "5.0.0",
|
||||
"eslint-plugin-tsdoc": "0.2.17",
|
||||
@ -174,6 +175,7 @@
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"test",
|
||||
"test/installation"
|
||||
"test/installation",
|
||||
"tools/eslint"
|
||||
]
|
||||
}
|
||||
|
34
tools/eslint/package.json
Normal file
34
tools/eslint/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@puppeteer/eslint",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/puppeteer/puppeteer/tree/main/tools/eslint"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"prepare": "wireit"
|
||||
},
|
||||
"wireit": {
|
||||
"build": {
|
||||
"command": "tsc -b",
|
||||
"clean": "if-file-deleted",
|
||||
"files": [
|
||||
"src/**"
|
||||
],
|
||||
"output": [
|
||||
"lib/**",
|
||||
"tsconfig.tsbuildinfo"
|
||||
]
|
||||
},
|
||||
"prepare": {
|
||||
"dependencies": [
|
||||
"build"
|
||||
]
|
||||
}
|
||||
},
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0"
|
||||
}
|
@ -1,5 +1,26 @@
|
||||
/**
|
||||
* Copyright 2023 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// @ts-nocheck
|
||||
// TODO: We should convert this to types.
|
||||
|
||||
const prettier = require('@prettier/sync');
|
||||
const prettierConfig = require('./.prettierrc.cjs');
|
||||
|
||||
const prettierConfigPath = '../../../.prettierrc.cjs';
|
||||
const prettierConfig = require(prettierConfigPath);
|
||||
|
||||
const cleanupBlockComment = value => {
|
||||
return value
|
||||
@ -46,7 +67,7 @@ const buildBlockComment = (value, offset) => {
|
||||
/**
|
||||
* @type import("eslint").Rule.RuleModule
|
||||
*/
|
||||
const rule = {
|
||||
const prettierCommentsRule = {
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
@ -85,8 +106,4 @@ const rule = {
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
'prettier-comments': rule,
|
||||
},
|
||||
};
|
||||
module.exports = prettierCommentsRule;
|
89
tools/eslint/src/use-using.ts
Normal file
89
tools/eslint/src/use-using.ts
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright 2023 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {ESLintUtils, TSESTree} from '@typescript-eslint/utils';
|
||||
import type {
|
||||
RuleListener,
|
||||
RuleModule,
|
||||
} from '@typescript-eslint/utils/ts-eslint';
|
||||
|
||||
const usingSymbols = ['ElementHandle', 'JSHandle'];
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(name => {
|
||||
return `https://github.com/puppeteer/puppeteer/tree/main/tools/eslint/${name}.js`;
|
||||
});
|
||||
|
||||
const useUsingRule: RuleModule<'useUsing', [], RuleListener> = createRule<
|
||||
[],
|
||||
'useUsing'
|
||||
>({
|
||||
name: 'use-using',
|
||||
meta: {
|
||||
docs: {
|
||||
description: "Requires 'using' for element/JS handles.",
|
||||
requiresTypeChecking: true,
|
||||
},
|
||||
messages: {
|
||||
useUsing: "Use 'using'.",
|
||||
},
|
||||
schema: [],
|
||||
type: 'problem',
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
const services = ESLintUtils.getParserServices(context);
|
||||
const checker = services.program.getTypeChecker();
|
||||
|
||||
return {
|
||||
VariableDeclaration(node): void {
|
||||
if (['using', 'await using'].includes(node.kind)) {
|
||||
return;
|
||||
}
|
||||
for (const declaration of node.declarations) {
|
||||
if (declaration.id.type === TSESTree.AST_NODE_TYPES.Identifier) {
|
||||
const tsNode = services.esTreeNodeToTSNodeMap.get(declaration.id);
|
||||
const type = checker.getTypeAtLocation(tsNode);
|
||||
let isElementHandleReference = false;
|
||||
if (type.isUnionOrIntersection()) {
|
||||
for (const member of type.types) {
|
||||
if (
|
||||
member.symbol !== undefined &&
|
||||
usingSymbols.includes(member.symbol.escapedName as string)
|
||||
) {
|
||||
isElementHandleReference = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isElementHandleReference =
|
||||
type.symbol !== undefined
|
||||
? usingSymbols.includes(type.symbol.escapedName as string)
|
||||
: false;
|
||||
}
|
||||
if (isElementHandleReference) {
|
||||
context.report({
|
||||
node: declaration.id,
|
||||
messageId: 'useUsing',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export = useUsingRule;
|
14
tools/eslint/tsconfig.json
Normal file
14
tools/eslint/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"sourceMap": false,
|
||||
"composite": false,
|
||||
"removeComments": true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user