Skip to content

Commit c917875

Browse files
Lightning00BladeDevtools-frontend LUCI CQ
authored andcommitted
[eslint] Support TypeScript rules
Bug: 397586315 Change-Id: I98652778c389ba3f73ccbc9f0de63cebc3502191 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6414779 Reviewed-by: Victor Porof <[email protected]> Reviewed-by: Danil Somsikov <[email protected]> Commit-Queue: Nikolay Vitkov <[email protected]>
1 parent dfab8d0 commit c917875

File tree

10 files changed

+142
-29
lines changed

10 files changed

+142
-29
lines changed

PRESUBMIT.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,11 @@ def _CheckDevToolsLint(input_api, output_api):
344344
files_to_lint = []
345345

346346
results.extend(
347-
_checkWithNodeScript(input_api, output_api, lint_path, files_to_lint))
347+
_checkWithNodeScript(input_api,
348+
output_api,
349+
lint_path,
350+
files_to_lint,
351+
allow_typescript=True))
348352
return results
349353

350354

@@ -690,7 +694,8 @@ def _getAffectedFiles(input_api, parent_directories, excluded_actions,
690694
def _checkWithNodeScript(input_api,
691695
output_api,
692696
script_path,
693-
script_arguments=[]): # pylint: disable=invalid-name
697+
script_arguments=[],
698+
allow_typescript=False):
694699
original_sys_path = sys.path
695700
try:
696701
sys.path = sys.path + [
@@ -700,9 +705,14 @@ def _checkWithNodeScript(input_api,
700705
finally:
701706
sys.path = original_sys_path
702707

703-
return _ExecuteSubProcess(input_api, output_api,
704-
[devtools_paths.node_path(), script_path],
705-
script_arguments, [])
708+
process = [devtools_paths.node_path(), script_path]
709+
710+
if allow_typescript:
711+
process.insert(1, '--no-warnings=ExperimentalWarning')
712+
process.insert(1, '--experimental-strip-types')
713+
714+
return _ExecuteSubProcess(input_api, output_api, process, script_arguments,
715+
[])
706716

707717

708718
def _getFilesToLint(input_api, output_api, lint_config_files,

eslint.config.mjs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,10 @@ import eslintPlugin from 'eslint-plugin-eslint-plugin';
99
import importPlugin from 'eslint-plugin-import';
1010
import jsdocPlugin from 'eslint-plugin-jsdoc';
1111
import mochaPlugin from 'eslint-plugin-mocha';
12-
import rulesdirPlugin from 'eslint-plugin-rulesdir';
1312
import globals from 'globals';
1413
import { join } from 'path';
1514

16-
rulesdirPlugin.RULES_DIR = join(
17-
import.meta.dirname,
18-
'scripts',
19-
'eslint_rules',
20-
'lib',
21-
);
15+
import rulesdirPlugin from './scripts/eslint_rules/rules-dir.mjs';
2216

2317
/**
2418
* @type {import('eslint').Linter.Config[]}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"debug-webtest": "vpython3 third_party/node/node.py --output scripts/npm_test.js --debug-devtools",
2626
"generate-protocol-resources": "scripts/deps/generate_protocol_resources.py && git cl format --js",
2727
"install-deps": "scripts/deps/manage_node_deps.py",
28-
"lint": "vpython3 third_party/node/node.py --output scripts/test/run_lint_check.mjs",
28+
"lint": "vpython3 third_party/node/node.py --output --experimental-strip-types --no-warnings=ExperimentalWarning scripts/test/run_lint_check.mjs",
2929
"prebuild": "gn gen out/Default",
3030
"rdb": "rdb stream -new -realm chrome:public --",
3131
"start": "vpython3 third_party/node/node.py --output scripts/run_start.mjs",
Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
// Copyright 2020 The Chromium Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
'use strict';
54

6-
/**
7-
* @type {import('eslint').Rule.RuleModule}
8-
*/
9-
module.exports = {
5+
import {createRule} from './tsUtils.ts';
6+
7+
export default createRule({
8+
name: 'no-commented-out-console',
109
meta: {
1110
type: 'problem',
1211
docs: {
1312
description: 'check for commented out console.{warn/log/etc} lines',
1413
category: 'Possible Errors',
1514
},
15+
messages: {
16+
foundComment: 'Found a commented out console call.',
17+
},
1618
fixable: 'code',
17-
schema: [] // no options
19+
schema: [], // no options
1820
},
21+
defaultOptions: [],
1922
create: function(context) {
2023
const sourceCode = context.sourceCode ?? context.getSourceCode();
2124

2225
function checkCommentAndReportError(comment) {
2326
const trimmed = comment.value.trim();
2427
if (trimmed.startsWith('console.log(')) {
25-
context.report({node: comment, message: 'Found a commented out console call.'});
28+
context.report({
29+
node: comment,
30+
messageId: 'foundComment',
31+
});
2632
}
2733
}
2834

@@ -35,7 +41,7 @@ module.exports = {
3541
for (const comment of comments) {
3642
checkCommentAndReportError(comment);
3743
}
38-
}
44+
},
3945
};
40-
}
41-
};
46+
},
47+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
import {ESLintUtils} from '@typescript-eslint/utils';
5+
6+
export interface ExtraDocs {
7+
requiresTypeChecking?: boolean;
8+
category?: string;
9+
}
10+
11+
const LINK_BASE =
12+
'https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/scripts/eslint_rules/lib';
13+
export const createRule = ESLintUtils.RuleCreator<ExtraDocs>(
14+
name => `${LINK_BASE}/${name}.ts`,
15+
);

scripts/eslint_rules/rules-dir.mjs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// EsLint rule dir loader
6+
// https://github.com/eslint-community/eslint-plugin-rulesdir
7+
// but modified as we need to use it with ESM
8+
// This code is licensed under the MIT license
9+
/**
10+
* The MIT License (MIT)
11+
* =====================
12+
*
13+
* Copyright © 2017 Teddy Katz
14+
*
15+
* Permission is hereby granted, free of charge, to any person
16+
* obtaining a copy of this software and associated documentation
17+
* files (the “Software”), to deal in the Software without
18+
* restriction, including without limitation the rights to use,
19+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
20+
* copies of the Software, and to permit persons to whom the
21+
* Software is furnished to do so, subject to the following
22+
* conditions:
23+
*
24+
* The above copyright notice and this permission notice shall be
25+
* included in all copies or substantial portions of the Software.
26+
*
27+
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
28+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
29+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
31+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
32+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34+
* OTHER DEALINGS IN THE SOFTWARE.
35+
*/
36+
37+
/**
38+
* @fileoverview Allows a local ESLint rules directory to be used without a command-line flag
39+
* @author Teddy Katz
40+
*/
41+
42+
import { readdirSync } from 'fs';
43+
import { extname, resolve, basename, join } from 'path';
44+
import { pathToFileURL } from 'url';
45+
46+
const RULES_DIR = join(import.meta.dirname, 'lib');
47+
48+
const ruleExtensions = new Set(['.js', '.cjs', '.mjs', '.ts', '.cts', '.mts']);
49+
50+
const rulesModules = {};
51+
52+
for (const filename of readdirSync(RULES_DIR)) {
53+
if (!ruleExtensions.has(extname(filename))) {
54+
continue;
55+
}
56+
const absolutePath = resolve(RULES_DIR, filename);
57+
const ruleName = basename(absolutePath, extname(absolutePath));
58+
if (rulesModules[ruleName]) {
59+
throw new Error(
60+
`eslint-plugin-rulesdir found two rules with the same name: ${ruleName}`,
61+
);
62+
}
63+
const moduleURL =
64+
process.platform === 'win32'
65+
? pathToFileURL(absolutePath).href
66+
: absolutePath;
67+
const loadedRule = await import(moduleURL);
68+
rulesModules[ruleName] = loadedRule.default ? loadedRule.default : loadedRule;
69+
}
70+
71+
export default {
72+
get rules() {
73+
return rulesModules;
74+
},
75+
};

scripts/eslint_rules/tests/no-commented-out-console.test.js renamed to scripts/eslint_rules/tests/no-commented-out-console.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
// Copyright 2020 The Chromium Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4-
'use strict';
5-
const rule = require('../lib/no-commented-out-console.js');
64

7-
const {RuleTester} = require('./utils/utils.js');
5+
import rule from '../lib/no-commented-out-console.ts';
6+
7+
import {RuleTester} from './utils/tsUtils.ts';
88

99
new RuleTester().run('no-commented-out-console', rule, {
1010
valid: [
1111
{
1212
code: 'console.log("foo")',
13-
filename: 'front_end/components/test.ts',
13+
filename: 'front_end/componentRuleTesters/test.ts',
1414
},
1515
{
1616
code: '// console.group() is not filtered',
@@ -29,7 +29,7 @@ new RuleTester().run('no-commented-out-console', rule, {
2929
{
3030
code: '// console.log("foo")',
3131
filename: 'front_end/components/test.ts',
32-
errors: [{message: 'Found a commented out console call.'}],
32+
errors: [{messageId: 'foundComment'}],
3333
},
3434
],
3535
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import {RuleTester} from '@typescript-eslint/rule-tester';
6+
7+
// Add the mocha hooks to the rule tester.
8+
RuleTester.afterAll = after;
9+
10+
export {RuleTester};

scripts/eslint_rules/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"outDir": "ignored",
88
"checkJs": true,
99
"noEmit": true,
10-
"noImplicitAny": false
10+
"noImplicitAny": false,
11+
"allowImportingTsExtensions": true
1112
}
1213
}

test/run.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ class ScriptsMochaTests extends Tests {
184184
return super.run(
185185
tests.map(test => ScriptPathPair.getFromPair(test)),
186186
[
187+
'--experimental-strip-types',
188+
'--no-warnings=ExperimentalWarning',
187189
path.join(SOURCE_ROOT, 'node_modules', 'mocha', 'bin', 'mocha'),
188190
],
189191
);

0 commit comments

Comments
 (0)