From b2821c53214f59810ba374a785613b7a21e12c23 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 14:48:58 -0700 Subject: [PATCH 1/8] Added tests for JSDoc comment templates on other declarations/statements. --- .../docCommentTemplateClassDecl01.ts | 35 ++++++++++ .../docCommentTemplateClassDeclMethods01.ts | 69 +++++++++++++++++++ .../docCommentTemplateConstructor01.ts | 50 ++++++++++++++ .../docCommentTemplateNamespaces01.ts | 46 +++++++++++++ .../docCommentTemplateVariableStatements01.ts | 54 +++++++++++++++ .../docCommentTemplateVariableStatements02.ts | 54 +++++++++++++++ 6 files changed, 308 insertions(+) create mode 100644 tests/cases/fourslash/docCommentTemplateClassDecl01.ts create mode 100644 tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts create mode 100644 tests/cases/fourslash/docCommentTemplateConstructor01.ts create mode 100644 tests/cases/fourslash/docCommentTemplateNamespaces01.ts create mode 100644 tests/cases/fourslash/docCommentTemplateVariableStatements01.ts create mode 100644 tests/cases/fourslash/docCommentTemplateVariableStatements02.ts diff --git a/tests/cases/fourslash/docCommentTemplateClassDecl01.ts b/tests/cases/fourslash/docCommentTemplateClassDecl01.ts new file mode 100644 index 00000000000..c7c858cd262 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateClassDecl01.ts @@ -0,0 +1,35 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +/////*decl*/class C { +//// private p; +//// constructor(a, b, c, d); +//// constructor(public a, private b, protected c, d, e?) { +//// } +//// +//// foo(); +//// foo(a?, b?, ...args) { +//// } +////} + +confirmNormalizedJsDoc("decl", /*indentation*/ 0, ` +/** + * + */`); diff --git a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts new file mode 100644 index 00000000000..bb14d89e3bf --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts @@ -0,0 +1,69 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +const enum Indentation { + Gutter = 0, + Proper = 4, +} + + +////class C { +/////*0*/ /*1*/ +//// foo(); +//// /*2*/foo(a); +//// /*3*/foo(a, b); +//// /*4*/ foo(a, {x: string}, c); +//// /*5*/foo(a?, b?, ...args) { +//// } +////} + +confirmNormalizedJsDoc("0", Indentation.Gutter, ` +/** + * + */`); + +confirmNormalizedJsDoc("2", Indentation.Proper, ` +/** + * + * @param a + */`); + +confirmNormalizedJsDoc("3", Indentation.Proper, ` +/** + * + * @param a + * @param b + */`); + +confirmNormalizedJsDoc("4", Indentation.Proper, ` +/** + * + * @param a + * @param param1 + * @param b + */`); + +confirmNormalizedJsDoc("5", Indentation.Proper, ` +/** + * + * @param a + * @param b + * @param args + */`); diff --git a/tests/cases/fourslash/docCommentTemplateConstructor01.ts b/tests/cases/fourslash/docCommentTemplateConstructor01.ts new file mode 100644 index 00000000000..c44d8fc22bd --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateConstructor01.ts @@ -0,0 +1,50 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +////class C { +//// private p; +//// /*0*/ +//// constructor(a, b, c, d); +//// /*1*/ +//// constructor(public a, private b, protected c, d, e?) { +//// } +//// +//// foo(); +//// foo(a?, b?, ...args) { +//// } +////} + +confirmNormalizedJsDoc("0", /*indentation*/ 4, ` +/** + * + * @param a + * @param b + * @param c + * @param d + */`); + +confirmNormalizedJsDoc("1", /*indentation*/ 4, ` +/** + * + * @param a + * @param b + * @param c + * @param d + */`); diff --git a/tests/cases/fourslash/docCommentTemplateNamespaces01.ts b/tests/cases/fourslash/docCommentTemplateNamespaces01.ts new file mode 100644 index 00000000000..6c10d5f5395 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateNamespaces01.ts @@ -0,0 +1,46 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +/////*namespaceN*/ +////namespace n { +////} +//// +/////*namespaceM*/ +////module m { +////} +//// +/////*ambientModule*/ +////module "ambientModule" { +////} + +confirmNormalizedJsDoc("namespaceN", /*indentation*/ 4, ` +/** + * + */`); + +confirmNormalizedJsDoc("namespaceM", /*indentation*/ 4, ` +/** + * + */`); + +confirmNormalizedJsDoc("namespaceM", /*indentation*/ 4, ` +/** + * + */`); diff --git a/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts b/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts new file mode 100644 index 00000000000..11ea2b52967 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts @@ -0,0 +1,54 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +/////*a*/ +////var a = 10; +//// +/////*b*/ +////let b = ""; +//// +/////*c*/ +////const c = 30; +//// +/////*d*/ +////let d = function d(x, y, z) { +//// return +(x + y + z); +////}; +//// +/////*e*/ +////let e = class E { +//// constructor(a, b, c) { +//// this.a = a; +//// this.b = b || (this.c = c); +//// } +////} +//// +/////*f*/ +////let f = { +//// foo: 10, +//// bar: "20" +////}; + +for (const varName of "abcdef".split("")) { + confirmNormalizedJsDoc(varName, /*indentation*/ 0, ` +/** + * + */`); +} diff --git a/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts b/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts new file mode 100644 index 00000000000..7ff2115c7d6 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts @@ -0,0 +1,54 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +/////*a*/ +////var a1 = 10, a2 = 20; +//// +/////*b*/ +////let b1 = "", b2 = true; +//// +/////*c*/ +////const c1 = 30, c2 = 40; +//// +/////*d*/ +////let d1 = function d(x, y, z) { +//// return +(x + y + z); +////}, d2 = 50; +//// +/////*e*/ +////let e1 = class E { +//// constructor(a, b, c) { +//// this.a = a; +//// this.b = b || (this.c = c); +//// } +////}, e2 = () => 100; +//// +/////*f*/ +////let f1 = { +//// foo: 10, +//// bar: "20" +////}, f2 = null; + +for (const varName of "abcdef".split("")) { + confirmNormalizedJsDoc(varName, /*indentation*/ 0, ` +/** + * + */`); +} From 1545ab56f3e4afbbbbdaef4a05ffa0cc76f1a4e4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 14:58:12 -0700 Subject: [PATCH 2/8] Use a loop because reduce is unreadable. --- src/services/services.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 87cca1fe0f1..90885043720 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -7030,6 +7030,7 @@ namespace ts { // - class decls let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); + if (!containingFunction || containingFunction.getStart() < position) { return undefined; } @@ -7043,9 +7044,15 @@ namespace ts { // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; - let docParams = parameters.reduce((prev, cur, index) => - prev + - indentationStr + " * @param " + (cur.name.kind === SyntaxKind.Identifier ? (cur.name).text : "param" + index) + newLine, ""); + let docParams = ""; + for (let i = 0, numParams = parameters.length; i < numParams; i++) { + const currentName = parameters[i].name; + const paramName = currentName.kind === SyntaxKind.Identifier ? + (currentName).text : + "param" + i; + + docParams += `${indentationStr} * @param ${paramName}${newLine}`; + } // A doc comment consists of the following // * The opening comment line From 7f4f461a84b7bf71503d14e57e6b1936acb7d406 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 16:30:40 -0700 Subject: [PATCH 3/8] Amended tests. --- .../docCommentTemplateClassDecl01.ts | 9 +-- .../docCommentTemplateClassDeclMethods01.ts | 59 ++++++++++--------- .../docCommentTemplateConstructor01.ts | 38 ++++++------ .../docCommentTemplateNamespaces01.ts | 10 ++-- .../docCommentTemplateVariableStatements01.ts | 6 +- .../docCommentTemplateVariableStatements02.ts | 6 +- 6 files changed, 67 insertions(+), 61 deletions(-) diff --git a/tests/cases/fourslash/docCommentTemplateClassDecl01.ts b/tests/cases/fourslash/docCommentTemplateClassDecl01.ts index c7c858cd262..958a8c60fa4 100644 --- a/tests/cases/fourslash/docCommentTemplateClassDecl01.ts +++ b/tests/cases/fourslash/docCommentTemplateClassDecl01.ts @@ -12,10 +12,10 @@ function useCRLFAndStripLeadingNewline(str: string): string { return str; } -function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { +function confirmNormalizedJsDoc(markerName: string, newTextOffset: number, template: string): void { goTo.marker(markerName); const normalized = useCRLFAndStripLeadingNewline(template); - verify.DocCommentTemplate(normalized, indentation); + verify.DocCommentTemplate(normalized, newTextOffset); } /////*decl*/class C { @@ -29,7 +29,8 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat //// } ////} -confirmNormalizedJsDoc("decl", /*indentation*/ 0, ` +confirmNormalizedJsDoc("decl", /*newTextOffset*/ 8, ` /** * - */`); + */ +`); diff --git a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts index bb14d89e3bf..72f9ce10809 100644 --- a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts +++ b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts @@ -19,8 +19,8 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat } const enum Indentation { - Gutter = 0, - Proper = 4, + Standard = 8, + Indented = 12, } @@ -34,36 +34,39 @@ const enum Indentation { //// } ////} -confirmNormalizedJsDoc("0", Indentation.Gutter, ` +confirmNormalizedJsDoc("0", Indentation.Standard, ` /** * */`); -confirmNormalizedJsDoc("2", Indentation.Proper, ` -/** - * - * @param a - */`); +confirmNormalizedJsDoc("2", Indentation.Indented, + `/** + * + * @param a + */ + `); -confirmNormalizedJsDoc("3", Indentation.Proper, ` -/** - * - * @param a - * @param b - */`); +confirmNormalizedJsDoc("3", Indentation.Indented, + `/** + * + * @param a + * @param b + */ + `); -confirmNormalizedJsDoc("4", Indentation.Proper, ` -/** - * - * @param a - * @param param1 - * @param b - */`); +confirmNormalizedJsDoc("4", Indentation.Indented, + `/** + * + * @param a + * @param param1 + * @param c + */`); -confirmNormalizedJsDoc("5", Indentation.Proper, ` -/** - * - * @param a - * @param b - * @param args - */`); +confirmNormalizedJsDoc("5", Indentation.Indented, + `/** + * + * @param a + * @param b + * @param args + */ + `); diff --git a/tests/cases/fourslash/docCommentTemplateConstructor01.ts b/tests/cases/fourslash/docCommentTemplateConstructor01.ts index c44d8fc22bd..b26ece7a5e6 100644 --- a/tests/cases/fourslash/docCommentTemplateConstructor01.ts +++ b/tests/cases/fourslash/docCommentTemplateConstructor01.ts @@ -12,10 +12,10 @@ function useCRLFAndStripLeadingNewline(str: string): string { return str; } -function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { +function confirmNormalizedJsDoc(markerName: string, newTextOffset: number, template: string): void { goTo.marker(markerName); const normalized = useCRLFAndStripLeadingNewline(template); - verify.DocCommentTemplate(normalized, indentation); + verify.DocCommentTemplate(normalized, newTextOffset); } ////class C { @@ -31,20 +31,22 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat //// } ////} -confirmNormalizedJsDoc("0", /*indentation*/ 4, ` -/** - * - * @param a - * @param b - * @param c - * @param d - */`); +const newTextOffset = 12; +confirmNormalizedJsDoc("0", /*newTextOffset*/ newTextOffset, + `/** + * + * @param a + * @param b + * @param c + * @param d + */`); -confirmNormalizedJsDoc("1", /*indentation*/ 4, ` -/** - * - * @param a - * @param b - * @param c - * @param d - */`); +confirmNormalizedJsDoc("1", /*newTextOffset*/ newTextOffset, + `/** + * + * @param a + * @param b + * @param c + * @param d + * @param e + */`); diff --git a/tests/cases/fourslash/docCommentTemplateNamespaces01.ts b/tests/cases/fourslash/docCommentTemplateNamespaces01.ts index 6c10d5f5395..4d9fb987be5 100644 --- a/tests/cases/fourslash/docCommentTemplateNamespaces01.ts +++ b/tests/cases/fourslash/docCommentTemplateNamespaces01.ts @@ -12,10 +12,10 @@ function useCRLFAndStripLeadingNewline(str: string): string { return str; } -function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { +function confirmNormalizedJsDoc(markerName: string, charOffset: number, template: string): void { goTo.marker(markerName); const normalized = useCRLFAndStripLeadingNewline(template); - verify.DocCommentTemplate(normalized, indentation); + verify.DocCommentTemplate(normalized, charOffset); } /////*namespaceN*/ @@ -30,17 +30,17 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat ////module "ambientModule" { ////} -confirmNormalizedJsDoc("namespaceN", /*indentation*/ 4, ` +confirmNormalizedJsDoc("namespaceN", /*indentation*/ 8, ` /** * */`); -confirmNormalizedJsDoc("namespaceM", /*indentation*/ 4, ` +confirmNormalizedJsDoc("namespaceM", /*indentation*/ 8, ` /** * */`); -confirmNormalizedJsDoc("namespaceM", /*indentation*/ 4, ` +confirmNormalizedJsDoc("namespaceM", /*indentation*/ 8, ` /** * */`); diff --git a/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts b/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts index 11ea2b52967..6859d9aa1ec 100644 --- a/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts +++ b/tests/cases/fourslash/docCommentTemplateVariableStatements01.ts @@ -12,10 +12,10 @@ function useCRLFAndStripLeadingNewline(str: string): string { return str; } -function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { +function confirmNormalizedJsDoc(markerName: string, newTextOffset: number, template: string): void { goTo.marker(markerName); const normalized = useCRLFAndStripLeadingNewline(template); - verify.DocCommentTemplate(normalized, indentation); + verify.DocCommentTemplate(normalized, newTextOffset); } /////*a*/ @@ -47,7 +47,7 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat ////}; for (const varName of "abcdef".split("")) { - confirmNormalizedJsDoc(varName, /*indentation*/ 0, ` + confirmNormalizedJsDoc(varName, /*newTextOffset*/ 8, ` /** * */`); diff --git a/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts b/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts index 7ff2115c7d6..9339e703570 100644 --- a/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts +++ b/tests/cases/fourslash/docCommentTemplateVariableStatements02.ts @@ -12,10 +12,10 @@ function useCRLFAndStripLeadingNewline(str: string): string { return str; } -function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { +function confirmNormalizedJsDoc(markerName: string, newTextOffset: number, template: string): void { goTo.marker(markerName); const normalized = useCRLFAndStripLeadingNewline(template); - verify.DocCommentTemplate(normalized, indentation); + verify.DocCommentTemplate(normalized, newTextOffset); } /////*a*/ @@ -47,7 +47,7 @@ function confirmNormalizedJsDoc(markerName: string, indentation: number, templat ////}, f2 = null; for (const varName of "abcdef".split("")) { - confirmNormalizedJsDoc(varName, /*indentation*/ 0, ` + confirmNormalizedJsDoc(varName, /*newTextOffset*/ 8, ` /** * */`); From 67b44b59c0754817bce5d4011bcf85541e82f188 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 16:40:13 -0700 Subject: [PATCH 4/8] Add JSDoc to methods, constructors, classes, and namespace/module declarations. --- src/compiler/utilities.ts | 2 +- src/harness/fourslash.ts | 9 ++++++++- src/services/services.ts | 25 +++++++++++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3397cd242b1..9928be4529b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -621,7 +621,7 @@ namespace ts { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } - export function isFunctionLike(node: Node): boolean { + export function isFunctionLike(node: Node): node is FunctionLikeDeclaration { if (node) { switch (node.kind) { case SyntaxKind.Constructor: diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 1d333a29ccb..7faf4d1cc0b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1908,7 +1908,7 @@ module FourSlash { } if (actual.newText !== expected.newText) { - this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); + this.raiseError(name + ' failed - expected insertion:\n' + this.clarifyNewlines(expected.newText) + '\nactual insertion:\n' + this.clarifyNewlines(actual.newText)); } if (actual.caretOffset !== expected.caretOffset) { @@ -1917,6 +1917,13 @@ module FourSlash { } } + private clarifyNewlines(str: string) { + return str.replace(/\r?\n/g, lineEnding => { + const representation = lineEnding === "\r\n" ? "CRLF" : "LF"; + return "# - " + representation + lineEnding; + }); + } + public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { this.taoInvalidReason = "verifyMatchingBracePosition NYI"; diff --git a/src/services/services.ts b/src/services/services.ts index 90885043720..3d4ecc4a14d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -7028,14 +7028,31 @@ namespace ts { // - methods // - constructors // - class decls - let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); + let commentOwner: Node; + findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { + switch (commentOwner.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.VariableStatement: + break findOwner; + case SyntaxKind.SourceFile: + return undefined; + case SyntaxKind.ModuleDeclaration: + // We don't want to give back a JSDoc for the 'b' in 'module a.b'. + if (false && commentOwner.parent.kind === SyntaxKind.ModuleDeclaration) { + return undefined; + } + break findOwner; + } + } - - if (!containingFunction || containingFunction.getStart() < position) { + if (!commentOwner || commentOwner.getStart() < position) { return undefined; } - let parameters = containingFunction.parameters; + let parameters = isFunctionLike(commentOwner) ? commentOwner.parameters : emptyArray; let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; From 08e2b0a15958a4adc86fa080bd4ad584c3ee79f4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 17:09:16 -0700 Subject: [PATCH 5/8] Added tests for dotted namespace declarations, object literal methods. --- .../docCommentTemplateClassDeclMethods01.ts | 7 +++ .../docCommentTemplateClassDeclMethods02.ts | 46 +++++++++++++++++++ ...cCommentTemplateNamespacesAndModules01.ts} | 0 ...ocCommentTemplateNamespacesAndModules02.ts | 36 +++++++++++++++ ...ocCommentTemplateObjectLiteralMethods01.ts | 46 +++++++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 tests/cases/fourslash/docCommentTemplateClassDeclMethods02.ts rename tests/cases/fourslash/{docCommentTemplateNamespaces01.ts => docCommentTemplateNamespacesAndModules01.ts} (100%) create mode 100644 tests/cases/fourslash/docCommentTemplateNamespacesAndModules02.ts create mode 100644 tests/cases/fourslash/docCommentTemplateObjectLiteralMethods01.ts diff --git a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts index 72f9ce10809..43881c92816 100644 --- a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts +++ b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts @@ -39,6 +39,13 @@ confirmNormalizedJsDoc("0", Indentation.Standard, ` * */`); + +confirmNormalizedJsDoc("1", Indentation.Indented, + `/** + * + */`); + + confirmNormalizedJsDoc("2", Indentation.Indented, `/** * diff --git a/tests/cases/fourslash/docCommentTemplateClassDeclMethods02.ts b/tests/cases/fourslash/docCommentTemplateClassDeclMethods02.ts new file mode 100644 index 00000000000..99392cf3855 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateClassDeclMethods02.ts @@ -0,0 +1,46 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +const enum Indentation { + Indented = 12, +} + + +////class C { +//// /*0*/ +//// [Symbol.iterator]() { +//// return undefined; +//// } +//// /*1*/ +//// [1 + 2 + 3 + Math.rand()](x: number, y: string, z = true) { } +////} + +confirmNormalizedJsDoc("0", Indentation.Indented, + `/** + * + */`); + +confirmNormalizedJsDoc("1", Indentation.Indented, + `/** + * + * @param x + * @param y + * @param z + */`); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateNamespaces01.ts b/tests/cases/fourslash/docCommentTemplateNamespacesAndModules01.ts similarity index 100% rename from tests/cases/fourslash/docCommentTemplateNamespaces01.ts rename to tests/cases/fourslash/docCommentTemplateNamespacesAndModules01.ts diff --git a/tests/cases/fourslash/docCommentTemplateNamespacesAndModules02.ts b/tests/cases/fourslash/docCommentTemplateNamespacesAndModules02.ts new file mode 100644 index 00000000000..e59b16d6163 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateNamespacesAndModules02.ts @@ -0,0 +1,36 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, charOffset: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, charOffset); +} + +/////*top*/ +////namespace n1. +//// /*n2*/ n2. +//// /*n3*/ n3 { +////} + +confirmNormalizedJsDoc("top", /*indentation*/ 8, ` +/** + * + */`); + +goTo.marker("n2"); +verify.noDocCommentTemplate(); + +goTo.marker("n3"); +verify.noDocCommentTemplate(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentTemplateObjectLiteralMethods01.ts b/tests/cases/fourslash/docCommentTemplateObjectLiteralMethods01.ts new file mode 100644 index 00000000000..4af1b60c698 --- /dev/null +++ b/tests/cases/fourslash/docCommentTemplateObjectLiteralMethods01.ts @@ -0,0 +1,46 @@ +/// + +const CRLF = "\r\n"; +/** + * @returns the given value with '\n' normalized to '\r\n' and with no leading newline + */ +function useCRLFAndStripLeadingNewline(str: string): string { + str = str.replace(/\r?\n/g, CRLF); + if (str.indexOf(CRLF) === 0) { + str = str.slice(CRLF.length); + } + return str; +} + +function confirmNormalizedJsDoc(markerName: string, indentation: number, template: string): void { + goTo.marker(markerName); + const normalized = useCRLFAndStripLeadingNewline(template); + verify.DocCommentTemplate(normalized, indentation); +} + +const enum Indentation { + Indented = 12, +} + + +////var x = { +//// /*0*/ +//// foo() { +//// return undefined; +//// } +//// /*1*/ +//// [1 + 2 + 3 + Math.rand()](x: number, y: string, z = true) { } +////} + +confirmNormalizedJsDoc("0", Indentation.Indented, + `/** + * + */`); + +confirmNormalizedJsDoc("1", Indentation.Indented, + `/** + * + * @param x + * @param y + * @param z + */`); \ No newline at end of file From 81dabb4d515e7f1854556c99e3d7c3a4c98977a6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 24 Sep 2015 17:09:48 -0700 Subject: [PATCH 6/8] Ensure that doc comments don't appear between dotted names. Also updated TODO --- src/services/services.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 3d4ecc4a14d..b5c64a434fa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -7025,9 +7025,10 @@ namespace ts { } // TODO: add support for: - // - methods - // - constructors - // - class decls + // - enums/enum members + // - interfaces + // - property declarations + // - potentially property assignments let commentOwner: Node; findOwner: for (commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { switch (commentOwner.kind) { @@ -7041,7 +7042,7 @@ namespace ts { return undefined; case SyntaxKind.ModuleDeclaration: // We don't want to give back a JSDoc for the 'b' in 'module a.b'. - if (false && commentOwner.parent.kind === SyntaxKind.ModuleDeclaration) { + if (commentOwner.parent.kind === SyntaxKind.ModuleDeclaration) { return undefined; } break findOwner; From 43a6eb8171e14efb4285e5dbe213910ca976fc03 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 25 Sep 2015 11:43:29 -0700 Subject: [PATCH 7/8] Switched parameter name to array binding pattern. --- tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts index 43881c92816..da407b632ef 100644 --- a/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts +++ b/tests/cases/fourslash/docCommentTemplateClassDeclMethods01.ts @@ -29,7 +29,7 @@ const enum Indentation { //// foo(); //// /*2*/foo(a); //// /*3*/foo(a, b); -//// /*4*/ foo(a, {x: string}, c); +//// /*4*/ foo(a, {x: string}, [c]); //// /*5*/foo(a?, b?, ...args) { //// } ////} @@ -66,7 +66,7 @@ confirmNormalizedJsDoc("4", Indentation.Indented, * * @param a * @param param1 - * @param c + * @param param2 */`); confirmNormalizedJsDoc("5", Indentation.Indented, From a458d4b2f4a5c7a19ee12fcf4f13c79c0400999f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 25 Sep 2015 11:49:11 -0700 Subject: [PATCH 8/8] Amended comments. --- src/services/services.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index b5c64a434fa..4326e57f93e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6997,8 +6997,12 @@ namespace ts { * Checks if position points to a valid position to add JSDoc comments, and if so, * returns the appropriate template. Otherwise returns an empty string. * Valid positions are - * - outside of comments, statements, and expressions, and - * - preceding a function declaration. + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations * * Hosts should ideally check that: * - The line is all whitespace up to 'position' before performing the insertion. @@ -7041,7 +7045,9 @@ namespace ts { case SyntaxKind.SourceFile: return undefined; case SyntaxKind.ModuleDeclaration: - // We don't want to give back a JSDoc for the 'b' in 'module a.b'. + // If in walking up the tree, we hit a a nested namespace declaration, + // then we must be somewhere within a dotted namespace name; however we don't + // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. if (commentOwner.parent.kind === SyntaxKind.ModuleDeclaration) { return undefined; }