@@ -10,7 +10,7 @@ import * as ts from 'typescript';
10
10
11
11
import * as jsdoc from './jsdoc' ;
12
12
import * as path from './path' ;
13
- import { createNotEmittedStatement , reportDiagnostic , synthesizeCommentRanges , updateSourceFileNode } from './transformer_util' ;
13
+ import { reportDiagnostic , synthesizeCommentRanges , updateSourceFileNode } from './transformer_util' ;
14
14
15
15
/**
16
16
* A set of JSDoc tags that mark a comment as a fileoverview comment. These are
@@ -65,6 +65,9 @@ function augmentFileoverviewComments(
65
65
// * Suppress uselessCode. We emit an "if (false)" around type
66
66
// declarations, which is flagged as unused code unless we suppress it.
67
67
'uselessCode' ,
68
+ // suspiciousCode errors flag patterns that are suspicious if human-written
69
+ // but not inherently wrong. See also b/323580655.
70
+ 'suspiciousCode' ,
68
71
// * Suppress some checks for user errors that TS already checks.
69
72
'missingReturn' ,
70
73
'unusedPrivateMembers' ,
@@ -152,35 +155,34 @@ export function transformFileoverviewCommentFactory(
152
155
// they do not get lost later on.
153
156
const synthesizedComments =
154
157
jsdoc . synthesizeLeadingComments ( firstStatement ) ;
155
- const notEmitted = ts . factory . createNotEmittedStatement ( sourceFile ) ;
156
158
// Modify the comments on the firstStatement in place by removing the
157
159
// file-level comments.
158
160
fileComments = synthesizedComments . splice ( 0 , i + 1 ) ;
159
- // Move the fileComments onto notEmitted.
160
- ts . setSyntheticLeadingComments ( notEmitted , fileComments ) ;
161
- sourceFile =
162
- updateSourceFileNode ( sourceFile , ts . factory . createNodeArray ( [
163
- notEmitted , firstStatement , ...sourceFile . statements . slice ( 1 )
164
- ] ) ) ;
165
161
break ;
166
162
}
163
+ }
167
164
168
-
169
- // Now walk every top level statement and escape/drop any @fileoverview
170
- // comments found. Closure ignores all @fileoverview comments but the
171
- // last, so tsickle must make sure not to emit duplicated ones.
172
- for ( let i = 0 ; i < sourceFile . statements . length ; i ++ ) {
173
- const stmt = sourceFile . statements [ i ] ;
174
- // Accept the NotEmittedStatement inserted above.
175
- if ( i === 0 && stmt . kind === ts . SyntaxKind . NotEmittedStatement ) {
176
- continue ;
177
- }
178
- const comments = jsdoc . synthesizeLeadingComments ( stmt ) ;
179
- checkNoFileoverviewComments (
180
- stmt , comments ,
181
- `file comments must be at the top of the file, ` +
182
- `separated from the file body by an empty line.` ) ;
165
+ // Move the fileComments onto notEmitted.
166
+ const notEmitted = ts . factory . createNotEmittedStatement ( sourceFile ) ;
167
+ ts . setSyntheticLeadingComments ( notEmitted , fileComments ) ;
168
+ sourceFile = updateSourceFileNode (
169
+ sourceFile ,
170
+ ts . factory . createNodeArray ( [ notEmitted , ... sourceFile . statements ] ) ) ;
171
+
172
+ // Now walk every top level statement and escape/drop any @fileoverview
173
+ // comments found. Closure ignores all @fileoverview comments but the
174
+ // last, so tsickle must make sure not to emit duplicated ones.
175
+ for ( let i = 0 ; i < sourceFile . statements . length ; i ++ ) {
176
+ const stmt = sourceFile . statements [ i ] ;
177
+ // Accept the NotEmittedStatement inserted above.
178
+ if ( i === 0 && stmt . kind === ts . SyntaxKind . NotEmittedStatement ) {
179
+ continue ;
183
180
}
181
+ const comments = jsdoc . synthesizeLeadingComments ( stmt ) ;
182
+ checkNoFileoverviewComments (
183
+ stmt , comments ,
184
+ `file comments must be at the top of the file, ` +
185
+ `separated from the file body by an empty line.` ) ;
184
186
}
185
187
186
188
// Closure Compiler considers the *last* comment with @fileoverview (or
@@ -192,14 +194,17 @@ export function transformFileoverviewCommentFactory(
192
194
let fileoverviewIdx = - 1 ;
193
195
let tags : jsdoc . Tag [ ] = [ ] ;
194
196
for ( let i = fileComments . length - 1 ; i >= 0 ; i -- ) {
195
- const parse = jsdoc . parseContents ( fileComments [ i ] . text ) ;
196
- if ( parse !== null &&
197
- parse . tags . some ( t => FILEOVERVIEW_COMMENT_MARKERS . has ( t . tagName ) ) ) {
197
+ const parsed = jsdoc . parse ( fileComments [ i ] ) ;
198
+ if ( parsed !== null &&
199
+ parsed . tags . some (
200
+ t => FILEOVERVIEW_COMMENT_MARKERS . has ( t . tagName ) ) ) {
198
201
fileoverviewIdx = i ;
199
- tags = parse . tags ;
202
+ tags = parsed . tags ;
200
203
break ;
201
204
}
202
205
}
206
+ const mutableJsDoc = new jsdoc . MutableJSDoc (
207
+ notEmitted , fileComments , fileoverviewIdx , tags ) ;
203
208
204
209
if ( fileoverviewIdx !== - 1 ) {
205
210
checkNoFileoverviewComments (
@@ -208,28 +213,11 @@ export function transformFileoverviewCommentFactory(
208
213
`duplicate file level comment` ) ;
209
214
}
210
215
211
- augmentFileoverviewComments ( options , sourceFile , tags , generateExtraSuppressions ) ;
212
- const commentText = jsdoc . toStringWithoutStartEnd ( tags ) ;
213
-
214
- if ( fileoverviewIdx < 0 ) {
215
- // No existing comment to merge with, just emit a new one.
216
- return addNewFileoverviewComment ( sourceFile , commentText ) ;
217
- }
216
+ augmentFileoverviewComments (
217
+ options , sourceFile , mutableJsDoc . tags , generateExtraSuppressions ) ;
218
+ mutableJsDoc . updateComment ( ) ;
218
219
219
- fileComments [ fileoverviewIdx ] . text = commentText ;
220
- // sf does not need to be updated, synthesized comments are mutable.
221
220
return sourceFile ;
222
221
} ;
223
222
} ;
224
223
}
225
-
226
- function addNewFileoverviewComment (
227
- sf : ts . SourceFile , commentText : string ) : ts . SourceFile {
228
- let syntheticFirstStatement = createNotEmittedStatement ( sf ) ;
229
- syntheticFirstStatement = ts . addSyntheticTrailingComment (
230
- syntheticFirstStatement , ts . SyntaxKind . MultiLineCommentTrivia ,
231
- commentText , true ) ;
232
- return updateSourceFileNode (
233
- sf ,
234
- ts . factory . createNodeArray ( [ syntheticFirstStatement , ...sf . statements ] ) ) ;
235
- }
0 commit comments