@@ -2,6 +2,24 @@ const { AST_NODE_TYPES, TSESTree, ESLintUtils } = require("@typescript-eslint/ut
2
2
const { createRule } = require ( "./utils.cjs" ) ;
3
3
const ts = require ( "typescript" ) ;
4
4
5
+ const unset = Symbol ( ) ;
6
+ /**
7
+ * @template T
8
+ * @param {() => T } fn
9
+ * @returns {() => T }
10
+ */
11
+ function memoize ( fn ) {
12
+ /** @type {T | unset } */
13
+ let value = unset ;
14
+ return ( ) => {
15
+ if ( value === unset ) {
16
+ value = fn ( ) ;
17
+ }
18
+ return value ;
19
+ } ;
20
+ }
21
+
22
+
5
23
module . exports = createRule ( {
6
24
name : "parameter-trivia" ,
7
25
meta : {
@@ -74,39 +92,58 @@ module.exports = createRule({
74
92
return ;
75
93
}
76
94
77
- const comments = sourceCode . getCommentsBefore ( node ) ;
78
- if ( ! comments || comments . length === 0 ) {
79
- // TODO(jakebailey): quick fix
80
- context . report ( { messageId : "parameterTriviaArgumentError" , node } ) ;
81
- return ;
82
- }
95
+ const getExpectedName = memoize ( ( ) => {
96
+ const signature = getSignature ( ) ;
97
+ if ( signature ) {
98
+ const expectedName = signature . parameters [ i ] ?. escapedName ;
99
+ if ( expectedName ) {
100
+ return ts . unescapeLeadingUnderscores ( expectedName ) ;
101
+ }
102
+ }
103
+ return undefined ;
104
+ } ) ;
83
105
106
+ const comments = sourceCode . getCommentsBefore ( node ) ;
107
+ /** @type {TSESTree.Comment | undefined } */
84
108
const comment = comments [ comments . length - 1 ] ;
85
- if ( comment . type !== "Block" ) {
86
- // TODO(jakebailey): quick fix
87
- context . report ( { messageId : "parameterTriviaArgumentError" , node } ) ;
109
+
110
+ if ( ! comment || comment . type !== "Block" ) {
111
+ const expectedName = getExpectedName ( ) ;
112
+ if ( expectedName ) {
113
+ context . report ( {
114
+ messageId : "parameterTriviaArgumentError" ,
115
+ node,
116
+ fix : ( fixer ) => {
117
+ return fixer . insertTextBefore ( node , `/*${ expectedName } */ ` ) ;
118
+ }
119
+ } ) ;
120
+ }
121
+ else {
122
+ context . report ( { messageId : "parameterTriviaArgumentError" , node } ) ;
123
+ }
88
124
return ;
89
125
}
90
126
91
127
const argRangeStart = node . range [ 0 ] ;
92
128
const commentRangeEnd = comment . range [ 1 ] ;
93
- const signature = getSignature ( ) ;
94
- if ( signature ) {
95
- const expectedName = signature . parameters [ i ] ?. escapedName ;
96
- if ( expectedName ) {
97
- const got = comment . value . trim ( ) ;
98
- const want = ts . unescapeLeadingUnderscores ( expectedName ) ;
99
- if ( got !== want ) {
100
- context . report ( {
101
- messageId : "parameterTriviaArgumentNameError" ,
102
- data : { got, want } ,
103
- node : comment ,
104
- fix : ( fixer ) => {
105
- return fixer . replaceText ( comment , `/*${ expectedName } */` ) ;
106
- } ,
107
- } ) ;
108
- return ;
109
- }
129
+ const expectedName = getExpectedName ( ) ;
130
+ if ( expectedName ) {
131
+ let got = comment . value . trim ( ) ;
132
+ if ( got [ 0 ] === "*" ) {
133
+ // Accept JSDoc style comments
134
+ got = got . slice ( 1 ) ;
135
+ }
136
+
137
+ if ( got !== expectedName ) {
138
+ context . report ( {
139
+ messageId : "parameterTriviaArgumentNameError" ,
140
+ data : { got, want : expectedName } ,
141
+ node : comment ,
142
+ fix : ( fixer ) => {
143
+ return fixer . replaceText ( comment , `/*${ expectedName } */` ) ;
144
+ } ,
145
+ } ) ;
146
+ return ;
110
147
}
111
148
}
112
149
@@ -131,22 +168,15 @@ module.exports = createRule({
131
168
return ;
132
169
}
133
170
134
- /** @type {ts.Signature | undefined } */
135
- let signature ;
136
- const getSignature = ( ) => {
137
- if ( signature ) {
138
- return signature ;
139
- }
140
-
171
+ const getSignature = memoize ( ( ) => {
141
172
if ( context . parserServices ?. hasFullTypeInformation ) {
142
173
const parserServices = ESLintUtils . getParserServices ( context ) ;
143
174
const checker = parserServices . program . getTypeChecker ( ) ;
144
175
const tsNode = parserServices . esTreeNodeToTSNodeMap . get ( node ) ;
145
- return signature = checker . getResolvedSignature ( tsNode ) ;
176
+ return checker . getResolvedSignature ( tsNode ) ;
146
177
}
147
-
148
178
return undefined ;
149
- } ;
179
+ } ) ;
150
180
151
181
for ( let i = 0 ; i < node . arguments . length ; i ++ ) {
152
182
const arg = node . arguments [ i ] ;
0 commit comments