Skip to content

Commit 29895e8

Browse files
authored
Handle header comments better by comparing its end line with first node line (microsoft#36413)
Fixes microsoft#31508
1 parent 420b478 commit 29895e8

File tree

2 files changed

+126
-13
lines changed

2 files changed

+126
-13
lines changed

src/services/textChanges.ts

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,23 +1152,46 @@ namespace ts.textChanges {
11521152
advancePastLineBreak();
11531153
}
11541154

1155-
// For a source file, it is possible there are detached comments we should not skip
1156-
let ranges = getLeadingCommentRanges(text, position);
1155+
const ranges = getLeadingCommentRanges(text, position);
11571156
if (!ranges) return position;
1158-
// However we should still skip a pinned comment at the top
1159-
if (ranges.length && ranges[0].kind === SyntaxKind.MultiLineCommentTrivia && isPinnedComment(text, ranges[0].pos)) {
1160-
position = ranges[0].end;
1161-
advancePastLineBreak();
1162-
ranges = ranges.slice(1);
1163-
}
1164-
// As well as any triple slash references
1157+
1158+
// Find the first attached comment to the first node and add before it
1159+
let lastComment: { range: CommentRange; pinnedOrTripleSlash: boolean; } | undefined;
1160+
let firstNodeLine: number | undefined;
11651161
for (const range of ranges) {
1166-
if (range.kind === SyntaxKind.SingleLineCommentTrivia && isRecognizedTripleSlashComment(text, range.pos, range.end)) {
1167-
position = range.end;
1168-
advancePastLineBreak();
1162+
if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
1163+
if (isPinnedComment(text, range.pos)) {
1164+
lastComment = { range, pinnedOrTripleSlash: true };
1165+
continue;
1166+
}
1167+
}
1168+
else if (isRecognizedTripleSlashComment(text, range.pos, range.end)) {
1169+
lastComment = { range, pinnedOrTripleSlash: true };
11691170
continue;
11701171
}
1171-
break;
1172+
1173+
if (lastComment) {
1174+
// Always insert after pinned or triple slash comments
1175+
if (lastComment.pinnedOrTripleSlash) break;
1176+
1177+
// There was a blank line between the last comment and this comment.
1178+
// This comment is not part of the copyright comments
1179+
const commentLine = sourceFile.getLineAndCharacterOfPosition(range.pos).line;
1180+
const lastCommentEndLine = sourceFile.getLineAndCharacterOfPosition(lastComment.range.end).line;
1181+
if (commentLine >= lastCommentEndLine + 2) break;
1182+
}
1183+
1184+
if (sourceFile.statements.length) {
1185+
if (firstNodeLine === undefined) firstNodeLine = sourceFile.getLineAndCharacterOfPosition(sourceFile.statements[0].getStart()).line;
1186+
const commentEndLine = sourceFile.getLineAndCharacterOfPosition(range.end).line;
1187+
if (firstNodeLine < commentEndLine + 2) break;
1188+
}
1189+
lastComment = { range, pinnedOrTripleSlash: false };
1190+
}
1191+
1192+
if (lastComment) {
1193+
position = lastComment.range.end;
1194+
advancePastLineBreak();
11721195
}
11731196
return position;
11741197

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: /a.ts
4+
////export class A { }
5+
6+
// @Filename: /b.ts
7+
/////*---------------------------------------------------------------------------------------------
8+
//// * Copyright (c) Microsoft Corporation. All rights reserved.
9+
//// * Licensed under the MIT License. See License.txt in the project root for license information.
10+
//// *--------------------------------------------------------------------------------------------*/
11+
////
12+
////export class B extends A { }
13+
14+
// @Filename: /c.ts
15+
/////*---------------------------------------------------------------------------------------------
16+
//// * Copyright (c) Microsoft Corporation. All rights reserved.
17+
//// * Licensed under the MIT License. See License.txt in the project root for license information.
18+
//// *--------------------------------------------------------------------------------------------*/
19+
////
20+
//// /// <reference types="node" />
21+
//// /// <reference path="./a.ts" />
22+
//// /// <amd-dependency path="./b.ts" />
23+
////export class C extends A { }
24+
25+
// @Filename: /d.ts
26+
/////*---------------------------------------------------------------------------------------------
27+
//// * Copyright (c) Microsoft Corporation. All rights reserved.
28+
//// * Licensed under the MIT License. See License.txt in the project root for license information.
29+
//// *--------------------------------------------------------------------------------------------*/
30+
////
31+
//// /// <reference types="node" />
32+
//// /// <reference path="./a.ts" />
33+
//// /// <amd-dependency path="./b.ts" />
34+
//// /**
35+
//// * This is a comment intended to be attached to this interface
36+
//// */
37+
////export class D extends A { }
38+
39+
goTo.file("/b.ts");
40+
verify.codeFix({
41+
description: ignoreInterpolations(ts.Diagnostics.Import_0_from_module_1),
42+
newFileContent:
43+
`/*---------------------------------------------------------------------------------------------
44+
* Copyright (c) Microsoft Corporation. All rights reserved.
45+
* Licensed under the MIT License. See License.txt in the project root for license information.
46+
*--------------------------------------------------------------------------------------------*/
47+
48+
import { A } from "./a";
49+
50+
export class B extends A { }`,
51+
});
52+
53+
goTo.file("/c.ts");
54+
verify.codeFix({
55+
description: ignoreInterpolations(ts.Diagnostics.Import_0_from_module_1),
56+
newFileContent:
57+
`/*---------------------------------------------------------------------------------------------
58+
* Copyright (c) Microsoft Corporation. All rights reserved.
59+
* Licensed under the MIT License. See License.txt in the project root for license information.
60+
*--------------------------------------------------------------------------------------------*/
61+
62+
/// <reference types="node" />
63+
/// <reference path="./a.ts" />
64+
/// <amd-dependency path="./b.ts" />
65+
66+
import { A } from "./a";
67+
68+
export class C extends A { }`,
69+
});
70+
71+
goTo.file("/d.ts");
72+
verify.codeFix({
73+
description: ignoreInterpolations(ts.Diagnostics.Import_0_from_module_1),
74+
newFileContent:
75+
`/*---------------------------------------------------------------------------------------------
76+
* Copyright (c) Microsoft Corporation. All rights reserved.
77+
* Licensed under the MIT License. See License.txt in the project root for license information.
78+
*--------------------------------------------------------------------------------------------*/
79+
80+
/// <reference types="node" />
81+
/// <reference path="./a.ts" />
82+
/// <amd-dependency path="./b.ts" />
83+
84+
import { A } from "./a";
85+
86+
/**
87+
* This is a comment intended to be attached to this interface
88+
*/
89+
export class D extends A { }`,
90+
});

0 commit comments

Comments
 (0)