Skip to content

Commit 0c55789

Browse files
danilsomsikovDevtools-frontend LUCI CQ
authored andcommitted
Convert the next three eslint rules to TypeScript.
* enforce-custom-element-definitions-location * html-tagged-template * jslog-context-list Bug: 397586315 Change-Id: I001213294dd094abe1281c81595ecd8bd9dd7c29 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6434122 Reviewed-by: Nikolay Vitkov <[email protected]> Auto-Submit: Danil Somsikov <[email protected]> Commit-Queue: Danil Somsikov <[email protected]>
1 parent 56c3499 commit 0c55789

7 files changed

+142
-226
lines changed

scripts/eslint_rules/lib/enforce-custom-element-definitions-location.js renamed to scripts/eslint_rules/lib/enforce-custom-element-definitions-location.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
// Copyright 2021 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';
4+
import path from 'node:path';
55

6-
const path = require('path');
6+
import {createRule} from './tsUtils.ts';
77

8-
/**
9-
* @type {import('eslint').Rule.RuleModule}
10-
*/
11-
module.exports = {
8+
export default createRule<[{rootFrontendDirectory: string}], 'definitionInWrongFolder'>({
9+
name: 'enforce-custom-element-definitions-location',
1210
meta: {
1311
type: 'problem',
1412

1513
docs: {
16-
description:
17-
'ensure that custom element definitions are in the correct folders.',
14+
description: 'ensure that custom element definitions are in the correct folders.',
1815
category: 'Possible Errors',
1916
},
2017
fixable: 'code',
2118
messages: {
22-
definitionInWrongFolder:
23-
'A custom element definition was found in a folder that ' +
24-
'should not contain element definitions. If you want to define a custom element, ' +
25-
'either place it in `ui/components/` or in a `components` sub-folder of a panel. ' +
26-
'E.g. `panels/elements/components/`.',
19+
definitionInWrongFolder: 'A custom element definition was found in a folder that ' +
20+
'should not contain element definitions. If you want to define a custom element, ' +
21+
'either place it in `ui/components/` or in a `components` sub-folder of a panel. ' +
22+
'E.g. `panels/elements/components/`.',
2723
},
2824
schema: [
2925
{
@@ -37,17 +33,18 @@ module.exports = {
3733
},
3834
],
3935
},
40-
create: function (context) {
36+
defaultOptions: [{rootFrontendDirectory: ''}],
37+
create: function(context) {
4138
const filename = context.filename ?? context.getFilename();
4239
const classDefiningFileName = path.resolve(filename);
4340

4441
let frontEndDirectory = '';
45-
if (context.options?.[0]?.rootFrontendDirectory) {
42+
if (context.options[0]?.rootFrontendDirectory) {
4643
frontEndDirectory = context.options[0].rootFrontendDirectory;
4744
}
4845
if (!frontEndDirectory) {
4946
throw new Error(
50-
'rootFrontEndDirectory must be provided to custom_elements_definitions_location.',
47+
'rootFrontEndDirectory must be provided to custom_elements_definitions_location.',
5148
);
5249
}
5350

@@ -77,10 +74,10 @@ module.exports = {
7774

7875
if (classDefiningFileName.startsWith(PANELS_DIRECTORY)) {
7976
const filePathWithPanelName = classDefiningFileName.substring(
80-
PANELS_DIRECTORY.length + 1,
77+
PANELS_DIRECTORY.length + 1,
8178
);
8279
const filePathWithoutPanelName = filePathWithPanelName.substring(
83-
filePathWithPanelName.indexOf(path.sep) + 1,
80+
filePathWithPanelName.indexOf(path.sep) + 1,
8481
);
8582

8683
if (filePathWithoutPanelName.includes(`components${path.sep}`)) {
@@ -95,4 +92,4 @@ module.exports = {
9592
},
9693
};
9794
},
98-
};
95+
});

scripts/eslint_rules/lib/html-tagged-template.js renamed to scripts/eslint_rules/lib/html-tagged-template.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
// Copyright 2024 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+
import type {TSESLint, TSESTree} from '@typescript-eslint/utils';
45

5-
/**
6-
* @type {import('eslint').Rule.RuleModule}
7-
*/
8-
module.exports = {
6+
import {createRule} from './tsUtils.ts';
7+
8+
type ImportDeclaration = TSESTree.ImportDeclaration;
9+
type RuleFix = TSESLint.RuleFix;
10+
11+
export default createRule({
12+
name: 'html-tagged-template',
913
meta: {
1014
type: 'problem',
1115

1216
docs: {
1317
description: 'Usage of Lit.html',
1418
category: 'Possible Errors',
1519
},
20+
messages: {
21+
useUnqualifiedHtmlTaggedTemplate: 'Use unqualified html tagged template for compatibility with lit-analyzer',
22+
},
1623
fixable: 'code',
17-
schema: [], // no options
24+
schema: [], // no options
1825
},
19-
create: function (context) {
26+
defaultOptions: [],
27+
create: function(context) {
2028
const sourceCode = context.sourceCode ?? context.getSourceCode();
21-
let lastImport = null;
29+
let lastImport: ImportDeclaration|null = null;
2230
let shorthandDefined = false;
2331
return {
2432
ImportDeclaration(node) {
@@ -49,9 +57,9 @@ module.exports = {
4957
tag.property.type === 'Identifier' && tag.property.name === 'html') {
5058
context.report({
5159
node,
52-
message: 'Use unqualified html tagged template for compatibility with lit-analyzer',
60+
messageId: 'useUnqualifiedHtmlTaggedTemplate',
5361
fix(fixer) {
54-
const result = [];
62+
const result: RuleFix[] = [];
5563
if (tag.object?.range?.[0] && tag.property?.range?.[0]) {
5664
result.push(
5765
fixer.removeRange([
@@ -63,7 +71,7 @@ module.exports = {
6371

6472
if (lastImport && !shorthandDefined) {
6573
result.push(
66-
fixer.insertTextAfter(lastImport, '\n\nconst {html} = Lit;'),
74+
fixer.insertTextAfter(lastImport, '\n\nconst {html} = Lit;'),
6775
);
6876
shorthandDefined = true;
6977
}
@@ -74,4 +82,4 @@ module.exports = {
7482
},
7583
};
7684
},
77-
};
85+
});

scripts/eslint_rules/lib/jslog-context-list.js renamed to scripts/eslint_rules/lib/jslog-context-list.ts

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
'use strict';
5+
import fs from 'node:fs';
6+
import path from 'node:path';
7+
import {fileURLToPath} from 'node:url';
68

7-
const fs = require('fs');
8-
const path = require('path');
9+
import {createRule} from './tsUtils.ts';
910

11+
// @ts-expect-error
12+
const filename = fileURLToPath(import.meta.url);
1013
const FILE = 'front_end/ui/visual_logging/KnownContextValues.ts';
11-
const FRONT_END_PARENT_FOLDER = path.join(__filename, '..', '..', '..', '..');
14+
const FRONT_END_PARENT_FOLDER = path.join(filename, '..', '..', '..', '..');
1215
const ABSOLUTE_FILE_PATH = path.join(FRONT_END_PARENT_FOLDER, FILE);
1316
const LICENSE_HEADER = `// Copyright 2024 The Chromium Authors. All rights reserved.
1417
// Use of this source code is governed by a BSD-style license that can be
@@ -20,49 +23,47 @@ const formattedValues = new Set(
2023
fs.readFileSync(ABSOLUTE_FILE_PATH, 'utf-8').split('\n').filter(l => l.startsWith(' \'')),
2124
);
2225

23-
/**
24-
* @type {import('eslint').Rule.RuleModule}
25-
*/
26-
module.exports = {
26+
export default createRule({
27+
name: 'jslog-context-list',
2728
meta: {
2829
type: 'problem',
2930

3031
docs: {
3132
description: 'Puts jslog context values into KnownContextValues.ts file',
3233
category: 'Possible Errors',
3334
},
35+
messages: {
36+
unknownJslogContextValue: 'Found jslog context value \'{{ value }}\' that is not listed in ' + FILE,
37+
},
3438
fixable: 'code',
35-
schema: [], // no options
39+
schema: [], // no options
3640
},
3741
defaultOptions: [],
38-
create: function (context) {
42+
create: function(context) {
3943
const checkValue = (value, node) => {
4044
if (typeof value !== 'string') {
4145
return;
4246
}
4347
if (!value.length) {
4448
return;
4549
}
46-
const formattedValue =
47-
' ' + JSON.stringify(value).replaceAll('"', '\'') + ',';
50+
const formattedValue = ' ' + JSON.stringify(value).replaceAll('"', '\'') + ',';
4851
if (formattedValues.has(formattedValue)) {
4952
return;
5053
}
5154
formattedValues.add(formattedValue);
5255
if (process.env.ESLINT_FAIL_ON_UNKNOWN_JSLOG_CONTEXT_VALUE) {
5356
context.report({
5457
node,
55-
message: `Found jslog context value '${value}' that is not listed in ${FILE}`,
58+
messageId: 'unknownJslogContextValue',
59+
data: {value},
5660
});
5761
}
5862
};
5963

6064
const checkPropertyValue = (propertyName, node) => {
6165
for (const property of node?.properties || []) {
62-
if (
63-
property.key?.name === propertyName ||
64-
property.key?.value === propertyName
65-
) {
66+
if (property.key?.name === propertyName || property.key?.value === propertyName) {
6667
checkValue(property.value?.value, node);
6768
}
6869
}
@@ -74,18 +75,12 @@ module.exports = {
7475
return;
7576
}
7677

77-
if (
78-
node.callee.type === 'MemberExpression' &&
79-
node.callee.object.type === 'Identifier' &&
80-
node.callee.object.name === 'VisualLogging'
81-
) {
78+
if (node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' &&
79+
node.callee.object.name === 'VisualLogging') {
8280
if (firstArg.type === 'Literal') {
8381
checkValue(firstArg.value, node);
8482
}
85-
} else if (
86-
node.callee.type === 'MemberExpression' &&
87-
node.callee.property.type === 'Identifier'
88-
) {
83+
} else if (node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier') {
8984
const propertyName = node.callee.property.name;
9085
if (propertyName === 'registerActionExtension') {
9186
checkPropertyValue('actionId', firstArg);
@@ -104,29 +99,19 @@ module.exports = {
10499
checkPropertyValue('jslogContext', node);
105100
},
106101
VariableDeclarator(node) {
107-
if (
108-
node.id.type === 'Identifier' &&
109-
node.id.name === 'generatedProperties' &&
110-
node.init?.type === 'ArrayExpression'
111-
) {
102+
if (node.id.type === 'Identifier' && node.id.name === 'generatedProperties' &&
103+
node.init?.type === 'ArrayExpression') {
112104
for (const element of node.init.elements) {
113105
checkPropertyValue('name', element);
114106
}
115107
}
116-
if (
117-
node.id.type === 'Identifier' &&
118-
node.id.name === 'generatedAliasesFor' &&
119-
node.init?.type === 'NewExpression'
120-
) {
108+
if (node.id.type === 'Identifier' && node.id.name === 'generatedAliasesFor' &&
109+
node.init?.type === 'NewExpression') {
121110
const firstArg = node.init?.arguments?.[0];
122-
const elements =
123-
firstArg.type === 'ArrayExpression' ? firstArg.elements : [];
111+
const elements = firstArg.type === 'ArrayExpression' ? firstArg.elements : [];
124112

125113
for (const outerElement of elements) {
126-
const innerElements =
127-
outerElement?.type === 'ArrayExpression'
128-
? outerElement.elements
129-
: [];
114+
const innerElements = outerElement?.type === 'ArrayExpression' ? outerElement.elements : [];
130115
for (const innerElement of innerElements) {
131116
if (innerElement && 'value' in innerElement) {
132117
checkValue(innerElement.value, innerElement);
@@ -139,13 +124,10 @@ module.exports = {
139124
if (process.env.ESLINT_FAIL_ON_UNKNOWN_JSLOG_CONTEXT_VALUE) {
140125
return;
141126
}
142-
const finalContents =
143-
LICENSE_HEADER +
144-
'export const knownContextValues = new Set([\n' +
145-
[...formattedValues].sort().join('\n') +
146-
'\n]);\n';
127+
const finalContents = LICENSE_HEADER + 'export const knownContextValues = new Set([\n' +
128+
[...formattedValues].sort().join('\n') + '\n]);\n';
147129
fs.writeFileSync(ABSOLUTE_FILE_PATH, finalContents, 'utf-8');
148130
},
149131
};
150132
},
151-
};
133+
});

0 commit comments

Comments
 (0)