From 2d4b3e21b67f78a170bcab265acf0e6f24343b49 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Fri, 5 Feb 2021 22:56:54 +0200 Subject: [PATCH] feat(42637): add generateReturn option to UserPreferences --- src/harness/client.ts | 2 +- src/harness/fourslashImpl.ts | 4 +-- src/harness/fourslashInterfaceImpl.ts | 4 +-- src/harness/harnessLanguageService.ts | 4 +-- src/server/protocol.ts | 2 ++ src/server/session.ts | 2 +- src/services/jsDoc.ts | 29 ++++++++++--------- src/services/services.ts | 4 +-- src/services/shims.ts | 6 ++-- src/services/types.ts | 6 +++- .../reference/api/tsserverlibrary.d.ts | 6 +++- tests/baselines/reference/api/typescript.d.ts | 5 +++- ...ag.ts => docCommentTemplateReturnsTag1.ts} | 0 .../docCommentTemplateReturnsTag2.ts | 21 ++++++++++++++ tests/cases/fourslash/fourslash.ts | 6 +++- 15 files changed, 70 insertions(+), 31 deletions(-) rename tests/cases/fourslash/{docCommentTemplateReturnsTag.ts => docCommentTemplateReturnsTag1.ts} (100%) create mode 100644 tests/cases/fourslash/docCommentTemplateReturnsTag2.ts diff --git a/src/harness/client.ts b/src/harness/client.ts index 4bdb316b6b47d..f4f703d9164e3 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -605,7 +605,7 @@ namespace ts.server { return notImplemented(); } - getDocCommentTemplateAtPosition(_fileName: string, _position: number): TextInsertion { + getDocCommentTemplateAtPosition(_fileName: string, _position: number, _options?: DocCommentTemplateOptions): TextInsertion { return notImplemented(); } diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 8fd2f7f2447b8..d86f2e904fe65 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -3048,9 +3048,9 @@ namespace FourSlash { assert.deepEqual(actualModuleSpecifiers, moduleSpecifiers); } - public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined) { + public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions) { const name = "verifyDocCommentTemplate"; - const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; + const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition, options || { generateReturnInDocTemplate: true })!; if (expected === undefined) { if (actual) { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 2e64b2921e8b6..09b52997b1285 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -432,9 +432,9 @@ namespace FourSlashInterface { this.state.verifyNoMatchingBracePosition(bracePosition); } - public docCommentTemplateAt(marker: string | FourSlash.Marker, expectedOffset: number, expectedText: string) { + public docCommentTemplateAt(marker: string | FourSlash.Marker, expectedOffset: number, expectedText: string, options?: ts.DocCommentTemplateOptions) { this.state.goToMarker(marker); - this.state.verifyDocCommentTemplate({ newText: expectedText.replace(/\r?\n/g, "\r\n"), caretOffset: expectedOffset }); + this.state.verifyDocCommentTemplate({ newText: expectedText.replace(/\r?\n/g, "\r\n"), caretOffset: expectedOffset }, options); } public noDocCommentTemplateAt(marker: string | FourSlash.Marker) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 85164d58bb122..1a056683f912c 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -558,8 +558,8 @@ namespace Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } - getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion { - return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position)); + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: ts.DocCommentTemplateOptions): ts.TextInsertion { + return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position, options)); } isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { return unwrapJSONCallResult(this.shim.isValidBraceCompletionAtPosition(fileName, position, openingBrace)); diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 237ce1fd5a05f..1ce0c66019f6d 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -3273,6 +3273,8 @@ namespace ts.server.protocol { readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; + + readonly generateReturnInDocTemplate?: boolean; } export interface CompilerOptions { diff --git a/src/server/session.ts b/src/server/session.ts index 99133fbbff865..2ee15bd1b8aa1 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1641,7 +1641,7 @@ namespace ts.server { private getDocCommentTemplate(args: protocol.FileLocationRequestArgs) { const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args); const position = this.getPositionInFile(args, file); - return languageService.getDocCommentTemplateAtPosition(file, position); + return languageService.getDocCommentTemplateAtPosition(file, position, this.getPreferences(file)); } private getSpanOfEnclosingComment(args: protocol.SpanOfEnclosingCommentRequestArgs) { diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 7874ddfcb3ac5..b0e133521cdf0 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -251,7 +251,7 @@ namespace ts.JsDoc { * @param position The (character-indexed) position in the file where the check should * be performed. */ - export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number): TextInsertion | undefined { + export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined { const tokenAtPos = getTokenAtPosition(sourceFile, position); const existingDocComment = findAncestor(tokenAtPos, isJSDoc); if (existingDocComment && (existingDocComment.comment !== undefined || length(existingDocComment.tags))) { @@ -265,7 +265,7 @@ namespace ts.JsDoc { return undefined; } - const commentOwnerInfo = getCommentOwnerInfo(tokenAtPos); + const commentOwnerInfo = getCommentOwnerInfo(tokenAtPos, options); if (!commentOwnerInfo) { return undefined; } @@ -325,10 +325,10 @@ namespace ts.JsDoc { readonly parameters?: readonly ParameterDeclaration[]; readonly hasReturn?: boolean; } - function getCommentOwnerInfo(tokenAtPos: Node): CommentOwnerInfo | undefined { - return forEachAncestor(tokenAtPos, getCommentOwnerInfoWorker); + function getCommentOwnerInfo(tokenAtPos: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined { + return forEachAncestor(tokenAtPos, n => getCommentOwnerInfoWorker(n, options)); } - function getCommentOwnerInfoWorker(commentOwner: Node): CommentOwnerInfo | undefined | "quit" { + function getCommentOwnerInfoWorker(commentOwner: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined | "quit" { switch (commentOwner.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: @@ -337,10 +337,10 @@ namespace ts.JsDoc { case SyntaxKind.MethodSignature: case SyntaxKind.ArrowFunction: const host = commentOwner as ArrowFunction | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature; - return { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host) }; + return { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host, options) }; case SyntaxKind.PropertyAssignment: - return getCommentOwnerInfoWorker((commentOwner as PropertyAssignment).initializer); + return getCommentOwnerInfoWorker((commentOwner as PropertyAssignment).initializer, options); case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: @@ -357,7 +357,7 @@ namespace ts.JsDoc { ? getRightHandSideOfAssignment(varDeclarations[0].initializer) : undefined; return host - ? { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host) } + ? { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host, options) } : { commentOwner }; } @@ -371,27 +371,28 @@ namespace ts.JsDoc { return commentOwner.parent.kind === SyntaxKind.ModuleDeclaration ? undefined : { commentOwner }; case SyntaxKind.ExpressionStatement: - return getCommentOwnerInfoWorker((commentOwner as ExpressionStatement).expression); + return getCommentOwnerInfoWorker((commentOwner as ExpressionStatement).expression, options); case SyntaxKind.BinaryExpression: { const be = commentOwner as BinaryExpression; if (getAssignmentDeclarationKind(be) === AssignmentDeclarationKind.None) { return "quit"; } return isFunctionLike(be.right) - ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right) } + ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner }; } case SyntaxKind.PropertyDeclaration: const init = (commentOwner as PropertyDeclaration).initializer; if (init && (isFunctionExpression(init) || isArrowFunction(init))) { - return { commentOwner, parameters: init.parameters, hasReturn: hasReturn(init) }; + return { commentOwner, parameters: init.parameters, hasReturn: hasReturn(init, options) }; } } } - function hasReturn(node: Node) { - return isArrowFunction(node) && isExpression(node.body) - || isFunctionLikeDeclaration(node) && node.body && isBlock(node.body) && !!forEachReturnStatement(node.body, n => n); + function hasReturn(node: Node, options: DocCommentTemplateOptions | undefined) { + return !!options?.generateReturnInDocTemplate && + (isArrowFunction(node) && isExpression(node.body) + || isFunctionLikeDeclaration(node) && node.body && isBlock(node.body) && !!forEachReturnStatement(node.body, n => n)); } function getRightHandSideOfAssignment(rightHandSide: Expression): FunctionExpression | ArrowFunction | ConstructorDeclaration | undefined { diff --git a/src/services/services.ts b/src/services/services.ts index 3b4ce09683446..e1b60bdef809b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2004,8 +2004,8 @@ namespace ts { : Promise.reject("Host does not implement `installPackage`"); } - function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined { - return JsDoc.getDocCommentTemplateAtPosition(getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); + function getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined { + return JsDoc.getDocCommentTemplateAtPosition(getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position, options); } function isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { diff --git a/src/services/shims.ts b/src/services/shims.ts index 30144210271ea..e986820765ad9 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -263,7 +263,7 @@ namespace ts { /** * Returns JSON-encoded value of the type TextInsertion. */ - getDocCommentTemplateAtPosition(fileName: string, position: number): string; + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): string; /** * Returns JSON-encoded boolean to indicate whether we should support brace location @@ -999,10 +999,10 @@ namespace ts { }); } - public getDocCommentTemplateAtPosition(fileName: string, position: number): string { + public getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): string { return this.forwardJSONCall( `getDocCommentTemplateAtPosition('${fileName}', ${position})`, - () => this.languageService.getDocCommentTemplateAtPosition(fileName, position) + () => this.languageService.getDocCommentTemplateAtPosition(fileName, position, options) ); } diff --git a/src/services/types.ts b/src/services/types.ts index f1ca5f7372728..82563150ecb8e 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -490,7 +490,7 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** @@ -1073,6 +1073,10 @@ namespace ts { readonly allowRenameOfImportPath?: boolean; } + export interface DocCommentTemplateOptions { + readonly generateReturnInDocTemplate?: boolean; + } + export interface SignatureHelpParameter { name: string; documentation: SymbolDisplayPart[]; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 4419cf5a9cc3d..be1c47fd86a47 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5555,7 +5555,7 @@ declare namespace ts { getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. @@ -6020,6 +6020,9 @@ declare namespace ts { interface RenameInfoOptions { readonly allowRenameOfImportPath?: boolean; } + interface DocCommentTemplateOptions { + readonly generateReturnInDocTemplate?: boolean; + } interface SignatureHelpParameter { name: string; documentation: SymbolDisplayPart[]; @@ -9046,6 +9049,7 @@ declare namespace ts.server.protocol { readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; + readonly generateReturnInDocTemplate?: boolean; } interface CompilerOptions { allowJs?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f603ef46bacad..bba168d37e720 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5555,7 +5555,7 @@ declare namespace ts { getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; - getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; /** * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. @@ -6020,6 +6020,9 @@ declare namespace ts { interface RenameInfoOptions { readonly allowRenameOfImportPath?: boolean; } + interface DocCommentTemplateOptions { + readonly generateReturnInDocTemplate?: boolean; + } interface SignatureHelpParameter { name: string; documentation: SymbolDisplayPart[]; diff --git a/tests/cases/fourslash/docCommentTemplateReturnsTag.ts b/tests/cases/fourslash/docCommentTemplateReturnsTag1.ts similarity index 100% rename from tests/cases/fourslash/docCommentTemplateReturnsTag.ts rename to tests/cases/fourslash/docCommentTemplateReturnsTag1.ts diff --git a/tests/cases/fourslash/docCommentTemplateReturnsTag2.ts b/tests/cases/fourslash/docCommentTemplateReturnsTag2.ts new file mode 100644 index 0000000000000..18767a422805b --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateReturnsTag2.ts @@ -0,0 +1,21 @@ +/// + +/////*0*/ +////function f1(x: number, y: number) { +//// return 1; +////} + +verify.docCommentTemplateAt("0", 8, + `/** + * + * @param x + * @param y + * @returns + */`, { generateReturnInDocTemplate: true }); + +verify.docCommentTemplateAt("0", 8, + `/** + * + * @param x + * @param y + */`, { generateReturnInDocTemplate: false }); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 7228fee24b118..387d843190454 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -328,7 +328,7 @@ declare namespace FourSlashInterface { todoCommentsInCurrentFile(descriptors: string[]): void; matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void; noMatchingBracePositionInCurrentFile(bracePosition: number): void; - docCommentTemplateAt(markerName: string | FourSlashInterface.Marker, expectedOffset: number, expectedText: string): void; + docCommentTemplateAt(markerName: string | FourSlashInterface.Marker, expectedOffset: number, expectedText: string, options?: VerifyDocCommentTemplateOptions): void; noDocCommentTemplateAt(markerName: string | FourSlashInterface.Marker): void; rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void; codeFixAll(options: { fixId: string, fixAllDescription: string, newFileContent: NewFileContent, commands?: {}[] }): void; @@ -664,6 +664,10 @@ declare namespace FourSlashInterface { overrideSelectedItemIndex?: number; } + interface VerifyDocCommentTemplateOptions { + generateReturnInDocTemplate?: boolean; + } + export type SignatureHelpTriggerReason = | SignatureHelpInvokedReason | SignatureHelpCharacterTypedReason