diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 3be657d4cd02b..84d4e753ad02f 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -2500,18 +2500,35 @@ namespace FourSlash { public printOutliningSpans() { const spans = this.languageService.getOutliningSpans(this.activeFile.fileName); - Harness.IO.log(`Outlining spans (${spans.length} items)`); + Harness.IO.log(`Outlining spans (${spans.length} items)\nResults:`); Harness.IO.log(stringify(spans)); + this.printOutliningSpansInline(spans); + } + + private printOutliningSpansInline(spans: ts.OutliningSpan[]) { + const allSpanInsets = [] as { text: string, pos: number }[]; + let annotated = this.activeFile.content; + ts.forEach(spans, span => { + allSpanInsets.push({ text: "[|", pos: span.textSpan.start }); + allSpanInsets.push({ text: "|]", pos: span.textSpan.start + span.textSpan.length }); + }); + + const reverseSpans = allSpanInsets.sort((l, r) => r.pos - l.pos); + ts.forEach(reverseSpans, span => { + annotated = annotated.slice(0, span.pos) + span.text + annotated.slice(span.pos); + }); + Harness.IO.log(`\nMockup:\n${annotated}`); } public verifyOutliningSpans(spans: Range[], kind?: "comment" | "region" | "code" | "imports") { const actual = this.languageService.getOutliningSpans(this.activeFile.fileName); - if (actual.length !== spans.length) { - this.raiseError(`verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}`); + const filterActual = ts.filter(actual, f => kind === undefined ? true : f.kind === kind); + if (filterActual.length !== spans.length) { + this.raiseError(`verifyOutliningSpans failed - expected total spans to be ${spans.length}, but was ${actual.length}\n\nFound Spans:\n\n${this.printOutliningSpansInline(actual)}`); } - ts.zipWith(spans, actual, (expectedSpan, actualSpan, i) => { + ts.zipWith(spans, filterActual, (expectedSpan, actualSpan, i) => { if (expectedSpan.pos !== actualSpan.textSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan)) { return this.raiseError(`verifyOutliningSpans failed - span ${(i + 1)} expected: (${expectedSpan.pos},${expectedSpan.end}), actual: (${actualSpan.textSpan.start},${ts.textSpanEnd(actualSpan.textSpan)})`); } diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index b6212e2a2d285..ab8cfb3f6c33e 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -10,7 +10,8 @@ namespace ts.OutliningElementsCollector { function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { let depthRemaining = 40; let current = 0; - const statements = sourceFile.statements; + // Includes the EOF Token so that comments which aren't attached to statements are included + const statements = [...sourceFile.statements, sourceFile.endOfFileToken]; const n = statements.length; while (current < n) { while (current < n && !isAnyImportSyntax(statements[current])) { @@ -33,7 +34,7 @@ namespace ts.OutliningElementsCollector { if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); - if (isDeclaration(n)) { + if (isDeclaration(n) || n.kind === SyntaxKind.EndOfFileToken) { addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out); } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index d44148972fbf9..beb9d0c4d841f 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -317,7 +317,7 @@ declare namespace FourSlashInterface { baselineQuickInfo(): void; baselineSmartSelection(): void; nameOrDottedNameSpanTextIs(text: string): void; - outliningSpansInCurrentFile(spans: Range[]): void; + outliningSpansInCurrentFile(spans: Range[], kind?: "comment" | "region" | "code" | "imports"): void; outliningHintSpansInCurrentFile(spans: Range[]): void; todoCommentsInCurrentFile(descriptors: string[]): void; matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number): void; diff --git a/tests/cases/fourslash/outlineSpansBlockCommentsWithoutStatements.ts b/tests/cases/fourslash/outlineSpansBlockCommentsWithoutStatements.ts new file mode 100644 index 0000000000000..1d0fd91e78327 --- /dev/null +++ b/tests/cases/fourslash/outlineSpansBlockCommentsWithoutStatements.ts @@ -0,0 +1,9 @@ +/// + +// #22732 + +////[|/* +///// * Some text +//// */|] + +verify.outliningHintSpansInCurrentFile(test.ranges()); diff --git a/tests/cases/fourslash/outlineSpansTrailingBlockCommentsAfterStatements.ts b/tests/cases/fourslash/outlineSpansTrailingBlockCommentsAfterStatements.ts new file mode 100644 index 0000000000000..2397be94b56f1 --- /dev/null +++ b/tests/cases/fourslash/outlineSpansTrailingBlockCommentsAfterStatements.ts @@ -0,0 +1,10 @@ +/// + +// #22732 + +////console.log(0); +////[|/* +///// * Some text +//// */|] + +verify.outliningHintSpansInCurrentFile(test.ranges()); diff --git a/tests/cases/fourslash/server/getOutliningSpansForRegions.ts b/tests/cases/fourslash/server/getOutliningSpansForRegions.ts index 81d2409cf9db7..dbfe68204dc75 100644 --- a/tests/cases/fourslash/server/getOutliningSpansForRegions.ts +++ b/tests/cases/fourslash/server/getOutliningSpansForRegions.ts @@ -48,4 +48,4 @@ ////// #endregion ////*/ -verify.outliningSpansInCurrentFile(test.ranges(), "region"); +verify.outliningSpansInCurrentFile(test.ranges(), "region"); \ No newline at end of file