From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- remote/test/puppeteer/tools/eslint/package.json | 37 ++++++++ .../puppeteer/tools/eslint/src/check-license.ts | 83 ++++++++++++++++++ .../test/puppeteer/tools/eslint/src/extensions.ts | 48 +++++++++++ .../tools/eslint/src/prettier-comments.js | 99 ++++++++++++++++++++++ .../test/puppeteer/tools/eslint/src/use-using.ts | 85 +++++++++++++++++++ remote/test/puppeteer/tools/eslint/tsconfig.json | 14 +++ remote/test/puppeteer/tools/eslint/tsdoc.json | 15 ++++ 7 files changed, 381 insertions(+) create mode 100644 remote/test/puppeteer/tools/eslint/package.json create mode 100644 remote/test/puppeteer/tools/eslint/src/check-license.ts create mode 100644 remote/test/puppeteer/tools/eslint/src/extensions.ts create mode 100644 remote/test/puppeteer/tools/eslint/src/prettier-comments.js create mode 100644 remote/test/puppeteer/tools/eslint/src/use-using.ts create mode 100644 remote/test/puppeteer/tools/eslint/tsconfig.json create mode 100644 remote/test/puppeteer/tools/eslint/tsdoc.json (limited to 'remote/test/puppeteer/tools/eslint') diff --git a/remote/test/puppeteer/tools/eslint/package.json b/remote/test/puppeteer/tools/eslint/package.json new file mode 100644 index 0000000000..190367ae43 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/package.json @@ -0,0 +1,37 @@ +{ + "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", + "devDependencies": { + "@prettier/sync": "0.5.0" + } +} diff --git a/remote/test/puppeteer/tools/eslint/src/check-license.ts b/remote/test/puppeteer/tools/eslint/src/check-license.ts new file mode 100644 index 0000000000..7ae1a54384 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/src/check-license.ts @@ -0,0 +1,83 @@ +/** + * @license + * Copyright 2024 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import type {TSESTree} from '@typescript-eslint/utils'; +import {ESLintUtils} from '@typescript-eslint/utils'; + +const createRule = ESLintUtils.RuleCreator(name => { + return `https://github.com/puppeteer/puppeteer/tree/main/tools/eslint/${name}.ts`; +}); + +const copyrightPattern = /Copyright ([0-9]{4}) Google Inc\./; + +// const currentYear = new Date().getFullYear; + +// const licenseHeader = `/** +// * @license +// * Copyright ${currentYear} Google Inc. +// * SPDX-License-Identifier: Apache-2.0 +// */`; + +const enforceLicenseRule = createRule<[], 'licenseRule'>({ + name: 'check-license', + meta: { + type: 'layout', + docs: { + description: 'Validate existence of license header', + requiresTypeChecking: false, + }, + fixable: undefined, // TODO: change to 'code' once fixer works. + schema: [], + messages: { + licenseRule: 'Add license header.', + }, + }, + defaultOptions: [], + create(context) { + const sourceCode = context.sourceCode; + const comments = sourceCode.getAllComments(); + const header = + comments[0]?.type === 'Block' && isHeaderComment(comments[0]) + ? comments[0] + : null; + + function isHeaderComment(comment: TSESTree.Comment) { + if (comment && comment.range[0] >= 0 && comment.range[1] <= 88) { + return true; + } else { + return false; + } + } + + return { + Program(node) { + if ( + header && + header.value.includes('@license') && + header.value.includes('SPDX-License-Identifier: Apache-2.0') && + copyrightPattern.test(header.value) + ) { + return; + } + + // Add header license + if (!header || !header.value.includes('@license')) { + // const startLoc: [number, number] = [0, 88]; + context.report({ + node: node, + messageId: 'licenseRule', + // TODO: fix the fixer. + // fix(fixer) { + // return fixer.insertTextBeforeRange(startLoc, licenseHeader); + // }, + }); + } + }, + }; + }, +}); + +export = enforceLicenseRule; diff --git a/remote/test/puppeteer/tools/eslint/src/extensions.ts b/remote/test/puppeteer/tools/eslint/src/extensions.ts new file mode 100644 index 0000000000..89b9279625 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/src/extensions.ts @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2023 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import {ESLintUtils} from '@typescript-eslint/utils'; + +const createRule = ESLintUtils.RuleCreator(name => { + return `https://github.com/puppeteer/puppeteer/tree/main/tools/eslint/${name}.js`; +}); + +const enforceExtensionRule = createRule<[], 'extensionsRule'>({ + name: 'extensions', + meta: { + docs: { + description: 'Requires `.js` for imports', + requiresTypeChecking: false, + }, + messages: { + extensionsRule: 'Add `.js` to import.', + }, + schema: [], + fixable: 'code', + type: 'problem', + }, + defaultOptions: [], + create(context) { + return { + ImportDeclaration(node): void { + const file = node.source.value.split('/').pop(); + + if (!node.source.value.startsWith('.') || file?.includes('.')) { + return; + } + context.report({ + node: node.source, + messageId: 'extensionsRule', + fix(fixer) { + return fixer.replaceText(node.source, `'${node.source.value}.js'`); + }, + }); + }, + }; + }, +}); + +export = enforceExtensionRule; diff --git a/remote/test/puppeteer/tools/eslint/src/prettier-comments.js b/remote/test/puppeteer/tools/eslint/src/prettier-comments.js new file mode 100644 index 0000000000..3cbaad2909 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/src/prettier-comments.js @@ -0,0 +1,99 @@ +/** + * @license + * Copyright 2023 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +// @ts-nocheck +// TODO: We should convert this to types. + +const prettier = require('@prettier/sync'); + +const prettierConfigPath = '../../../.prettierrc.cjs'; +const prettierConfig = require(prettierConfigPath); + +const cleanupBlockComment = value => { + return value + .trim() + .split('\n') + .map(value => { + value = value.trim(); + if (value.startsWith('*')) { + value = value.slice(1); + if (value.startsWith(' ')) { + value = value.slice(1); + } + } + return value.trimEnd(); + }) + .join('\n') + .trim(); +}; + +const format = (value, offset) => { + return prettier + .format(value, { + ...prettierConfig, + parser: 'markdown', + // This is the print width minus 3 (the length of ` * `) and the offset. + printWidth: 80 - (offset + 3), + }) + .trim(); +}; + +const buildBlockComment = (value, offset) => { + const spaces = ' '.repeat(offset); + const lines = value.split('\n').map(line => { + return ` * ${line}`; + }); + lines.unshift('/**'); + lines.push(' */'); + lines.forEach((line, i) => { + lines[i] = `${spaces}${line}`; + }); + return lines.join('\n'); +}; + +/** + * @type import("eslint").Rule.RuleModule + */ +const prettierCommentsRule = { + meta: { + type: 'suggestion', + docs: { + description: 'Enforce Prettier formatting on comments', + recommended: false, + }, + fixable: 'code', + schema: [], + messages: {}, + }, + + create(context) { + for (const comment of context.sourceCode.getAllComments()) { + switch (comment.type) { + case 'Block': { + const offset = comment.loc.start.column; + const value = cleanupBlockComment(comment.value); + const formattedValue = format(value, offset); + if (formattedValue !== value) { + context.report({ + node: comment, + message: `Comment is not formatted correctly.`, + fix(fixer) { + return fixer.replaceText( + comment, + buildBlockComment(formattedValue, offset).trimStart() + ); + }, + }); + } + break; + } + } + } + return {}; + }, +}; + +module.exports = prettierCommentsRule; diff --git a/remote/test/puppeteer/tools/eslint/src/use-using.ts b/remote/test/puppeteer/tools/eslint/src/use-using.ts new file mode 100644 index 0000000000..0c727a4334 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/src/use-using.ts @@ -0,0 +1,85 @@ +/** + * @license + * Copyright 2023 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import {ESLintUtils, TSESTree} from '@typescript-eslint/utils'; + +const usingSymbols = ['ElementHandle', 'JSHandle']; + +const createRule = ESLintUtils.RuleCreator(name => { + return `https://github.com/puppeteer/puppeteer/tree/main/tools/eslint/${name}.js`; +}); + +const useUsingRule = createRule<[], 'useUsing' | 'useUsingFix'>({ + name: 'use-using', + meta: { + docs: { + description: "Requires 'using' for element/JS handles.", + requiresTypeChecking: true, + }, + hasSuggestions: true, + messages: { + useUsing: "Use 'using'.", + useUsingFix: "Replace with 'using' to ignore.", + }, + 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) || node.declare) { + 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', + suggest: [ + { + messageId: 'useUsingFix', + fix(fixer) { + return fixer.replaceTextRange( + [node.range[0], node.range[0] + node.kind.length], + 'using' + ); + }, + }, + ], + }); + } + } + } + }, + }; + }, +}); + +export = useUsingRule; diff --git a/remote/test/puppeteer/tools/eslint/tsconfig.json b/remote/test/puppeteer/tools/eslint/tsconfig.json new file mode 100644 index 0000000000..da26cc936b --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/tsconfig.json @@ -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, + }, +} diff --git a/remote/test/puppeteer/tools/eslint/tsdoc.json b/remote/test/puppeteer/tools/eslint/tsdoc.json new file mode 100644 index 0000000000..f5b91f4af6 --- /dev/null +++ b/remote/test/puppeteer/tools/eslint/tsdoc.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + + "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"], + "tagDefinitions": [ + { + "tagName": "@license", + "syntaxKind": "modifier", + "allowMultiple": false + } + ], + "supportForTags": { + "@license": true + } +} -- cgit v1.2.3