Merge pull request #37029 from armanio123/AddToggleCommentFeature
Add ToggleLineComment and ToggleMultilineComment service
This commit is contained in:
commit
6279f981b3
|
@ -825,6 +825,22 @@ namespace ts.server {
|
|||
return notImplemented();
|
||||
}
|
||||
|
||||
toggleLineComment(): TextChange[] {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
toggleMultilineComment(): TextChange[] {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
commentSelection(): TextChange[] {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
uncommentSelection(): TextChange[] {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
throw new Error("dispose is not available through the server layer.");
|
||||
}
|
||||
|
|
|
@ -3226,7 +3226,7 @@ namespace FourSlash {
|
|||
|
||||
this.raiseError(
|
||||
`Expected to find a fix with the name '${fixName}', but none exists.` +
|
||||
availableFixes.length
|
||||
availableFixes.length
|
||||
? ` Available fixes: ${availableFixes.map(fix => `${fix.fixName} (${fix.fixId ? "with" : "without"} fix-all)`).join(", ")}`
|
||||
: ""
|
||||
);
|
||||
|
@ -3465,13 +3465,13 @@ namespace FourSlash {
|
|||
|
||||
const incomingCalls =
|
||||
direction === CallHierarchyItemDirection.Outgoing ? { result: "skip" } as const :
|
||||
alreadySeen ? { result: "seen" } as const :
|
||||
{ result: "show", values: this.languageService.provideCallHierarchyIncomingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const;
|
||||
alreadySeen ? { result: "seen" } as const :
|
||||
{ result: "show", values: this.languageService.provideCallHierarchyIncomingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const;
|
||||
|
||||
const outgoingCalls =
|
||||
direction === CallHierarchyItemDirection.Incoming ? { result: "skip" } as const :
|
||||
alreadySeen ? { result: "seen" } as const :
|
||||
{ result: "show", values: this.languageService.provideCallHierarchyOutgoingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const;
|
||||
alreadySeen ? { result: "seen" } as const :
|
||||
{ result: "show", values: this.languageService.provideCallHierarchyOutgoingCalls(callHierarchyItem.file, callHierarchyItem.selectionSpan.start) } as const;
|
||||
|
||||
let text = "";
|
||||
text += `${prefix}╭ name: ${callHierarchyItem.name}\n`;
|
||||
|
@ -3485,7 +3485,7 @@ namespace FourSlash {
|
|||
text += `${prefix}├ selectionSpan:\n`;
|
||||
text += this.formatCallHierarchyItemSpan(file, callHierarchyItem.selectionSpan, `${prefix}│ `,
|
||||
incomingCalls.result !== "skip" || outgoingCalls.result !== "skip" ? `${prefix}│ ` :
|
||||
`${trailingPrefix}╰ `);
|
||||
`${trailingPrefix}╰ `);
|
||||
|
||||
if (incomingCalls.result === "seen") {
|
||||
if (outgoingCalls.result === "skip") {
|
||||
|
@ -3514,8 +3514,8 @@ namespace FourSlash {
|
|||
text += `${prefix}│ ├ fromSpans:\n`;
|
||||
text += this.formatCallHierarchyItemSpans(file, incomingCall.fromSpans, `${prefix}│ │ `,
|
||||
i < incomingCalls.values.length - 1 ? `${prefix}│ ╰ ` :
|
||||
outgoingCalls.result !== "skip" ? `${prefix}│ ╰ ` :
|
||||
`${trailingPrefix}╰ ╰ `);
|
||||
outgoingCalls.result !== "skip" ? `${prefix}│ ╰ ` :
|
||||
`${trailingPrefix}╰ ╰ `);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3536,7 +3536,7 @@ namespace FourSlash {
|
|||
text += `${prefix}│ ├ fromSpans:\n`;
|
||||
text += this.formatCallHierarchyItemSpans(file, outgoingCall.fromSpans, `${prefix}│ │ `,
|
||||
i < outgoingCalls.values.length - 1 ? `${prefix}│ ╰ ` :
|
||||
`${trailingPrefix}╰ ╰ `);
|
||||
`${trailingPrefix}╰ ╰ `);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3696,6 +3696,50 @@ namespace FourSlash {
|
|||
public configurePlugin(pluginName: string, configuration: any): void {
|
||||
(<ts.server.SessionClient>this.languageService).configurePlugin(pluginName, configuration);
|
||||
}
|
||||
|
||||
public toggleLineComment(newFileContent: string): void {
|
||||
const changes: ts.TextChange[] = [];
|
||||
for (const range of this.getRanges()) {
|
||||
changes.push.apply(changes, this.languageService.toggleLineComment(this.activeFile.fileName, range));
|
||||
}
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(newFileContent: string): void {
|
||||
const changes: ts.TextChange[] = [];
|
||||
for (const range of this.getRanges()) {
|
||||
changes.push.apply(changes, this.languageService.toggleMultilineComment(this.activeFile.fileName, range));
|
||||
}
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
|
||||
public commentSelection(newFileContent: string): void {
|
||||
const changes: ts.TextChange[] = [];
|
||||
for (const range of this.getRanges()) {
|
||||
changes.push.apply(changes, this.languageService.commentSelection(this.activeFile.fileName, range));
|
||||
}
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
|
||||
public uncommentSelection(newFileContent: string): void {
|
||||
const changes: ts.TextChange[] = [];
|
||||
for (const range of this.getRanges()) {
|
||||
changes.push.apply(changes, this.languageService.uncommentSelection(this.activeFile.fileName, range));
|
||||
}
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
}
|
||||
|
||||
function prefixMessage(message: string | undefined) {
|
||||
|
|
|
@ -214,6 +214,22 @@ namespace FourSlashInterface {
|
|||
public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) {
|
||||
this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName);
|
||||
}
|
||||
|
||||
public toggleLineComment(newFileContent: string) {
|
||||
this.state.toggleLineComment(newFileContent);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(newFileContent: string) {
|
||||
this.state.toggleMultilineComment(newFileContent);
|
||||
}
|
||||
|
||||
public commentSelection(newFileContent: string) {
|
||||
this.state.commentSelection(newFileContent);
|
||||
}
|
||||
|
||||
public uncommentSelection(newFileContent: string) {
|
||||
this.state.uncommentSelection(newFileContent);
|
||||
}
|
||||
}
|
||||
|
||||
export class Verify extends VerifyNegatable {
|
||||
|
|
|
@ -603,6 +603,18 @@ namespace Harness.LanguageService {
|
|||
clearSourceMapperCache(): never {
|
||||
return ts.notImplemented();
|
||||
}
|
||||
toggleLineComment(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.toggleLineComment(fileName, textRange));
|
||||
}
|
||||
toggleMultilineComment(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.toggleMultilineComment(fileName, textRange));
|
||||
}
|
||||
commentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.commentSelection(fileName, textRange));
|
||||
}
|
||||
uncommentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.uncommentSelection(fileName, textRange));
|
||||
}
|
||||
dispose(): void { this.shim.dispose({}); }
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,18 @@ namespace ts.server.protocol {
|
|||
SelectionRange = "selectionRange",
|
||||
/* @internal */
|
||||
SelectionRangeFull = "selectionRange-full",
|
||||
|
||||
ToggleLineComment = "toggleLineComment",
|
||||
/* @internal */
|
||||
ToggleLineCommentFull = "toggleLineComment-full",
|
||||
ToggleMultilineComment = "toggleMultilineComment",
|
||||
/* @internal */
|
||||
ToggleMultilineCommentFull = "toggleMultilineComment-full",
|
||||
CommentSelection = "commentSelection",
|
||||
/* @internal */
|
||||
CommentSelectionFull = "commentSelection-full",
|
||||
UncommentSelection = "uncommentSelection",
|
||||
/* @internal */
|
||||
UncommentSelectionFull = "uncommentSelection-full",
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
|
||||
|
@ -1542,6 +1553,26 @@ namespace ts.server.protocol {
|
|||
parent?: SelectionRange;
|
||||
}
|
||||
|
||||
export interface ToggleLineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleLineComment;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
|
||||
export interface ToggleMultilineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleMultilineComment;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
|
||||
export interface CommentSelectionRequest extends FileRequest {
|
||||
command: CommandTypes.CommentSelection;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
|
||||
export interface UncommentSelectionRequest extends FileRequest {
|
||||
command: CommandTypes.UncommentSelection;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information found in an "open" request.
|
||||
*/
|
||||
|
|
|
@ -2012,8 +2012,7 @@ namespace ts.server {
|
|||
position = getPosition(args);
|
||||
}
|
||||
else {
|
||||
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
|
||||
textRange = { pos: startPosition, end: endPosition };
|
||||
textRange = this.getRange(args, scriptInfo);
|
||||
}
|
||||
return Debug.checkDefined(position === undefined ? textRange : position);
|
||||
|
||||
|
@ -2022,6 +2021,12 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
private getRange(args: protocol.FileRangeRequestArgs, scriptInfo: ScriptInfo): TextRange {
|
||||
const { startPosition, endPosition } = this.getStartAndEndPosition(args, scriptInfo);
|
||||
|
||||
return { pos: startPosition, end: endPosition };
|
||||
}
|
||||
|
||||
private getApplicableRefactors(args: protocol.GetApplicableRefactorsRequestArgs): protocol.ApplicableRefactorInfo[] {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file)!;
|
||||
|
@ -2251,6 +2256,70 @@ namespace ts.server {
|
|||
});
|
||||
}
|
||||
|
||||
private toggleLineComment(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfo(file)!;
|
||||
const textRange = this.getRange(args, scriptInfo);
|
||||
|
||||
const textChanges = languageService.toggleLineComment(file, textRange);
|
||||
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
|
||||
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
private toggleMultilineComment(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const textRange = this.getRange(args, scriptInfo);
|
||||
|
||||
const textChanges = languageService.toggleMultilineComment(file, textRange);
|
||||
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
|
||||
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
private commentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const textRange = this.getRange(args, scriptInfo);
|
||||
|
||||
const textChanges = languageService.commentSelection(file, textRange);
|
||||
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
|
||||
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
private uncommentSelection(args: protocol.FileRangeRequestArgs, simplifiedResult: boolean): TextChange[] | protocol.CodeEdit[] {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const textRange = this.getRange(args, scriptInfo);
|
||||
|
||||
const textChanges = languageService.uncommentSelection(file, textRange);
|
||||
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
|
||||
return textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo));
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
private mapSelectionRange(selectionRange: SelectionRange, scriptInfo: ScriptInfo): protocol.SelectionRange {
|
||||
const result: protocol.SelectionRange = {
|
||||
textSpan: toProtocolTextSpan(selectionRange.textSpan, scriptInfo),
|
||||
|
@ -2697,6 +2766,30 @@ namespace ts.server {
|
|||
[CommandNames.ProvideCallHierarchyOutgoingCalls]: (request: protocol.ProvideCallHierarchyOutgoingCallsRequest) => {
|
||||
return this.requiredResponse(this.provideCallHierarchyOutgoingCalls(request.arguments));
|
||||
},
|
||||
[CommandNames.ToggleLineComment]: (request: protocol.ToggleLineCommentRequest) => {
|
||||
return this.requiredResponse(this.toggleLineComment(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.ToggleLineCommentFull]: (request: protocol.ToggleLineCommentRequest) => {
|
||||
return this.requiredResponse(this.toggleLineComment(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.ToggleMultilineComment]: (request: protocol.ToggleMultilineCommentRequest) => {
|
||||
return this.requiredResponse(this.toggleMultilineComment(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.ToggleMultilineCommentFull]: (request: protocol.ToggleMultilineCommentRequest) => {
|
||||
return this.requiredResponse(this.toggleMultilineComment(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.CommentSelection]: (request: protocol.CommentSelectionRequest) => {
|
||||
return this.requiredResponse(this.commentSelection(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.CommentSelectionFull]: (request: protocol.CommentSelectionRequest) => {
|
||||
return this.requiredResponse(this.commentSelection(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.UncommentSelection]: (request: protocol.UncommentSelectionRequest) => {
|
||||
return this.requiredResponse(this.uncommentSelection(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.UncommentSelectionFull]: (request: protocol.UncommentSelectionRequest) => {
|
||||
return this.requiredResponse(this.uncommentSelection(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
}));
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace ts {
|
|||
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject<TKind> | IdentifierObject | PrivateIdentifierObject {
|
||||
const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) :
|
||||
kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) :
|
||||
kind === SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(SyntaxKind.PrivateIdentifier, pos, end) :
|
||||
new TokenObject(kind, pos, end);
|
||||
kind === SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(SyntaxKind.PrivateIdentifier, pos, end) :
|
||||
new TokenObject(kind, pos, end);
|
||||
node.parent = parent;
|
||||
node.flags = parent.flags & NodeFlags.ContextFlags;
|
||||
return node;
|
||||
|
@ -773,7 +773,7 @@ namespace ts {
|
|||
if (!hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) {
|
||||
break;
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.BindingElement: {
|
||||
|
@ -834,7 +834,7 @@ namespace ts {
|
|||
if (getAssignmentDeclarationKind(node as BinaryExpression) !== AssignmentDeclarationKind.None) {
|
||||
addDeclaration(node as BinaryExpression);
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
default:
|
||||
forEachChild(node, visit);
|
||||
|
@ -1994,6 +1994,236 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getLinesForRange(sourceFile: SourceFile, textRange: TextRange) {
|
||||
return {
|
||||
lineStarts: sourceFile.getLineStarts(),
|
||||
firstLine: sourceFile.getLineAndCharacterOfPosition(textRange.pos).line,
|
||||
lastLine: sourceFile.getLineAndCharacterOfPosition(textRange.end).line
|
||||
};
|
||||
}
|
||||
|
||||
function toggleLineComment(fileName: string, textRange: TextRange, insertComment?: boolean): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const textChanges: TextChange[] = [];
|
||||
const { lineStarts, firstLine, lastLine } = getLinesForRange(sourceFile, textRange);
|
||||
|
||||
let isCommenting = insertComment || false;
|
||||
let leftMostPosition = Number.MAX_VALUE;
|
||||
const lineTextStarts = new Map<string, number>();
|
||||
const firstNonWhitespaceCharacterRegex = new RegExp(/\S/);
|
||||
const isJsx = isInsideJsxElement(sourceFile, lineStarts[firstLine]);
|
||||
const openComment = isJsx ? "{/*" : "//";
|
||||
|
||||
// Check each line before any text changes.
|
||||
for (let i = firstLine; i <= lastLine; i++) {
|
||||
const lineText = sourceFile.text.substring(lineStarts[i], sourceFile.getLineEndOfPosition(lineStarts[i]));
|
||||
|
||||
// Find the start of text and the left-most character. No-op on empty lines.
|
||||
const regExec = firstNonWhitespaceCharacterRegex.exec(lineText);
|
||||
if (regExec) {
|
||||
leftMostPosition = Math.min(leftMostPosition, regExec.index);
|
||||
lineTextStarts.set(i.toString(), regExec.index);
|
||||
|
||||
if (lineText.substr(regExec.index, openComment.length) !== openComment) {
|
||||
isCommenting = insertComment === undefined || insertComment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Push all text changes.
|
||||
for (let i = firstLine; i <= lastLine; i++) {
|
||||
const lineTextStart = lineTextStarts.get(i.toString());
|
||||
|
||||
// If the line is not an empty line; otherwise no-op.
|
||||
if (lineTextStart !== undefined) {
|
||||
if (isJsx) {
|
||||
textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { pos: lineStarts[i] + leftMostPosition, end: sourceFile.getLineEndOfPosition(lineStarts[i]) }, isCommenting, isJsx));
|
||||
}
|
||||
else if (isCommenting) {
|
||||
textChanges.push({
|
||||
newText: openComment,
|
||||
span: {
|
||||
length: 0,
|
||||
start: lineStarts[i] + leftMostPosition
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (sourceFile.text.substr(lineStarts[i] + lineTextStart, openComment.length) === openComment) {
|
||||
textChanges.push({
|
||||
newText: "",
|
||||
span: {
|
||||
length: openComment.length,
|
||||
start: lineStarts[i] + lineTextStart
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
function toggleMultilineComment(fileName: string, textRange: TextRange, insertComment?: boolean, isInsideJsx?: boolean): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const textChanges: TextChange[] = [];
|
||||
const { text } = sourceFile;
|
||||
|
||||
let hasComment = false;
|
||||
let isCommenting = insertComment || false;
|
||||
const positions = [] as number[] as SortedArray<number>;
|
||||
|
||||
let { pos } = textRange;
|
||||
const isJsx = isInsideJsx !== undefined ? isInsideJsx : isInsideJsxElement(sourceFile, pos);
|
||||
|
||||
const openMultiline = isJsx ? "{/*" : "/*";
|
||||
const closeMultiline = isJsx ? "*/}" : "*/";
|
||||
const openMultilineRegex = isJsx ? "\\{\\/\\*" : "\\/\\*";
|
||||
const closeMultilineRegex = isJsx ? "\\*\\/\\}" : "\\*\\/";
|
||||
|
||||
// Get all comment positions
|
||||
while (pos <= textRange.end) {
|
||||
// Start of comment is considered inside comment.
|
||||
const offset = text.substr(pos, openMultiline.length) === openMultiline ? openMultiline.length : 0;
|
||||
const commentRange = isInComment(sourceFile, pos + offset);
|
||||
|
||||
// If position is in a comment add it to the positions array.
|
||||
if (commentRange) {
|
||||
// Comment range doesn't include the brace character. Increase it to include them.
|
||||
if (isJsx) {
|
||||
commentRange.pos--;
|
||||
commentRange.end++;
|
||||
}
|
||||
|
||||
positions.push(commentRange.pos);
|
||||
if (commentRange.kind === SyntaxKind.MultiLineCommentTrivia) {
|
||||
positions.push(commentRange.end);
|
||||
}
|
||||
|
||||
hasComment = true;
|
||||
pos = commentRange.end + 1;
|
||||
}
|
||||
else { // If it's not in a comment range, then we need to comment the uncommented portions.
|
||||
const newPos = text.substring(pos, textRange.end).search(`(${openMultilineRegex})|(${closeMultilineRegex})`);
|
||||
|
||||
isCommenting = insertComment !== undefined
|
||||
? insertComment
|
||||
: isCommenting || !isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos); // If isCommenting is already true we don't need to check whitespace again.
|
||||
pos = newPos === -1 ? textRange.end + 1 : pos + newPos + closeMultiline.length;
|
||||
}
|
||||
}
|
||||
|
||||
// If it didn't found a comment and isCommenting is false means is only empty space.
|
||||
// We want to insert comment in this scenario.
|
||||
if (isCommenting || !hasComment) {
|
||||
if (isInComment(sourceFile, textRange.pos)?.kind !== SyntaxKind.SingleLineCommentTrivia) {
|
||||
insertSorted(positions, textRange.pos, compareValues);
|
||||
}
|
||||
insertSorted(positions, textRange.end, compareValues);
|
||||
|
||||
// Insert open comment if the first position is not a comment already.
|
||||
const firstPos = positions[0];
|
||||
if (text.substr(firstPos, openMultiline.length) !== openMultiline) {
|
||||
textChanges.push({
|
||||
newText: openMultiline,
|
||||
span: {
|
||||
length: 0,
|
||||
start: firstPos
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Insert open and close comment to all positions between first and last. Exclusive.
|
||||
for (let i = 1; i < positions.length - 1; i++) {
|
||||
if (text.substr(positions[i] - closeMultiline.length, closeMultiline.length) !== closeMultiline) {
|
||||
textChanges.push({
|
||||
newText: closeMultiline,
|
||||
span: {
|
||||
length: 0,
|
||||
start: positions[i]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (text.substr(positions[i], openMultiline.length) !== openMultiline) {
|
||||
textChanges.push({
|
||||
newText: openMultiline,
|
||||
span: {
|
||||
length: 0,
|
||||
start: positions[i]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Insert open comment if the last position is not a comment already.
|
||||
if (textChanges.length % 2 !== 0) {
|
||||
textChanges.push({
|
||||
newText: closeMultiline,
|
||||
span: {
|
||||
length: 0,
|
||||
start: positions[positions.length - 1]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If is not commenting then remove all comments found.
|
||||
for (const pos of positions) {
|
||||
const from = pos - closeMultiline.length > 0 ? pos - closeMultiline.length : 0;
|
||||
const offset = text.substr(from, closeMultiline.length) === closeMultiline ? closeMultiline.length : 0;
|
||||
textChanges.push({
|
||||
newText: "",
|
||||
span: {
|
||||
length: openMultiline.length,
|
||||
start: pos - offset
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
function commentSelection(fileName: string, textRange: TextRange): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const { firstLine, lastLine } = getLinesForRange(sourceFile, textRange);
|
||||
|
||||
// If there is a selection that is on the same line, add multiline.
|
||||
return firstLine === lastLine && textRange.pos !== textRange.end
|
||||
? toggleMultilineComment(fileName, textRange, /*insertComment*/ true)
|
||||
: toggleLineComment(fileName, textRange, /*insertComment*/ true);
|
||||
}
|
||||
|
||||
function uncommentSelection(fileName: string, textRange: TextRange): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const textChanges: TextChange[] = [];
|
||||
const { pos } = textRange;
|
||||
let { end } = textRange;
|
||||
|
||||
// If cursor is not a selection we need to increase the end position
|
||||
// to include the start of the comment.
|
||||
if (pos === end) {
|
||||
end += isInsideJsxElement(sourceFile, pos) ? 2 : 1;
|
||||
}
|
||||
|
||||
for (let i = pos; i <= end; i++) {
|
||||
const commentRange = isInComment(sourceFile, i);
|
||||
if (commentRange) {
|
||||
switch (commentRange.kind) {
|
||||
case SyntaxKind.SingleLineCommentTrivia:
|
||||
textChanges.push.apply(textChanges, toggleLineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false));
|
||||
break;
|
||||
case SyntaxKind.MultiLineCommentTrivia:
|
||||
textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false));
|
||||
}
|
||||
|
||||
i = commentRange.end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
function isUnclosedTag({ openingElement, closingElement, parent }: JsxElement): boolean {
|
||||
return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) ||
|
||||
isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent);
|
||||
|
@ -2274,7 +2504,11 @@ namespace ts {
|
|||
clearSourceMapperCache: () => sourceMapper.clearCache(),
|
||||
prepareCallHierarchy,
|
||||
provideCallHierarchyIncomingCalls,
|
||||
provideCallHierarchyOutgoingCalls
|
||||
provideCallHierarchyOutgoingCalls,
|
||||
toggleLineComment,
|
||||
toggleMultilineComment,
|
||||
commentSelection,
|
||||
uncommentSelection,
|
||||
};
|
||||
|
||||
if (syntaxOnly) {
|
||||
|
@ -2348,7 +2582,7 @@ namespace ts {
|
|||
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
|
||||
return isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
return isObjectLiteralElement(node.parent) &&
|
||||
|
|
|
@ -277,6 +277,11 @@ namespace ts {
|
|||
|
||||
getEmitOutput(fileName: string): string;
|
||||
getEmitOutputObject(fileName: string): EmitOutput;
|
||||
|
||||
toggleLineComment(fileName: string, textChange: TextRange): string;
|
||||
toggleMultilineComment(fileName: string, textChange: TextRange): string;
|
||||
commentSelection(fileName: string, textChange: TextRange): string;
|
||||
uncommentSelection(fileName: string, textChange: TextRange): string;
|
||||
}
|
||||
|
||||
export interface ClassifierShim extends Shim {
|
||||
|
@ -1068,6 +1073,34 @@ namespace ts {
|
|||
() => this.languageService.getEmitOutput(fileName),
|
||||
this.logPerformance) as EmitOutput;
|
||||
}
|
||||
|
||||
public toggleLineComment(fileName: string, textRange: TextRange): string {
|
||||
return this.forwardJSONCall(
|
||||
`toggleLineComment('${fileName}', '${JSON.stringify(textRange)}')`,
|
||||
() => this.languageService.toggleLineComment(fileName, textRange)
|
||||
);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(fileName: string, textRange: TextRange): string {
|
||||
return this.forwardJSONCall(
|
||||
`toggleMultilineComment('${fileName}', '${JSON.stringify(textRange)}')`,
|
||||
() => this.languageService.toggleMultilineComment(fileName, textRange)
|
||||
);
|
||||
}
|
||||
|
||||
public commentSelection(fileName: string, textRange: TextRange): string {
|
||||
return this.forwardJSONCall(
|
||||
`commentSelection('${fileName}', '${JSON.stringify(textRange)}')`,
|
||||
() => this.languageService.commentSelection(fileName, textRange)
|
||||
);
|
||||
}
|
||||
|
||||
public uncommentSelection(fileName: string, textRange: TextRange): string {
|
||||
return this.forwardJSONCall(
|
||||
`uncommentSelection('${fileName}', '${JSON.stringify(textRange)}')`,
|
||||
() => this.languageService.uncommentSelection(fileName, textRange)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function convertClassifications(classifications: Classifications): { spans: string, endOfLineState: EndOfLineState } {
|
||||
|
|
|
@ -506,6 +506,11 @@ namespace ts {
|
|||
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
|
||||
/* @internal */ getAutoImportProvider(): Program | undefined;
|
||||
|
||||
toggleLineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
toggleMultilineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
commentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
uncommentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,7 +394,7 @@ namespace ts {
|
|||
case SyntaxKind.MethodSignature:
|
||||
return ScriptElementKind.memberFunctionElement;
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
const {initializer} = node as PropertyAssignment;
|
||||
const { initializer } = node as PropertyAssignment;
|
||||
return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
|
@ -557,7 +557,7 @@ namespace ts {
|
|||
if (!(<NewExpression>n).arguments) {
|
||||
return true;
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
|
@ -877,14 +877,14 @@ namespace ts {
|
|||
// specially by `getSymbolAtLocation`.
|
||||
if (isModifier(node) && (forRename || node.kind !== SyntaxKind.DefaultKeyword) ? contains(parent.modifiers, node) :
|
||||
node.kind === SyntaxKind.ClassKeyword ? isClassDeclaration(parent) || isClassExpression(node) :
|
||||
node.kind === SyntaxKind.FunctionKeyword ? isFunctionDeclaration(parent) || isFunctionExpression(node) :
|
||||
node.kind === SyntaxKind.InterfaceKeyword ? isInterfaceDeclaration(parent) :
|
||||
node.kind === SyntaxKind.EnumKeyword ? isEnumDeclaration(parent) :
|
||||
node.kind === SyntaxKind.TypeKeyword ? isTypeAliasDeclaration(parent) :
|
||||
node.kind === SyntaxKind.NamespaceKeyword || node.kind === SyntaxKind.ModuleKeyword ? isModuleDeclaration(parent) :
|
||||
node.kind === SyntaxKind.ImportKeyword ? isImportEqualsDeclaration(parent) :
|
||||
node.kind === SyntaxKind.GetKeyword ? isGetAccessorDeclaration(parent) :
|
||||
node.kind === SyntaxKind.SetKeyword && isSetAccessorDeclaration(parent)) {
|
||||
node.kind === SyntaxKind.FunctionKeyword ? isFunctionDeclaration(parent) || isFunctionExpression(node) :
|
||||
node.kind === SyntaxKind.InterfaceKeyword ? isInterfaceDeclaration(parent) :
|
||||
node.kind === SyntaxKind.EnumKeyword ? isEnumDeclaration(parent) :
|
||||
node.kind === SyntaxKind.TypeKeyword ? isTypeAliasDeclaration(parent) :
|
||||
node.kind === SyntaxKind.NamespaceKeyword || node.kind === SyntaxKind.ModuleKeyword ? isModuleDeclaration(parent) :
|
||||
node.kind === SyntaxKind.ImportKeyword ? isImportEqualsDeclaration(parent) :
|
||||
node.kind === SyntaxKind.GetKeyword ? isGetAccessorDeclaration(parent) :
|
||||
node.kind === SyntaxKind.SetKeyword && isSetAccessorDeclaration(parent)) {
|
||||
const location = getAdjustedLocationForDeclaration(parent, forRename);
|
||||
if (location) {
|
||||
return location;
|
||||
|
@ -1320,6 +1320,35 @@ namespace ts {
|
|||
return false;
|
||||
}
|
||||
|
||||
export function isInsideJsxElement(sourceFile: SourceFile, position: number): boolean {
|
||||
function isInsideJsxElementTraversal(node: Node): boolean {
|
||||
while (node) {
|
||||
if (node.kind >= SyntaxKind.JsxSelfClosingElement && node.kind <= SyntaxKind.JsxExpression
|
||||
|| node.kind === SyntaxKind.JsxText
|
||||
|| node.kind === SyntaxKind.LessThanToken
|
||||
|| node.kind === SyntaxKind.GreaterThanToken
|
||||
|| node.kind === SyntaxKind.Identifier
|
||||
|| node.kind === SyntaxKind.CloseBraceToken
|
||||
|| node.kind === SyntaxKind.OpenBraceToken
|
||||
|| node.kind === SyntaxKind.SlashToken) {
|
||||
node = node.parent;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.JsxElement) {
|
||||
if (position > node.getStart(sourceFile)) return true;
|
||||
|
||||
node = node.parent;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isInsideJsxElementTraversal(getTokenAtPosition(sourceFile, position));
|
||||
}
|
||||
|
||||
export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind, sourceFile: SourceFile) {
|
||||
const tokenKind = token.kind;
|
||||
let remainingMatchingTokens = 0;
|
||||
|
@ -1346,7 +1375,7 @@ namespace ts {
|
|||
export function removeOptionality(type: Type, isOptionalExpression: boolean, isOptionalChain: boolean) {
|
||||
return isOptionalExpression ? type.getNonNullableType() :
|
||||
isOptionalChain ? type.getNonOptionalType() :
|
||||
type;
|
||||
type;
|
||||
}
|
||||
|
||||
export function isPossiblyTypeArgumentPosition(token: Node, sourceFile: SourceFile, checker: TypeChecker): boolean {
|
||||
|
@ -1439,7 +1468,7 @@ namespace ts {
|
|||
break;
|
||||
|
||||
case SyntaxKind.EqualsGreaterThanToken:
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.StringLiteral:
|
||||
|
@ -1447,7 +1476,7 @@ namespace ts {
|
|||
case SyntaxKind.BigIntLiteral:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.ExtendsKeyword:
|
||||
|
@ -1934,6 +1963,16 @@ namespace ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
export function isTextWhiteSpaceLike(text: string, startPos: number, endPos: number): boolean {
|
||||
for (let i = startPos; i < endPos; i++) {
|
||||
if (!isWhiteSpaceLike(text.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// Display-part writer helpers
|
||||
|
@ -2242,8 +2281,8 @@ namespace ts {
|
|||
// This only happens for leaf nodes - internal nodes always see their children change.
|
||||
const clone =
|
||||
isStringLiteral(node) ? setOriginalNode(factory.createStringLiteralFromNode(node), node) as Node as T :
|
||||
isNumericLiteral(node) ? setOriginalNode(factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as Node as T :
|
||||
factory.cloneNode(node);
|
||||
isNumericLiteral(node) ? setOriginalNode(factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as Node as T :
|
||||
factory.cloneNode(node);
|
||||
return setTextRange(clone, node);
|
||||
}
|
||||
|
||||
|
|
|
@ -272,6 +272,10 @@ namespace ts.server {
|
|||
CommandNames.PrepareCallHierarchy,
|
||||
CommandNames.ProvideCallHierarchyIncomingCalls,
|
||||
CommandNames.ProvideCallHierarchyOutgoingCalls,
|
||||
CommandNames.ToggleLineComment,
|
||||
CommandNames.ToggleMultilineComment,
|
||||
CommandNames.CommentSelection,
|
||||
CommandNames.UncommentSelection,
|
||||
];
|
||||
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
|
|
|
@ -5487,6 +5487,10 @@ declare namespace ts {
|
|||
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput;
|
||||
getProgram(): Program | undefined;
|
||||
toggleLineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
toggleMultilineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
commentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
uncommentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
dispose(): void;
|
||||
}
|
||||
interface JsxClosingTagInfo {
|
||||
|
@ -6482,6 +6486,10 @@ declare namespace ts.server.protocol {
|
|||
GetEditsForFileRename = "getEditsForFileRename",
|
||||
ConfigurePlugin = "configurePlugin",
|
||||
SelectionRange = "selectionRange",
|
||||
ToggleLineComment = "toggleLineComment",
|
||||
ToggleMultilineComment = "toggleMultilineComment",
|
||||
CommentSelection = "commentSelection",
|
||||
UncommentSelection = "uncommentSelection",
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls"
|
||||
|
@ -7514,6 +7522,22 @@ declare namespace ts.server.protocol {
|
|||
textSpan: TextSpan;
|
||||
parent?: SelectionRange;
|
||||
}
|
||||
interface ToggleLineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleLineComment;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
interface ToggleMultilineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleMultilineComment;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
interface CommentSelectionRequest extends FileRequest {
|
||||
command: CommandTypes.CommentSelection;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
interface UncommentSelectionRequest extends FileRequest {
|
||||
command: CommandTypes.UncommentSelection;
|
||||
arguments: FileRangeRequestArgs;
|
||||
}
|
||||
/**
|
||||
* Information found in an "open" request.
|
||||
*/
|
||||
|
@ -9870,6 +9894,7 @@ declare namespace ts.server {
|
|||
private getSupportedCodeFixes;
|
||||
private isLocation;
|
||||
private extractPositionOrRange;
|
||||
private getRange;
|
||||
private getApplicableRefactors;
|
||||
private getEditsForRefactor;
|
||||
private organizeImports;
|
||||
|
@ -9887,6 +9912,10 @@ declare namespace ts.server {
|
|||
private getDiagnosticsForProject;
|
||||
private configurePlugin;
|
||||
private getSmartSelectionRange;
|
||||
private toggleLineComment;
|
||||
private toggleMultilineComment;
|
||||
private commentSelection;
|
||||
private uncommentSelection;
|
||||
private mapSelectionRange;
|
||||
private getScriptInfoFromProjectService;
|
||||
private toProtocolCallHierarchyItem;
|
||||
|
|
|
@ -5487,6 +5487,10 @@ declare namespace ts {
|
|||
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[];
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput;
|
||||
getProgram(): Program | undefined;
|
||||
toggleLineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
toggleMultilineComment(fileName: string, textRange: TextRange): TextChange[];
|
||||
commentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
uncommentSelection(fileName: string, textRange: TextRange): TextChange[];
|
||||
dispose(): void;
|
||||
}
|
||||
interface JsxClosingTagInfo {
|
||||
|
|
26
tests/cases/fourslash/commentSelection1.ts
Normal file
26
tests/cases/fourslash/commentSelection1.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Simple comment selection cases.
|
||||
|
||||
//// let var1[| = 1;
|
||||
//// let var2 = 2;
|
||||
//// let var3 |]= 3;
|
||||
////
|
||||
//// let var4[| = 4;|]
|
||||
////
|
||||
//// let [||]var5 = 5;
|
||||
////
|
||||
//// //let var6[| = 6;
|
||||
//// //let var7 = 7;
|
||||
//// //let var8 |]= 8;
|
||||
|
||||
verify.commentSelection(
|
||||
`//let var1 = 1;
|
||||
//let var2 = 2;
|
||||
//let var3 = 3;
|
||||
|
||||
let var4/* = 4;*/
|
||||
|
||||
//let var5 = 5;
|
||||
|
||||
////let var6 = 6;
|
||||
////let var7 = 7;
|
||||
////let var8 = 8;`);
|
29
tests/cases/fourslash/commentSelection2.ts
Normal file
29
tests/cases/fourslash/commentSelection2.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Common jsx insert comment.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <MyContainer>
|
||||
//// [|<MyFirstComponent />
|
||||
//// <MySecondComponent />|]
|
||||
//// </MyContainer>;
|
||||
//// const b = <MyContainer>
|
||||
//// {/*<MyF[|irstComponent />*/}
|
||||
//// {/*<MySec|]ondComponent />*/}
|
||||
//// </MyContainer>;
|
||||
//// const c = <MyContainer>[|
|
||||
//// <MyFirstComponent />
|
||||
//// <MySecondCompo|]nent />
|
||||
//// </MyContainer>;
|
||||
|
||||
verify.commentSelection(
|
||||
`const a = <MyContainer>
|
||||
{/*<MyFirstComponent />*/}
|
||||
{/*<MySecondComponent />*/}
|
||||
</MyContainer>;
|
||||
const b = <MyContainer>
|
||||
{/*<MyFirstComponent />*/}
|
||||
{/*<MySecondComponent />*/}
|
||||
</MyContainer>;
|
||||
//const c = <MyContainer>
|
||||
// <MyFirstComponent />
|
||||
// <MySecondComponent />
|
||||
</MyContainer>;`);
|
|
@ -398,6 +398,11 @@ declare namespace FourSlashInterface {
|
|||
generateTypes(...options: GenerateTypesOptions[]): void;
|
||||
|
||||
organizeImports(newContent: string): void;
|
||||
|
||||
toggleLineComment(newFileContent: string): void;
|
||||
toggleMultilineComment(newFileContent: string): void;
|
||||
commentSelection(newFileContent: string): void;
|
||||
uncommentSelection(newFileContent: string): void;
|
||||
}
|
||||
class edit {
|
||||
backspace(count?: number): void;
|
||||
|
|
18
tests/cases/fourslash/toggleLineComment1.ts
Normal file
18
tests/cases/fourslash/toggleLineComment1.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Simple comment and uncomment.
|
||||
|
||||
//// let var1[| = 1;
|
||||
//// let var2 = 2;
|
||||
//// let var3 |]= 3;
|
||||
////
|
||||
//// //let var4[| = 1;
|
||||
//// //let var5 = 2;
|
||||
//// //let var6 |]= 3;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`//let var1 = 1;
|
||||
//let var2 = 2;
|
||||
//let var3 = 3;
|
||||
|
||||
let var4 = 1;
|
||||
let var5 = 2;
|
||||
let var6 = 3;`);
|
11
tests/cases/fourslash/toggleLineComment10.ts
Normal file
11
tests/cases/fourslash/toggleLineComment10.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Close and open multiline comments if the line already contains more comments.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <div>
|
||||
//// Som[||]e{/* T */}ext
|
||||
//// </div>;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`const a = <div>
|
||||
{/*Some*/}{/* T */}{/*ext*/}
|
||||
</div>;`);
|
20
tests/cases/fourslash/toggleLineComment2.ts
Normal file
20
tests/cases/fourslash/toggleLineComment2.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
// When indentation is different between lines it should get the left most indentation
|
||||
// and use that for all lines.
|
||||
// When uncommeting, doesn't matter what indentation the line has.
|
||||
|
||||
//// let var1[| = 1;
|
||||
//// let var2 = 2;
|
||||
//// let var3 |]= 3;
|
||||
////
|
||||
//// // let var4[| = 1;
|
||||
//// //let var5 = 2;
|
||||
//// // let var6 |]= 3;
|
||||
|
||||
verify.toggleLineComment(
|
||||
` // let var1 = 1;
|
||||
//let var2 = 2;
|
||||
// let var3 = 3;
|
||||
|
||||
let var4 = 1;
|
||||
let var5 = 2;
|
||||
let var6 = 3;`);
|
26
tests/cases/fourslash/toggleLineComment3.ts
Normal file
26
tests/cases/fourslash/toggleLineComment3.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Comment and uncomment ignores empty lines.
|
||||
|
||||
//// let var1[| = 1;
|
||||
////
|
||||
//// let var2 = 2;
|
||||
////
|
||||
//// let var3 |]= 3;
|
||||
////
|
||||
//// //let var4[| = 1;
|
||||
////
|
||||
//// //let var5 = 2;
|
||||
////
|
||||
//// //let var6 |]= 3;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`//let var1 = 1;
|
||||
|
||||
//let var2 = 2;
|
||||
|
||||
//let var3 = 3;
|
||||
|
||||
let var4 = 1;
|
||||
|
||||
let var5 = 2;
|
||||
|
||||
let var6 = 3;`);
|
18
tests/cases/fourslash/toggleLineComment4.ts
Normal file
18
tests/cases/fourslash/toggleLineComment4.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// If at least one line is not commented then comment all lines again.
|
||||
|
||||
//// //const a[| = 1;
|
||||
//// const b = 2
|
||||
//// //const c =|] 3;
|
||||
////
|
||||
//// ////const d[| = 4;
|
||||
//// //const e = 5;
|
||||
//// ////const e =|] 6;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`// //const a = 1;
|
||||
//const b = 2
|
||||
// //const c = 3;
|
||||
|
||||
//const d = 4;
|
||||
const e = 5;
|
||||
//const e = 6;`);
|
22
tests/cases/fourslash/toggleLineComment5.ts
Normal file
22
tests/cases/fourslash/toggleLineComment5.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Comments inside strings are still considered comments.
|
||||
|
||||
//// let var1 = `
|
||||
//// //some stri[|ng
|
||||
//// //some other|] string
|
||||
//// `;
|
||||
////
|
||||
//// let var2 = `
|
||||
//// some stri[|ng
|
||||
//// some other|] string
|
||||
//// `;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`let var1 = \`
|
||||
some string
|
||||
some other string
|
||||
\`;
|
||||
|
||||
let var2 = \`
|
||||
//some string
|
||||
//some other string
|
||||
\`;`);
|
15
tests/cases/fourslash/toggleLineComment6.ts
Normal file
15
tests/cases/fourslash/toggleLineComment6.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Selection is at the start of jsx its still js.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// let a = (
|
||||
//// [|<div>
|
||||
//// some text|]
|
||||
//// </div>
|
||||
//// );
|
||||
|
||||
verify.toggleLineComment(
|
||||
`let a = (
|
||||
//<div>
|
||||
// some text
|
||||
</div>
|
||||
);`);
|
29
tests/cases/fourslash/toggleLineComment7.ts
Normal file
29
tests/cases/fourslash/toggleLineComment7.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Common comment line cases.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <MyContainer>
|
||||
//// [|<MyFirstComponent />
|
||||
//// <MySecondComponent />|]
|
||||
//// </MyContainer>;
|
||||
//// const b = <MyContainer>
|
||||
//// {/*<MyF[|irstComponent />*/}
|
||||
//// {/*<MySec|]ondComponent />*/}
|
||||
//// </MyContainer>;
|
||||
//// const c = <MyContainer>[|
|
||||
//// <MyFirstComponent />
|
||||
//// <MySecondCompo|]nent />
|
||||
//// </MyContainer>;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`const a = <MyContainer>
|
||||
{/*<MyFirstComponent />*/}
|
||||
{/*<MySecondComponent />*/}
|
||||
</MyContainer>;
|
||||
const b = <MyContainer>
|
||||
<MyFirstComponent />
|
||||
<MySecondComponent />
|
||||
</MyContainer>;
|
||||
//const c = <MyContainer>
|
||||
// <MyFirstComponent />
|
||||
// <MySecondComponent />
|
||||
</MyContainer>;`);
|
30
tests/cases/fourslash/toggleLineComment8.ts
Normal file
30
tests/cases/fourslash/toggleLineComment8.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
// When indentation is different between lines it should get the left most indentation
|
||||
// and use that for all lines.
|
||||
// When uncommeting, doesn't matter what indentation the line has.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <div>
|
||||
//// [|<div>
|
||||
//// SomeText
|
||||
//// </div>|]
|
||||
//// </div>;
|
||||
////
|
||||
//// const b = <div>
|
||||
//// {/*[|<div>*/}
|
||||
//// {/* SomeText*/}
|
||||
//// {/*</div>|]*/}
|
||||
//// </div>;
|
||||
|
||||
|
||||
verify.toggleLineComment(
|
||||
`const a = <div>
|
||||
{/*<div>*/}
|
||||
{/* SomeText*/}
|
||||
{/*</div>*/}
|
||||
</div>;
|
||||
|
||||
const b = <div>
|
||||
<div>
|
||||
SomeText
|
||||
</div>
|
||||
</div>;`);
|
18
tests/cases/fourslash/toggleLineComment9.ts
Normal file
18
tests/cases/fourslash/toggleLineComment9.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// If at least one line is not commented then comment all lines again.
|
||||
// TODO: Not sure about this one. The default behavior for line comment is to add en extra
|
||||
// layer of comments (see toggleLineComment4 test). For jsx this doesn't work right as it's actually
|
||||
// multiline comment. Figure out what to do.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <div>
|
||||
//// {/*[|<div>*/}
|
||||
//// SomeText
|
||||
//// {/*</div>|]*/}
|
||||
//// </div>;
|
||||
|
||||
verify.toggleLineComment(
|
||||
`const a = <div>
|
||||
{/*<div>*/}
|
||||
{/* SomeText*/}
|
||||
{/*</div>*/}
|
||||
</div>;`);
|
30
tests/cases/fourslash/toggleMultilineComment1.ts
Normal file
30
tests/cases/fourslash/toggleMultilineComment1.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Simple multiline comment and uncomment.
|
||||
|
||||
//// let var1[| = 1;
|
||||
//// let var2 = 2;
|
||||
//// let var3 |]= 3;
|
||||
////
|
||||
//// let var4/* = 1;
|
||||
//// let var5 [||]= 2;
|
||||
//// let var6 */= 3;
|
||||
////
|
||||
//// [|/*let var7 = 1;
|
||||
//// let var8 = 2;
|
||||
//// let var9 = 3;*/|]
|
||||
////
|
||||
//// let var10[||] = 10;
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`let var1/* = 1;
|
||||
let var2 = 2;
|
||||
let var3 */= 3;
|
||||
|
||||
let var4 = 1;
|
||||
let var5 = 2;
|
||||
let var6 = 3;
|
||||
|
||||
let var7 = 1;
|
||||
let var8 = 2;
|
||||
let var9 = 3;
|
||||
|
||||
let var10/**/ = 10;`);
|
35
tests/cases/fourslash/toggleMultilineComment2.ts
Normal file
35
tests/cases/fourslash/toggleMultilineComment2.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
// If selection is outside of a multiline comment then insert comment
|
||||
// instead of removing.
|
||||
|
||||
//// let var1/* = 1;
|
||||
//// let var2 [|= 2;
|
||||
//// let var3 */= 3;|]
|
||||
////
|
||||
//// [|let var4/* = 1;
|
||||
//// let var5 |]= 2;
|
||||
//// let var6 */= 3;
|
||||
////
|
||||
//// [|let var7/* = 1;
|
||||
//// let var8 = 2;
|
||||
//// let var9 */= 3;|]
|
||||
////
|
||||
//// /*let va[|r10 = 1;*/
|
||||
//// let var11 = 2;
|
||||
//// /*let var12|] = 3;*/
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`let var1/* = 1;
|
||||
let var2 *//*= 2;
|
||||
let var3 *//*= 3;*/
|
||||
|
||||
/*let var4*//* = 1;
|
||||
let var5 *//*= 2;
|
||||
let var6 */= 3;
|
||||
|
||||
/*let var7*//* = 1;
|
||||
let var8 = 2;
|
||||
let var9 *//*= 3;*/
|
||||
|
||||
/*let va*//*r10 = 1;*//*
|
||||
let var11 = 2;
|
||||
*//*let var12*//* = 3;*/`);
|
28
tests/cases/fourslash/toggleMultilineComment3.ts
Normal file
28
tests/cases/fourslash/toggleMultilineComment3.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/// <reference path="fourslash.ts">
|
||||
|
||||
// If range is inside a single line comment, just add the multiline comment.
|
||||
|
||||
//// // let va[|r1 = 1;
|
||||
//// let var2 = 2;
|
||||
//// // let var3|] = 3;
|
||||
////
|
||||
//// // let va[|r4 = 1;
|
||||
//// let var5 = 2;
|
||||
//// /* let var6|] = 3;*/
|
||||
////
|
||||
//// /* let va[|r7 = 1;*/
|
||||
//// let var8 = 2;
|
||||
//// // let var9|] = 3;
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`/*// let var1 = 1;
|
||||
let var2 = 2;
|
||||
// let var3*/ = 3;
|
||||
|
||||
/*// let var4 = 1;
|
||||
let var5 = 2;
|
||||
*//* let var6*//* = 3;*/
|
||||
|
||||
/* let va*//*r7 = 1;*//*
|
||||
let var8 = 2;
|
||||
// let var9*/ = 3;`);
|
7
tests/cases/fourslash/toggleMultilineComment4.ts
Normal file
7
tests/cases/fourslash/toggleMultilineComment4.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
// This is an edgecase. The string contains a multiline comment syntax but it is a string
|
||||
// and not actually a comment. When toggling it doesn't get escaped or appended comments.
|
||||
// The result would be a portion of the selection to be "not commented".
|
||||
|
||||
//// /*let s[|omeLongVa*/riable = "Some other /*long th*/in|]g";
|
||||
|
||||
verify.toggleMultilineComment(`/*let s*//*omeLongVa*//*riable = "Some other /*long th*/in*/g";`);
|
34
tests/cases/fourslash/toggleMultilineComment5.ts
Normal file
34
tests/cases/fourslash/toggleMultilineComment5.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Jsx uses block comments for each line commented.
|
||||
|
||||
// Common JSX comment scenarios
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <div tabIndex="0">[|</div>;|]
|
||||
//// const b = <div>This is [|valid HTML &|] JSX at the same time.</div>;
|
||||
//// const c = <MyContainer>
|
||||
//// [|<MyFirstComponent />
|
||||
//// <MySecondComponent />|]
|
||||
//// </MyContainer>;
|
||||
//// const d = <MyContainer>
|
||||
//// <MyFirstComp[|onent />
|
||||
//// <MySecondComponent />|]
|
||||
//// </MyContainer>;
|
||||
//// const e = <MyComponent>[|{'foo'}|]</MyComponent>;
|
||||
//// const f = <div>Some text</div[|>;|]
|
||||
//// const g = <div>Some text<[|/div>;|]
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`const a = <div tabIndex="0">{/*</div>;*/}
|
||||
const b = <div>This is {/*valid HTML &*/} JSX at the same time.</div>;
|
||||
const c = <MyContainer>
|
||||
{/*<MyFirstComponent />
|
||||
<MySecondComponent />*/}
|
||||
</MyContainer>;
|
||||
const d = <MyContainer>
|
||||
<MyFirstComp{/*onent />
|
||||
<MySecondComponent />*/}
|
||||
</MyContainer>;
|
||||
const e = <MyComponent>{/*{'foo'}*/}</MyComponent>;
|
||||
const f = <div>Some text</div{/*>;*/}
|
||||
const g = <div>Some text<{/*/div>;*/}`
|
||||
);
|
43
tests/cases/fourslash/toggleMultilineComment6.ts
Normal file
43
tests/cases/fourslash/toggleMultilineComment6.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Jsx uses multiline comments for each line commented.
|
||||
|
||||
// Selection is outside of a multiline comments inserts multiline comments instead of removing.
|
||||
// There's some variations between jsx and js comments depending on the position.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const var1 = <div>Tex{/*t1</div>;
|
||||
//// const var2 = <div>Text2[|</div>;
|
||||
//// const var3 = <div>Tex*/}t3</div>;|]
|
||||
////
|
||||
//// [|const var4 = <div>Tex{/*t4</div>;
|
||||
//// const var5 = <div|]>Text5</div>;
|
||||
//// const var6 = <div>Tex*/}t6</div>;
|
||||
////
|
||||
//// [|const var7 = <div>Tex{/*t7</div>;
|
||||
//// const var8 = <div>Text8</div>;
|
||||
//// const var9 = <div>Tex*/}t9</div>;|]
|
||||
////
|
||||
//// const var10 = <div>
|
||||
//// {/*<div>T[|ext</div>*/}
|
||||
//// <div>Text</div>
|
||||
//// {/*<div>Text|]</div>*/}
|
||||
//// </div>;
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`const var1 = <div>Tex{/*t1</div>;
|
||||
const var2 = <div>Text2*/}{/*</div>;
|
||||
const var3 = <div>Tex*/}{/*t3</div>;*/}
|
||||
|
||||
/*const var4 = <div>Tex{*//*t4</div>;
|
||||
const var5 = <div*//*>Text5</div>;
|
||||
const var6 = <div>Tex*/}t6</div>;
|
||||
|
||||
/*const var7 = <div>Tex{*//*t7</div>;
|
||||
const var8 = <div>Text8</div>;
|
||||
const var9 = <div>Tex*//*}t9</div>;*/
|
||||
|
||||
const var10 = <div>
|
||||
{/*<div>T*/}{/*ext</div>*/}{/*
|
||||
<div>Text</div>
|
||||
*/}{/*<div>Text*/}{/*</div>*/}
|
||||
</div>;`
|
||||
);
|
33
tests/cases/fourslash/toggleMultilineComment7.ts
Normal file
33
tests/cases/fourslash/toggleMultilineComment7.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Cases where the cursor is inside JSX like sintax but it's actually js.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = (
|
||||
//// [|<div>
|
||||
//// some text|]
|
||||
//// </div>
|
||||
//// );
|
||||
//// const b = <MyComponent foo={1 [|+ 2 + 3 + 4|]} />;
|
||||
//// const c = <MyComponent message={[|'hello world'|]} />;
|
||||
//// const d = <MyTextBox autocomplete={tr[|ue|]} />;
|
||||
//// const e = <MyCo[|mponent message={'hello world'} />;|]
|
||||
//// const f = [
|
||||
//// [|<li key="A">First item</li>,
|
||||
//// <li key="B">Second item</li>,|]
|
||||
//// <li key="C">Third item</li>,
|
||||
//// ];
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`const a = (
|
||||
/*<div>
|
||||
some text*/
|
||||
</div>
|
||||
);
|
||||
const b = <MyComponent foo={1 /*+ 2 + 3 + 4*/} />;
|
||||
const c = <MyComponent message={/*'hello world'*/} />;
|
||||
const d = <MyTextBox autocomplete={tr/*ue*/} />;
|
||||
const e = <MyCo/*mponent message={'hello world'} />;*/
|
||||
const f = [
|
||||
/*<li key="A">First item</li>,
|
||||
<li key="B">Second item</li>,*/
|
||||
<li key="C">Third item</li>,
|
||||
];`);
|
12
tests/cases/fourslash/toggleMultilineComment8.ts
Normal file
12
tests/cases/fourslash/toggleMultilineComment8.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// If the range only contains comments, uncomment all.
|
||||
|
||||
//// /*let var[|1 = 1;*/
|
||||
//// /*let var2 = 2;*/
|
||||
////
|
||||
//// /*let var3 |]= 3;*/
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`let var1 = 1;
|
||||
let var2 = 2;
|
||||
|
||||
let var3 = 3;`);
|
30
tests/cases/fourslash/toggleMultilineComment9.ts
Normal file
30
tests/cases/fourslash/toggleMultilineComment9.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
// When there's is only whitespace, insert comment. If there is whitespace but theres a comment in bewteen, then uncomment.
|
||||
|
||||
//// /*let var1[| = 1;*/
|
||||
//// |]
|
||||
////
|
||||
//// [|
|
||||
//// /*let var2 = 2;*/|]
|
||||
////
|
||||
//// [|
|
||||
////
|
||||
//// |]
|
||||
////
|
||||
//// [||]
|
||||
////
|
||||
//// let var3[||] = 3;
|
||||
|
||||
verify.toggleMultilineComment(
|
||||
`let var1 = 1;
|
||||
|
||||
|
||||
|
||||
let var2 = 2;
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
/**/
|
||||
|
||||
let var3/**/ = 3;`);
|
42
tests/cases/fourslash/uncommentSelection1.ts
Normal file
42
tests/cases/fourslash/uncommentSelection1.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Simple comment selection cases.
|
||||
|
||||
//// //let var1[| = 1;
|
||||
//// //let var2 = 2;
|
||||
//// //let var3 |]= 3;
|
||||
////
|
||||
//// //let var4[| = 4;
|
||||
//// /*let var5 = 5;*/
|
||||
//// //let var6 = 6;
|
||||
////
|
||||
//// let var7 |]= 7;
|
||||
////
|
||||
//// let var8/* = 1;
|
||||
//// let var9 [||]= 2;
|
||||
//// let var10 */= 3;
|
||||
////
|
||||
//// let var11[||]/* = 1;
|
||||
//// let var12 = 2;
|
||||
//// let var13 */= 3;
|
||||
////
|
||||
//// ////let var14 [||]= 14;
|
||||
|
||||
verify.uncommentSelection(
|
||||
`let var1 = 1;
|
||||
let var2 = 2;
|
||||
let var3 = 3;
|
||||
|
||||
let var4 = 4;
|
||||
let var5 = 5;
|
||||
let var6 = 6;
|
||||
|
||||
let var7 = 7;
|
||||
|
||||
let var8 = 1;
|
||||
let var9 = 2;
|
||||
let var10 = 3;
|
||||
|
||||
let var11 = 1;
|
||||
let var12 = 2;
|
||||
let var13 = 3;
|
||||
|
||||
//let var14 = 14;`);
|
34
tests/cases/fourslash/uncommentSelection2.ts
Normal file
34
tests/cases/fourslash/uncommentSelection2.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Common uncomment jsx cases
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const a = <MyContainer>
|
||||
//// {/*<MyF[|irstComponent />*/}
|
||||
//// {/*<MySec|]ondComponent />*/}
|
||||
//// </MyContainer>;
|
||||
////
|
||||
//// const b = <div>
|
||||
//// {/*[|<div>*/}
|
||||
//// SomeText
|
||||
//// {/*</div>|]*/}
|
||||
//// </div>;
|
||||
////
|
||||
//// const c = <MyContainer>
|
||||
//// [||]{/*<MyFirstComponent />*/}
|
||||
//// </MyContainer>;
|
||||
|
||||
|
||||
verify.uncommentSelection(
|
||||
`const a = <MyContainer>
|
||||
<MyFirstComponent />
|
||||
<MySecondComponent />
|
||||
</MyContainer>;
|
||||
|
||||
const b = <div>
|
||||
<div>
|
||||
SomeText
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
const c = <MyContainer>
|
||||
<MyFirstComponent />
|
||||
</MyContainer>;`);
|
34
tests/cases/fourslash/uncommentSelection3.ts
Normal file
34
tests/cases/fourslash/uncommentSelection3.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Remove all comments within the selection
|
||||
|
||||
//// let var1/* = 1;
|
||||
//// let var2 [|= 2;
|
||||
//// let var3 */= 3;|]
|
||||
////
|
||||
//// [|let var4/* = 1;
|
||||
//// let var5 |]= 2;
|
||||
//// let var6 */= 3;
|
||||
////
|
||||
//// [|let var7/* = 1;
|
||||
//// let var8 = 2;
|
||||
//// let var9 */= 3;|]
|
||||
////
|
||||
//// /*let va[|r10 = 1;*/
|
||||
//// let var11 = 2;
|
||||
//// /*let var12|] = 3;*/
|
||||
|
||||
verify.uncommentSelection(
|
||||
`let var1 = 1;
|
||||
let var2 = 2;
|
||||
let var3 = 3;
|
||||
|
||||
let var4 = 1;
|
||||
let var5 = 2;
|
||||
let var6 = 3;
|
||||
|
||||
let var7 = 1;
|
||||
let var8 = 2;
|
||||
let var9 = 3;
|
||||
|
||||
let var10 = 1;
|
||||
let var11 = 2;
|
||||
let var12 = 3;`);
|
40
tests/cases/fourslash/uncommentSelection4.ts
Normal file
40
tests/cases/fourslash/uncommentSelection4.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Remove all comments in jsx.
|
||||
|
||||
//@Filename: file.tsx
|
||||
//// const var1 = <div>Tex{/*t1</div>;
|
||||
//// const var2 = <div>Text2[|</div>;
|
||||
//// const var3 = <div>Tex*/}t3</div>;|]
|
||||
////
|
||||
//// [|const var4 = <div>Tex{/*t4</div>;
|
||||
//// const var5 = <div|]>Text5</div>;
|
||||
//// const var6 = <div>Tex*/}t6</div>;
|
||||
////
|
||||
//// [|const var7 = <div>Tex{/*t7</div>;
|
||||
//// const var8 = <div>Text8</div>;
|
||||
//// const var9 = <div>Tex*/}t9</div>;|]
|
||||
////
|
||||
//// const var10 = <div>
|
||||
//// {/*<div>T[|ext</div>*/}
|
||||
//// <div>Text</div>
|
||||
//// {/*<div>Text|]</div>*/}
|
||||
//// </div>;
|
||||
|
||||
verify.uncommentSelection(
|
||||
`const var1 = <div>Text1</div>;
|
||||
const var2 = <div>Text2</div>;
|
||||
const var3 = <div>Text3</div>;
|
||||
|
||||
const var4 = <div>Text4</div>;
|
||||
const var5 = <div>Text5</div>;
|
||||
const var6 = <div>Text6</div>;
|
||||
|
||||
const var7 = <div>Text7</div>;
|
||||
const var8 = <div>Text8</div>;
|
||||
const var9 = <div>Text9</div>;
|
||||
|
||||
const var10 = <div>
|
||||
<div>Text</div>
|
||||
<div>Text</div>
|
||||
<div>Text</div>
|
||||
</div>;`
|
||||
);
|
Loading…
Reference in a new issue