-
Notifications
You must be signed in to change notification settings - Fork 12.9k
inferFromUsage codefix now emits JSDoc in JS files #27610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
1bc0cd1
e34bf54
0f4a800
be3577c
bf5529b
4ee4d69
9ae4a99
09ae612
e99220f
ae062b2
69dec3f
b469d9f
56bcf3f
84b08c0
a3aae7b
d22961a
3cc99ea
31db1ce
6b0be8b
edcb30d
d129e32
e3cf787
bc32d3c
5066880
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
1. Format multiple params nicely in a single-multiline block. 2. Generate only params that haven't already been documented. Existing documentation is not touched.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -365,10 +365,24 @@ namespace ts.textChanges { | |
this.replaceRangeWithText(sourceFile, createRange(pos), text); | ||
} | ||
|
||
public tryInsertJSDocParams(sourceFile: SourceFile, annotations: [ParameterDe 8000 claration, TypeNode, boolean][]) { | ||
const parent = annotations[0][0].parent; | ||
const indent = getLineAndCharacterOfPosition(sourceFile, parent.getStart()).character; | ||
let commentText = "\n"; | ||
for (const [node, type, isOptionalParameter] of annotations) { | ||
if (isIdentifier(node.name)) { | ||
const printed = createPrinter().printNode(EmitHint.Unspecified, type, sourceFile); | ||
commentText += this.printJSDocParameter(indent, printed, node.name, isOptionalParameter); | ||
} | ||
} | ||
commentText += " ".repeat(indent + 1); | ||
this.insertCommentThenNewline(sourceFile, indent, parent.getStart(), commentText, CommentKind.Jsdoc); | ||
} | ||
|
||
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */ | ||
public tryInsertTypeAnnotation(sourceFile: SourceFile, topNode: TypeAnnotatable, type: TypeNode, isOptionalParameter?: boolean): void { | ||
public tryInsertTypeAnnotation(sourceFile: SourceFile, topNode: TypeAnnotatable, type: TypeNode): void { | ||
if (isInJSFile(sourceFile) && topNode.kind !== SyntaxKind.PropertySignature) { | ||
return this.tryInsertJSDocType(sourceFile, topNode, type, isOptionalParameter); | ||
return this.tryInsertJSDocType(sourceFile, topNode, type); | ||
} | ||
const node = topNode as SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature; | ||
let endNode: Node | undefined; | ||
|
@@ -391,16 +405,10 @@ namespace ts.textChanges { | |
* TODO: Might need to only disallow node from being a parameterdecl, propertydecl, propertysig | ||
* (or correctly handle parameterdecl by walking up and adding a param, at least) | ||
*/ | ||
public tryInsertJSDocType(sourceFile: SourceFile, node: Node, type: TypeNode, isOptionalParameter: boolean | undefined): void { | ||
// TODO: Parameter code needs to be MUCH smarter (multiple parameters are ugly, etc) | ||
// TODO: Parameter probably shouldn't need to manually unescape its text | ||
public tryInsertJSDocType(sourceFile: SourceFile, node: Node, type: TypeNode): void { | ||
const printed = createPrinter().printNode(EmitHint.Unspecified, type, sourceFile); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think this could also use |
||
let commentText; | ||
if (isParameter(node) && isIdentifier(node.name)) { | ||
commentText = this.printJSDocParameter(printed, node.name, isOptionalParameter); | ||
node = node.parent; | ||
} | ||
else if (isGetAccessorDeclaration(node)) { | ||
if (isGetAccessorDeclaration(node)) { | ||
commentText = ` @return {${printed}} `; | ||
} | ||
else { | ||
|
@@ -411,12 +419,12 @@ namespace ts.textChanges { | |
// this.replaceRangeWithText <-- SOMEDAY, when we support existing ones | ||
} | ||
|
||
private printJSDocParameter(printed: string, name: Identifier, isOptionalParameter: boolean | undefined) { | ||
private printJSDocParameter(indent: number, printed: string, name: Identifier, isOptionalParameter: boolean | undefined) { | ||
let printName = unescapeLeadingUnderscores(name.escapedText); | ||
if (isOptionalParameter) { | ||
printName = `[${printName}]`; | ||
} | ||
return ` @param {${printed}} ${printName} `; | ||
return " ".repeat(indent) + ` * @param {${printed}} ${printName}\n`; | ||
} | ||
|
||
public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: ReadonlyArray<TypeParameterDeclaration>): void { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/// <reference path='fourslash.ts' /> | ||
|
||
// @allowJs: true | ||
// @checkJs: true | ||
// @noImplicitAny: true | ||
// @strictNullChecks: true | ||
// @Filename: important.js | ||
/////** | ||
//// * @param {*} y | ||
//// */ | ||
////function f(x, y, z) { | ||
//// return x | ||
////} | ||
////f(1, 2, 3) | ||
|
||
verify.fileAfterCodeFix( | ||
` | ||
/** | ||
* @param {*} y | ||
*/ | ||
/** | ||
* @param {number} x | ||
* @param {number} z | ||
*/ | ||
function f(x, y, z) { | ||
return x | ||
} | ||
f(1, 2, 3) | ||
`, undefined, 2); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,9 @@ | |
|
||
verify.fileAfterCodeFix( | ||
`/** @param {number} a */ | ||
/** @param {(string | boolean)[]} rest */ | ||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you file this as a bug? We should combine comments, not add a new one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll file it after merging the PR since the bug depends on being able to emit JSDoc in the first place. I personally think the current approach is a good compromise and that we'll rarely have to generate partial JSDoc. The bigger lack is untyped JSDoc: /** @param x Just a description, no type */
function f(x) {
return x * x
} |
||
* @param {(string | boolean)[]} rest | ||
*/ | ||
function f(a, ...rest){ | ||
a; rest; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,9 @@ verify.codeFix({ | |
description: "Infer type of 'x' from usage", | ||
newFileContent: | ||
`export class C { | ||
/** @param {Promise<typeof import("/a")>} val */ | ||
/** | ||
* @param {Promise<typeof import("/a")>} val | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, nice catch. I asked Wesley and he said that |
||
*/ | ||
set x(val) { val; } | ||
method() { this.x = import("./a"); } | ||
}`, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I'm missing something obvious, but why "try"?