Skip to content

Commit aa99aa4

Browse files
author
Armando Aguirre
committed
Added comment and uncomment selection
1 parent 8590d6c commit aa99aa4

20 files changed

+365
-33
lines changed

src/harness/client.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,14 @@ namespace ts.server {
816816
throw new Error("Method not implemented.");
817817
}
818818

819+
commentSelection(): ts.TextChange[] {
820+
throw new Error("Method not implemented.");
821+
}
822+
823+
uncommentSelection(): ts.TextChange[] {
824+
throw new Error("Method not implemented.");
825+
}
826+
819827
clearSourceMapperCache(): never {
820828
return notImplemented();
821829
}

src/harness/fourslashImpl.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,6 +3651,28 @@ namespace FourSlash {
36513651

36523652
this.verifyCurrentFileContent(newFileContent);
36533653
}
3654+
3655+
public commentSelection(newFileContent: string): void {
3656+
let changes: ts.TextChange[] = [];
3657+
for (let range of this.getRanges()) {
3658+
changes.push.apply(changes, this.languageService.commentSelection(this.activeFile.fileName, range));
3659+
}
3660+
3661+
this.applyEdits(this.activeFile.fileName, changes);
3662+
3663+
this.verifyCurrentFileContent(newFileContent);
3664+
}
3665+
3666+
public uncommentSelection(newFileContent: string): void {
3667+
let changes: ts.TextChange[] = [];
3668+
for (let range of this.getRanges()) {
3669+
changes.push.apply(changes, this.languageService.uncommentSelection(this.activeFile.fileName, range));
3670+
}
3671+
3672+
this.applyEdits(this.activeFile.fileName, changes);
3673+
3674+
this.verifyCurrentFileContent(newFileContent);
3675+
}
36543676
}
36553677

36563678
function prefixMessage(message: string | undefined) {

src/harness/fourslashInterfaceImpl.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@ namespace FourSlashInterface {
218218
public toggleMultilineComment(newFileContent: string) {
219219
this.state.toggleMultilineComment(newFileContent);
220220
}
221+
222+
public commentSelection(newFileContent: string) {
223+
this.state.commentSelection(newFileContent);
224+
}
225+
226+
public uncommentSelection(newFileContent: string) {
227+
this.state.uncommentSelection(newFileContent);
228+
}
221229
}
222230

223231
export class Verify extends VerifyNegatable {

src/harness/harnessLanguageService.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,12 @@ namespace Harness.LanguageService {
604604
toggleMultilineComment(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
605605
return unwrapJSONCallResult(this.shim.toggleMultilineComment(fileName, textRange));
606606
}
607+
commentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
608+
return unwrapJSONCallResult(this.shim.commentSelection(fileName, textRange));
609+
}
610+
uncommentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
611+
return unwrapJSONCallResult(this.shim.uncommentSelection(fileName, textRange));
612+
}
607613
clearSourceMapperCache(): never {
608614
return ts.notImplemented();
609615
}

src/server/protocol.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,17 @@ namespace ts.server.protocol {
137137
/* @internal */
138138
SelectionRangeFull = "selectionRange-full",
139139
ToggleLineComment = "toggleLineComment",
140+
/* @internal */
140141
ToggleLineCommentFull = "toggleLineComment-full",
141142
ToggleMultilineComment = "toggleMultilineComment",
143+
/* @internal */
142144
ToggleMultilineCommentFull = "toggleMultilineComment-full",
143-
145+
CommentSelection = "commentSelection",
146+
/* @internal */
147+
CommentSelectionFull = "commentSelection-full",
148+
UncommentSelection = "uncommentSelection",
149+
/* @internal */
150+
UncommentSelectionFull = "uncommentSelection-full",
144151
PrepareCallHierarchy = "prepareCallHierarchy",
145152
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
146153
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
@@ -1532,6 +1539,16 @@ namespace ts.server.protocol {
15321539
arguments: FileRangeRequestArgs;
15331540
}
15341541

1542+
export interface CommentSelectionRequest extends FileRequest {
1543+
command: CommandTypes.CommentSelection;
1544+
arguments: FileRangeRequestArgs;
1545+
}
1546+
1547+
export interface UncommentSelectionRequest extends FileRequest {
1548+
command: CommandTypes.UncommentSelection;
1549+
arguments: FileRangeRequestArgs;
1550+
}
1551+
15351552
/**
15361553
* Information found in an "open" request.
15371554
*/

src/server/session.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,6 +2191,38 @@ namespace ts.server {
21912191
return textChanges;
21922192
}
21932193

2194+
private commentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
2195+
const { file, project } = this.getFileAndProject(args);
2196+
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
2197+
const textRange = this.getRange(args, scriptInfo);
2198+
2199+
const textChanges = project.getLanguageService().commentSelection(file, textRange);
2200+
2201+
if (simplifiedResult) {
2202+
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
2203+
2204+
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
2205+
}
2206+
2207+
return textChanges;
2208+
}
2209+
2210+
private uncommentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
2211+
const { file, project } = this.getFileAndProject(args);
2212+
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
2213+
const textRange = this.getRange(args, scriptInfo);
2214+
2215+
const textChanges = project.getLanguageService().uncommentSelection(file, textRange);
2216+
2217+
if (simplifiedResult) {
2218+
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
2219+
2220+
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
2221+
}
2222+
2223+
return textChanges;
2224+
}
2225+
21942226
private mapSelectionRange(selectionRange: SelectionRange, scriptInfo: ScriptInfo): protocol.SelectionRange {
21952227
const result: protocol.SelectionRange = {
21962228
textSpan: toProtocolTextSpan(selectionRange.textSpan, scriptInfo),
@@ -2648,6 +2680,18 @@ namespace ts.server {
26482680
[CommandNames.ToggleMultilineCommentFull]: (request: protocol.ToggleMultilineCommentRequest) => {
26492681
return this.requiredResponse(this.toggleMultilineComment(request.arguments, /*simplifiedResult*/false));
26502682
},
2683+
[CommandNames.CommentSelection]: (request: protocol.CommentSelectionRequest) => {
2684+
return this.requiredResponse(this.commentSelection(request.arguments, /*simplifiedResult*/true));
2685+
},
2686+
[CommandNames.CommentSelectionFull]: (request: protocol.CommentSelectionRequest) => {
2687+
return this.requiredResponse(this.commentSelection(request.arguments, /*simplifiedResult*/false));
2688+
},
2689+
[CommandNames.UncommentSelection]: (request: protocol.UncommentSelectionRequest) => {
2690+
return this.requiredResponse(this.uncommentSelection(request.arguments, /*simplifiedResult*/true));
2691+
},
2692+
[CommandNames.UncommentSelectionFull]: (request: protocol.UncommentSelectionRequest) => {
2693+
return this.requiredResponse(this.uncommentSelection(request.arguments, /*simplifiedResult*/false));
2694+
},
26512695
});
26522696

26532697
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {

src/services/services.ts

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,12 +1955,12 @@ namespace ts {
19551955
}
19561956
}
19571957

1958-
function toggleLineComment(fileName: string, textRange: TextRange): TextChange[] {
1958+
function toggleLineComment(fileName: string, textRange: TextRange, insertComment?: boolean): TextChange[] {
19591959
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
19601960
const textChanges: TextChange[] = [];
19611961
const { lineStarts, firstLine, lastLine } = getLinesForRange(sourceFile, textRange);
19621962

1963-
let isCommenting = false;
1963+
let isCommenting = insertComment || false;
19641964
let leftMostPosition = Number.MAX_VALUE;
19651965
let lineTextStarts = new Map<number>();
19661966
const whiteSpaceRegex = new RegExp(/\S/);
@@ -1978,7 +1978,7 @@ namespace ts {
19781978
lineTextStarts.set(i.toString(), regExec.index);
19791979

19801980
if (lineText.substr(regExec.index, openComment.length) !== openComment) {
1981-
isCommenting = true;
1981+
isCommenting = insertComment !== undefined ? insertComment : true;
19821982
}
19831983
}
19841984
}
@@ -1999,7 +1999,7 @@ namespace ts {
19991999
start: lineStarts[i] + leftMostPosition
20002000
}
20012001
});
2002-
} else {
2002+
} else if (sourceFile.text.substr(lineStarts[i] + lineTextStart, openComment.length) === openComment) {
20032003
textChanges.push({
20042004
newText: "",
20052005
span: {
@@ -2019,7 +2019,7 @@ namespace ts {
20192019
const textChanges: TextChange[] = [];
20202020
const { text } = sourceFile;
20212021

2022-
let isCommenting = insertComment !== undefined ? insertComment : false;
2022+
let isCommenting = insertComment || false;
20232023
const positions = [] as number[] as SortedArray<number>;
20242024

20252025
let pos = textRange.pos;
@@ -2053,7 +2053,9 @@ namespace ts {
20532053
} else { // If it's not in a comment range, then we need to comment the uncommented portions.
20542054
let newPos = text.substring(pos, textRange.end).search(`(${openMultilineRegex})|(${closeMultilineRegex})`);
20552055

2056-
isCommenting = isCommenting || !isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos);
2056+
isCommenting = insertComment !== undefined
2057+
? insertComment
2058+
: isCommenting || !isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos); // If isCommenting is already true we don't need to check whitespace again.
20572059
pos = newPos === -1 ? textRange.end + 1 : pos + newPos + closeMultiline.length;
20582060
}
20592061
}
@@ -2127,6 +2129,31 @@ namespace ts {
21272129
return textChanges;
21282130
}
21292131

2132+
function commentSelection(fileName: string, textRange: TextRange): TextChange[] {
2133+
return toggleLineComment(fileName, textRange, true);
2134+
}
2135+
function uncommentSelection(fileName: string, textRange: TextRange): TextChange[] {
2136+
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
2137+
const textChanges: TextChange[] = [];
2138+
2139+
for (let i = textRange.pos; i <= textRange.end; i++) {
2140+
let commentRange = isInComment(sourceFile, i);
2141+
if (commentRange) {
2142+
switch (commentRange.kind) {
2143+
case SyntaxKind.SingleLineCommentTrivia:
2144+
textChanges.push.apply(textChanges, toggleLineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, false));
2145+
break;
2146+
case SyntaxKind.MultiLineCommentTrivia:
2147+
textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, false));
2148+
}
2149+
2150+
i = commentRange.end + 1;
2151+
}
2152+
}
2153+
2154+
return textChanges;
2155+
}
2156+
21302157
function isUnclosedTag({ openingElement, closingElement, parent }: JsxElement): boolean {
21312158
return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) ||
21322159
isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent);
@@ -2407,7 +2434,9 @@ namespace ts {
24072434
provideCallHierarchyIncomingCalls,
24082435
provideCallHierarchyOutgoingCalls,
24092436
toggleLineComment,
2410-
toggleMultilineComment
2437+
toggleMultilineComment,
2438+
commentSelection,
2439+
uncommentSelection,
24112440
};
24122441
}
24132442

src/services/shims.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ namespace ts {
280280

281281
toggleLineComment(fileName: string, textChange: ts.TextRange): string;
282282
toggleMultilineComment(fileName: string, textChange: ts.TextRange): string;
283+
commentSelection(fileName: string, textChange: ts.TextRange): string;
284+
uncommentSelection(fileName: string, textChange: ts.TextRange): string;
283285
}
284286

285287
export interface ClassifierShim extends Shim {
@@ -1080,6 +1082,20 @@ namespace ts {
10801082
() => this.languageService.toggleMultilineComment(fileName, textRange)
10811083
);
10821084
}
1085+
1086+
public commentSelection(fileName: string, textRange: ts.TextRange): string {
1087+
return this.forwardJSONCall(
1088+
`commentSelection('${fileName}', '${JSON.stringify(textRange)}')`,
1089+
() => this.languageService.commentSelection(fileName, textRange)
1090+
);
1091+
}
1092+
1093+
public uncommentSelection(fileName: string, textRange: ts.TextRange): string {
1094+
return this.forwardJSONCall(
1095+
`uncommentSelection('${fileName}', '${JSON.stringify(textRange)}')`,
1096+
() => this.languageService.uncommentSelection(fileName, textRange)
1097+
);
1098+
}
10831099
}
10841100

10851101
function convertClassifications(classifications: Classifications): { spans: string, endOfLineState: EndOfLineState } {

src/services/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ namespace ts {
411411

412412
toggleLineComment(fileName: string, textRanges: TextRange): TextChange[];
413413
toggleMultilineComment(fileName: string, textRanges: TextRange): TextChange[];
414+
commentSelection(fileName: string, textRanges: TextRange): TextChange[];
415+
uncommentSelection(fileName: string, textRanges: TextRange): TextChange[];
414416

415417
dispose(): void;
416418
}

src/testRunner/unittests/tsserver/session.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,9 @@ namespace ts.server {
273273
CommandNames.ProvideCallHierarchyIncomingCalls,
274274
CommandNames.ProvideCallHierarchyOutgoingCalls,
275275
CommandNames.ToggleLineComment,
276-
CommandNames.ToggleMultilineComment
276+
CommandNames.ToggleMultilineComment,
277+
CommandNames.CommentSelection,
278+
CommandNames.UncommentSelection,
277279
];
278280

279281
it("should not throw when commands are executed with invalid arguments", () => {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5210,8 +5210,10 @@ declare namespace ts {
52105210
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
52115211
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput;
52125212
getProgram(): Program | undefined;
5213-
toggleLineComment(fileName: string, textRanges: TextRange[]): TextChange[];
5214-
toggleMultilineComment(fileName: string, textRanges: TextRange[]): TextChange[];
5213+
toggleLineComment(fileName: string, textRanges: TextRange): TextChange[];
5214+
toggleMultilineComment(fileName: string, textRanges: TextRange): TextChange[];
5215+
commentSelection(fileName: string, textRanges: TextRange): TextChange[];
5216+
uncommentSelection(fileName: string, textRanges: TextRange): TextChange[];
52155217
dispose(): void;
52165218
}
52175219
interface JsxClosingTagInfo {
@@ -6196,9 +6198,9 @@ declare namespace ts.server.protocol {
61966198
ConfigurePlugin = "configurePlugin",
61976199
SelectionRange = "selectionRange",
61986200
ToggleLineComment = "toggleLineComment",
6199-
ToggleLineCommentFull = "toggleLineComment-full",
62006201
ToggleMultilineComment = "toggleMultilineComment",
6201-
ToggleMultilineCommentFull = "toggleMultilineComment-full",
6202+
CommentSelection = "commentSelection",
6203+
UncommentSelection = "uncommentSelection",
62026204
PrepareCallHierarchy = "prepareCallHierarchy",
62036205
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
62046206
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls"
@@ -6774,16 +6776,6 @@ declare namespace ts.server.protocol {
67746776
*/
67756777
end: Location;
67766778
}
6777-
interface TextRange {
6778-
/**
6779-
* Position of the first character.
6780-
*/
6781-
pos: number;
6782-
/**
6783-
* Position of the last character.
6784-
*/
6785-
end: number;
6786-
}
67876779
/**
67886780
* Object found in response messages defining a span of text in a specific source file.
67896781
*/
@@ -7235,17 +7227,19 @@ declare namespace ts.server.protocol {
72357227
}
72367228
interface ToggleLineCommentRequest extends FileRequest {
72377229
command: CommandTypes.ToggleLineComment;
7238-
arguments: ToggleLineCommentRequestArgs;
7239-
}
7240-
interface ToggleLineCommentRequestArgs extends FileRequestArgs {
7241-
textRanges: TextRange[];
7230+
arguments: FileRangeRequestArgs;
72427231
}
72437232
interface ToggleMultilineCommentRequest extends FileRequest {
72447233
command: CommandTypes.ToggleMultilineComment;
7245-
arguments: ToggleMultilineCommentRequestArgs;
7234+
arguments: FileRangeRequestArgs;
7235+
}
7236+
interface CommentSelectionRequest extends FileRequest {
7237+
command: CommandTypes.CommentSelection;
7238+
arguments: FileRangeRequestArgs;
72467239
}
7247-
interface ToggleMultilineCommentRequestArgs extends FileRequestArgs {
7248-
textRanges: TextRange[];
7240+
interface UncommentSelectionRequest extends FileRequest {
7241+
command: CommandTypes.UncommentSelection;
7242+
arguments: FileRangeRequestArgs;
72497243
}
72507244
/**
72517245
* Information found in an "open" request.
@@ -9596,6 +9590,7 @@ declare namespace ts.server {
95969590
private getSupportedCodeFixes;
95979591
private isLocation;
95989592
private extractPositionOrRange;
9593+
private getRange;
95999594
private getApplicableRefactors;
96009595
private getEditsForRefactor;
96019596
private organizeImports;
@@ -9615,6 +9610,8 @@ declare namespace ts.server {
96159610
private getSmartSelectionRange;
96169611
private toggleLineComment;
96179612
private toggleMultilineComment;
9613+
private commentSelection;
9614+
private uncommentSelection;
96189615
private mapSelectionRange;
96199616
private getScriptInfoFromProjectService;
96209617
private toProtocolCallHierarchyItem;

0 commit comments

Comments
 (0)