Skip to content

Commit a93689c

Browse files
committed
Refactored eslint-plugin to use typescript-eslint
1 parent 0362e09 commit a93689c

File tree

7 files changed

+264
-125
lines changed

7 files changed

+264
-125
lines changed

Diff for: common/config/rush/pnpm-lock.yaml

+99
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: eslint-plugin/package.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,21 @@
3030
"@microsoft/tsdoc": "workspace:*",
3131
"@microsoft/tsdoc-config": "workspace:*"
3232
},
33+
"peerDependencies": {
34+
"@typescript-eslint/parser": "^8",
35+
"eslint": "^8"
36+
},
3337
"devDependencies": {
38+
"@typescript-eslint/rule-tester": "~8.3.0",
39+
"@typescript-eslint/utils": "~8.3.0",
3440
"@rushstack/heft-node-rig": "~2.6.11",
3541
"@rushstack/heft": "^0.66.13",
3642
"@types/eslint": "8.40.1",
3743
"@types/estree": "1.0.1",
3844
"@types/heft-jest": "1.0.3",
3945
"@types/node": "14.18.36",
4046
"eslint": "~8.57.0",
41-
"eslint-plugin-header": "~3.1.1"
47+
"eslint-plugin-header": "~3.1.1",
48+
"typescript": "~5.4.2"
4249
}
4350
}

Diff for: eslint-plugin/src/SyntaxRule.ts

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import { TSDocParser, TextRange, TSDocConfiguration, type ParserContext } from '@microsoft/tsdoc';
5+
import type { TSDocConfigFile } from '@microsoft/tsdoc-config';
6+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
7+
8+
const tsdocMessageIds: { [x: string]: string } = {};
9+
10+
const defaultTSDocConfiguration: TSDocConfiguration = new TSDocConfiguration();
11+
defaultTSDocConfiguration.allTsdocMessageIds.forEach((messageId: string) => {
12+
tsdocMessageIds[messageId] = `${messageId}: {{unformattedText}}`;
13+
});
14+
15+
import { Debug } from './Debug';
16+
import { ConfigCache } from './ConfigCache';
17+
18+
import { configMessages, createRule } from './utils';
19+
20+
export const rule: TSESLint.AnyRuleModule = createRule({
21+
name: 'syntax',
22+
meta: {
23+
messages: {
24+
...configMessages,
25+
...tsdocMessageIds
26+
},
27+
type: 'problem',
28+
docs: {
29+
description: 'Validates that TypeScript documentation comments conform to the TSDoc standard',
30+
// This package is experimental
31+
recommended: false
32+
},
33+
schema: []
34+
},
35+
defaultOptions: [],
36+
create: (context: TSESLint.RuleContext<string, unknown[]>) => {
37+
const sourceFilePath: string = context.getFilename();
38+
Debug.log(`Linting: "${sourceFilePath}"`);
39+
40+
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
41+
42+
try {
43+
const tsdocConfigFile: TSDocConfigFile = ConfigCache.getForSourceFile(sourceFilePath);
44+
if (!tsdocConfigFile.fileNotFound) {
45+
if (tsdocConfigFile.hasErrors) {
46+
context.report({
47+
loc: { line: 1, column: 1 },
48+
messageId: 'error-loading-config-file',
49+
data: {
50+
details: tsdocConfigFile.getErrorSummary()
51+
}
52+
});
53+
}
54+
55+
try {
56+
tsdocConfigFile.configureParser(tsdocConfiguration);
57+
} catch (e) {
58+
context.report({
59+
loc: { line: 1, column: 1 },
60+
messageId: 'error-applying-config',
61+
data: {
62+
details: e.message
63+
}
64+
});
65+
}
66+
}
67+
} catch (e) {
68+
context.report({
69+
loc: { line: 1, column: 1 },
70+
messageId: 'error-loading-config-file',
71+
data: {
72+
details: `Unexpected exception: ${e.message}`
73+
}
74+
});
75+
}
76+
77+
const tsdocParser: TSDocParser = new TSDocParser(tsdocConfiguration);
78+
79+
const sourceCode: TSESLint.SourceCode = context.sourceCode;
80+
const checkCommentBlocks: (node: TSESTree.Program) => void = function (node: TSESTree.Program) {
81+
for (const comment of sourceCode.getAllComments()) {
82+
if (comment.type !== 'Block') {
83+
continue;
84+
}
85+
if (!comment.range) {
86+
continue;
87+
}
88+
89+
const textRange: TextRange = TextRange.fromStringRange(
90+
sourceCode.text,
91+
comment.range[0],
92+
comment.range[1]
93+
);
94+
95+
// Smallest comment is "/***/"
96+
if (textRange.length < 5) {
97+
continue;
98+
}
99+
// Make sure it starts with "/**"
100+
if (textRange.buffer[textRange.pos + 2] !== '*') {
101+
continue;
102+
}
103+
104+
const parserContext: ParserContext = tsdocParser.parseRange(textRange);
105+
for (const message of parserContext.log.messages) {
106+
context.report({
107+
loc: {
108+
start: sourceCode.getLocFromIndex(message.textRange.pos),
109+
end: sourceCode.getLocFromIndex(message.textRange.end)
110+
},
111+
messageId: message.messageId,
112+
data: {
113+
unformattedText: message.unformattedText
114+
}
115+
});
116+
}
117+
}
118+
};
119+
120+
return {
121+
Program: checkCommentBlocks
122+
};
123+
}
124+
});

0 commit comments

Comments
 (0)