diff --git a/src/services/services.ts b/src/services/services.ts index 4f3e84661ad..08e76f08ec7 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -346,7 +346,8 @@ module ts { function isName(pos: number, end: number, sourceFile: SourceFile, name: string) { return pos + name.length < end && sourceFile.text.substr(pos, name.length) === name && - isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)); + (isWhiteSpace(sourceFile.text.charCodeAt(pos + name.length)) || + isLineBreak(sourceFile.text.charCodeAt(pos + name.length))); } function isParamTag(pos: number, end: number, sourceFile: SourceFile) { @@ -354,9 +355,19 @@ module ts { return isName(pos, end, sourceFile, paramTag); } + function pushDocCommentLineText(docComments: SymbolDisplayPart[], text: string, blankLineCount: number) { + // Add the empty lines in between texts + while (blankLineCount) { + docComments.push(textPart("")); + blankLineCount--; + } + docComments.push(textPart(text)); + } + function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { var spacesToRemoveAfterAsterisk: number; var docComments: SymbolDisplayPart[] = []; + var blankLineCount = 0; var isInParamTag = false; while (pos < end) { @@ -405,7 +416,12 @@ module ts { // Continue with next line pos = consumeLineBreaks(pos, end, sourceFile); if (docCommentTextOfLine) { - docComments.push(textPart(docCommentTextOfLine)); + pushDocCommentLineText(docComments, docCommentTextOfLine, blankLineCount); + blankLineCount = 0; + } + else if (!isInParamTag && docComments.length) { + // This is blank line when there is text already parsed + blankLineCount++; } } @@ -417,6 +433,8 @@ module ts { var paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { + var blankLineCount = 0; + var recordedParamTag = false; // Consume leading spaces pos = consumeWhiteSpaces(pos + paramTag.length); if (pos >= end) { @@ -478,8 +496,13 @@ module ts { // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { if (paramHelpString) { - paramDocComments.push(textPart(paramHelpString)); + pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); paramHelpString = ""; + blankLineCount = 0; + recordedParamTag = true; + } + else if (recordedParamTag) { + blankLineCount++; } // Get the pos after cleaning start of the line @@ -500,7 +523,7 @@ module ts { // If there is param help text, add it top the doc comments if (paramHelpString) { - paramDocComments.push(textPart(paramHelpString)); + pushDocCommentLineText(paramDocComments, paramHelpString, blankLineCount); } paramHelpStringMargin = undefined; } diff --git a/tests/cases/fourslash/commentsLinePreservation.ts b/tests/cases/fourslash/commentsLinePreservation.ts new file mode 100644 index 00000000000..012272d7544 --- /dev/null +++ b/tests/cases/fourslash/commentsLinePreservation.ts @@ -0,0 +1,161 @@ +/// + +/////** This is firstLine +//// * This is second Line +//// * +//// * This is fourth Line +//// */ +////var /*a*/a: string; +/////** +//// * This is firstLine +//// * This is second Line +//// * +//// * This is fourth Line +//// */ +////var /*b*/b: string; +/////** +//// * This is firstLine +//// * This is second Line +//// * +//// * This is fourth Line +//// * +//// */ +////var /*c*/c: string; +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param +//// * @random tag This should be third line +//// */ +////function /*d*/d(param: string) { /*1*/param = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param +//// */ +////function /*e*/e(param: string) { /*2*/param = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 first line of param +//// * +//// * param information third line +//// * @random tag This should be third line +//// */ +////function /*f*/f(param1: string) { /*3*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 +//// * +//// * param information first line +//// * @random tag This should be third line +//// */ +////function /*g*/g(param1: string) { /*4*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 +//// * +//// * param information first line +//// * +//// * param information third line +//// * @random tag This should be third line +//// */ +////function /*h*/h(param1: string) { /*5*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 +//// * +//// * param information first line +//// * +//// * param information third line +//// * +//// */ +////function /*i*/i(param1: string) { /*6*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 +//// * +//// * param information first line +//// * +//// * param information third line +//// */ +////function /*j*/j(param1: string) { /*7*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 hello @randomtag +//// * +//// * random information first line +//// * +//// * random information third line +//// */ +////function /*k*/k(param1: string) { /*8*/param1 = "hello"; } +/////** +//// * This is firstLine +//// * This is second Line +//// * @param param1 first Line text +//// * +//// * @param param1 +//// * +//// * blank line that shouldnt be shown when starting this +//// * second time information about the param again +//// */ +////function /*l*/l(param1: string) { /*9*/param1 = "hello"; } + +goTo.marker('a'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line"); + +goTo.marker('b'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line"); + +goTo.marker('c'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n\nThis is fourth Line"); + +goTo.marker('d'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line"); +goTo.marker('1'); +verify.quickInfoIs(undefined, ""); + +goTo.marker('e'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line"); +goTo.marker('2'); +verify.quickInfoIs(undefined, ""); + +goTo.marker('f'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line"); +goTo.marker('3'); +verify.quickInfoIs(undefined, "first line of param\n\nparam information third line"); + +goTo.marker('g'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line"); +goTo.marker('4'); +verify.quickInfoIs(undefined, "param information first line"); + +goTo.marker('h'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@random tag This should be third line"); +goTo.marker('5'); +verify.quickInfoIs(undefined, "param information first line\n\nparam information third line"); + +goTo.marker('i'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line"); +goTo.marker('6'); +verify.quickInfoIs(undefined, "param information first line\n\nparam information third line"); + +goTo.marker('j'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line"); +goTo.marker('7'); +verify.quickInfoIs(undefined, "param information first line\n\nparam information third line"); + +goTo.marker('k'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line\n@randomtag \n\n random information first line\n\n random information third line"); +goTo.marker('8'); +verify.quickInfoIs(undefined, "hello "); + +goTo.marker('l'); +verify.quickInfoIs(undefined, "This is firstLine\nThis is second Line"); +goTo.marker('9'); +verify.quickInfoIs(undefined, "first Line text\nblank line that shouldnt be shown when starting this \nsecond time information about the param again");