mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Added toggleLineComment, toggleMultilineComment with jsx and tests
This commit is contained in:
parent
3eaa7c65f6
commit
33333e86eb
@ -812,6 +812,14 @@ namespace ts.server {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
toggleLineComment(): ts.TextChange[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
toggleMultilineComment(): ts.TextChange[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
throw new Error("dispose is not available through the server layer.");
|
||||
}
|
||||
|
||||
@ -3657,6 +3657,26 @@ namespace FourSlash {
|
||||
public configurePlugin(pluginName: string, configuration: any): void {
|
||||
(<ts.server.SessionClient>this.languageService).configurePlugin(pluginName, configuration);
|
||||
}
|
||||
|
||||
public toggleLineComment(newFileContent: string): void {
|
||||
const ranges = this.getRanges();
|
||||
assert(ranges.length);
|
||||
const changes = this.languageService.toggleLineComment(this.activeFile.fileName, ranges);
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(newFileContent: string): void {
|
||||
const ranges = this.getRanges();
|
||||
assert(ranges.length);
|
||||
const changes = this.languageService.toggleMultilineComment(this.activeFile.fileName, ranges);
|
||||
|
||||
this.applyEdits(this.activeFile.fileName, changes);
|
||||
|
||||
this.verifyCurrentFileContent(newFileContent);
|
||||
}
|
||||
}
|
||||
|
||||
function prefixMessage(message: string | undefined) {
|
||||
|
||||
@ -210,6 +210,14 @@ namespace FourSlashInterface {
|
||||
public refactorAvailable(name: string, actionName?: string) {
|
||||
this.state.verifyRefactorAvailable(this.negative, name, actionName);
|
||||
}
|
||||
|
||||
public toggleLineComment(newFileContent: string) {
|
||||
this.state.toggleLineComment(newFileContent);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(newFileContent: string) {
|
||||
this.state.toggleMultilineComment(newFileContent);
|
||||
}
|
||||
}
|
||||
|
||||
export class Verify extends VerifyNegatable {
|
||||
|
||||
@ -600,6 +600,12 @@ namespace Harness.LanguageService {
|
||||
clearSourceMapperCache(): never {
|
||||
return ts.notImplemented();
|
||||
}
|
||||
toggleLineComment(fileName: string, textRanges: ts.TextRange[]): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.toggleLineComment(fileName, textRanges));
|
||||
}
|
||||
toggleMultilineComment(fileName: string, textRanges: ts.TextRange[]): ts.TextChange[] {
|
||||
return unwrapJSONCallResult(this.shim.toggleMultilineComment(fileName, textRanges));
|
||||
}
|
||||
dispose(): void { this.shim.dispose({}); }
|
||||
}
|
||||
|
||||
|
||||
@ -136,6 +136,10 @@ namespace ts.server.protocol {
|
||||
SelectionRange = "selectionRange",
|
||||
/* @internal */
|
||||
SelectionRangeFull = "selectionRange-full",
|
||||
ToggleLineComment = "toggleLineComment",
|
||||
ToggleLineCommentFull = "toggleLineComment-full",
|
||||
ToggleMultilineComment = "toggleMultilineComment",
|
||||
ToggleMultilineCommentFull = "toggleMultilineComment-full",
|
||||
|
||||
PrepareCallHierarchy = "prepareCallHierarchy",
|
||||
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
|
||||
@ -919,6 +923,18 @@ namespace ts.server.protocol {
|
||||
end: Location;
|
||||
}
|
||||
|
||||
export interface TextRange {
|
||||
/**
|
||||
* Position of the first character.
|
||||
*/
|
||||
pos: number;
|
||||
|
||||
/**
|
||||
* Position of the last character.
|
||||
*/
|
||||
end: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object found in response messages defining a span of text in a specific source file.
|
||||
*/
|
||||
@ -1533,6 +1549,24 @@ namespace ts.server.protocol {
|
||||
parent?: SelectionRange;
|
||||
}
|
||||
|
||||
export interface ToggleLineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleLineComment;
|
||||
arguments: ToggleLineCommentRequestArgs;
|
||||
}
|
||||
|
||||
export interface ToggleLineCommentRequestArgs extends FileRequestArgs {
|
||||
textRanges: TextRange[];
|
||||
}
|
||||
|
||||
export interface ToggleMultilineCommentRequest extends FileRequest {
|
||||
command: CommandTypes.ToggleMultilineComment;
|
||||
arguments: ToggleMultilineCommentRequestArgs;
|
||||
}
|
||||
|
||||
export interface ToggleMultilineCommentRequestArgs extends FileRequestArgs {
|
||||
textRanges: TextRange[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Information found in an "open" request.
|
||||
*/
|
||||
|
||||
@ -2196,6 +2196,22 @@ namespace ts.server {
|
||||
});
|
||||
}
|
||||
|
||||
private toggleLineComment(args: protocol.ToggleLineCommentRequestArgs, simplifiedResult: boolean) {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
|
||||
const result = project.getLanguageService().toggleLineComment(file, args.textRanges);
|
||||
|
||||
return simplifiedResult ? [] : result;
|
||||
}
|
||||
|
||||
private toggleMultilineComment(args: protocol.ToggleMultilineCommentRequestArgs, simplifiedResult: boolean) {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
|
||||
const result = project.getLanguageService().toggleMultilineComment(file, args.textRanges);
|
||||
|
||||
return simplifiedResult ? [] : result;
|
||||
}
|
||||
|
||||
private mapSelectionRange(selectionRange: SelectionRange, scriptInfo: ScriptInfo): protocol.SelectionRange {
|
||||
const result: protocol.SelectionRange = {
|
||||
textSpan: toProtocolTextSpan(selectionRange.textSpan, scriptInfo),
|
||||
@ -2641,6 +2657,18 @@ 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.ToggleMultilineComment]: (request: protocol.ToggleMultilineCommentRequest) => {
|
||||
return this.requiredResponse(this.toggleMultilineComment(request.arguments, /*simplifiedResult*/false));
|
||||
},
|
||||
});
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
|
||||
|
||||
@ -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);
|
||||
@ -1977,6 +1977,185 @@ 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, textRanges: TextRange[]): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
|
||||
const textChanges: TextChange[] = [];
|
||||
|
||||
for (const textRange of textRanges) {
|
||||
const { lineStarts, firstLine, lastLine } = getLinesForRange(sourceFile, textRange);
|
||||
|
||||
let isCommenting = false;
|
||||
let leftMostPosition = Number.MAX_VALUE;
|
||||
let lineTextStarts = new Map<number>();
|
||||
const whiteSpaceRegex = new RegExp(/\S/);
|
||||
|
||||
// First check the lines before any text changes.
|
||||
for (let i = firstLine; i <= lastLine; i++) {
|
||||
const lineText = sourceFile.text.substring(lineStarts[i], lineStarts[i + 1]); // TODO: Validate the end of line it might go outside of range.
|
||||
|
||||
// Find the start of text and the left-most character. No-op on empty lines.
|
||||
const regExec = whiteSpaceRegex.exec(lineText);
|
||||
if (regExec) {
|
||||
leftMostPosition = Math.min(leftMostPosition, regExec.index);
|
||||
lineTextStarts.set(i.toString(), regExec.index);
|
||||
// let sourceFilePosition = lineStarts[i] + leftMostPosition;
|
||||
if (lineText.substr(regExec.index, 3) !== "// ") { // TODO: Validate when it is inside a comment. It can only uncomment if it's inside a comment. // TODO: Check when not finishing on empty space.
|
||||
isCommenting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (isCommenting) {
|
||||
textChanges.push({
|
||||
newText: "// ",
|
||||
span: {
|
||||
length: 0,
|
||||
start: lineStarts[i] + leftMostPosition
|
||||
}
|
||||
});
|
||||
} else {
|
||||
textChanges.push({
|
||||
newText: "",
|
||||
span: {
|
||||
length: 3,
|
||||
start: lineStarts[i] + lineTextStart
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return textChanges;
|
||||
}
|
||||
|
||||
function toggleMultilineComment(fileName: string, textRanges: TextRange[]): TextChange[] {
|
||||
const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
|
||||
const textChanges: TextChange[] = [];
|
||||
const { text } = sourceFile;
|
||||
|
||||
for (const textRange of textRanges) {
|
||||
let isCommenting = false;
|
||||
const positions = [] as number[] as SortedArray<number>;
|
||||
|
||||
let pos = textRange.pos;
|
||||
const isJsx = isInsideJsxTags(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) {
|
||||
// Include brace positions.
|
||||
if (isJsx) {
|
||||
commentRange.pos--;
|
||||
commentRange.end++;
|
||||
}
|
||||
|
||||
positions.push(commentRange.pos);
|
||||
if (commentRange.kind === SyntaxKind.MultiLineCommentTrivia) {
|
||||
positions.push(commentRange.end);
|
||||
}
|
||||
|
||||
pos = commentRange.end + 1;
|
||||
} else {
|
||||
isCommenting = true;
|
||||
|
||||
const newPos = text.substring(pos, textRange.end).search(`(${openMultilineRegex})|(${closeMultilineRegex})`);
|
||||
pos = newPos === -1 ? textRange.end + 1 : pos + newPos + closeMultiline.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCommenting) {
|
||||
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.
|
||||
const lastPos = positions[positions.length - 1];
|
||||
if (text.substr(lastPos - closeMultiline.length, closeMultiline.length) !== closeMultiline) {
|
||||
textChanges.push({
|
||||
newText: closeMultiline,
|
||||
span: {
|
||||
length: 0,
|
||||
start: lastPos
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < positions.length; i++) {
|
||||
const offset = text.substr(positions[i] - closeMultiline.length, closeMultiline.length) === closeMultiline ? closeMultiline.length : 0;
|
||||
textChanges.push({
|
||||
newText: "",
|
||||
span: {
|
||||
length: 2,
|
||||
start: positions[i] - offset
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -2255,7 +2434,9 @@ namespace ts {
|
||||
clearSourceMapperCache: () => sourceMapper.clearCache(),
|
||||
prepareCallHierarchy,
|
||||
provideCallHierarchyIncomingCalls,
|
||||
provideCallHierarchyOutgoingCalls
|
||||
provideCallHierarchyOutgoingCalls,
|
||||
toggleLineComment,
|
||||
toggleMultilineComment
|
||||
};
|
||||
}
|
||||
|
||||
@ -2319,7 +2500,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,9 @@ namespace ts {
|
||||
|
||||
getEmitOutput(fileName: string): string;
|
||||
getEmitOutputObject(fileName: string): EmitOutput;
|
||||
|
||||
toggleLineComment(fileName: string, textChanges: ts.TextRange[]): string;
|
||||
toggleMultilineComment(fileName: string, textChanges: ts.TextRange[]): string;
|
||||
}
|
||||
|
||||
export interface ClassifierShim extends Shim {
|
||||
@ -1066,6 +1069,20 @@ namespace ts {
|
||||
() => this.languageService.getEmitOutput(fileName),
|
||||
this.logPerformance) as EmitOutput;
|
||||
}
|
||||
|
||||
public toggleLineComment(fileName: string, textRanges: ts.TextRange[]): string {
|
||||
return this.forwardJSONCall(
|
||||
`toggleLineComment('${fileName}', '${JSON.stringify(textRanges)}')`,
|
||||
() => this.languageService.toggleLineComment(fileName, textRanges)
|
||||
);
|
||||
}
|
||||
|
||||
public toggleMultilineComment(fileName: string, textRanges: ts.TextRange[]): string {
|
||||
return this.forwardJSONCall(
|
||||
`toggleMultilineComment('${fileName}', '${JSON.stringify(textRanges)}')`,
|
||||
() => this.languageService.toggleMultilineComment(fileName, textRanges)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function convertClassifications(classifications: Classifications): { spans: string, endOfLineState: EndOfLineState } {
|
||||
|
||||
@ -486,6 +486,9 @@ namespace ts {
|
||||
|
||||
/* @internal */ getNonBoundSourceFile(fileName: string): SourceFile;
|
||||
|
||||
toggleLineComment(fileName: string, textRanges: TextRange[]): TextChange[];
|
||||
toggleMultilineComment(fileName: string, textRanges: 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:
|
||||
@ -1320,6 +1320,25 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isInsideJsxTags(sourceFile: SourceFile, position: number) {
|
||||
const token = getTokenAtPosition(sourceFile, position);
|
||||
|
||||
switch (token.kind) {
|
||||
case SyntaxKind.JsxText:
|
||||
return true;
|
||||
case SyntaxKind.LessThanToken:
|
||||
case SyntaxKind.Identifier:
|
||||
return token.parent.kind === SyntaxKind.JsxText // <div>Hello |</div>
|
||||
|| token.parent.kind === SyntaxKind.JsxClosingElement // <div>|</div>
|
||||
|| isJsxOpeningLikeElement(token.parent) && isJsxElement(token.parent.parent) // <div>|<component /></div> or <div><comp|onent /></div>
|
||||
case SyntaxKind.CloseBraceToken:
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return isJsxExpression(token.parent) && isJsxElement(token.parent.parent); // <div>{|}</div> or <div>|{}</div>
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind, sourceFile: SourceFile) {
|
||||
const tokenKind = token.kind;
|
||||
let remainingMatchingTokens = 0;
|
||||
@ -1346,7 +1365,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 +1458,7 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.EqualsGreaterThanToken:
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.StringLiteral:
|
||||
@ -1447,7 +1466,7 @@ namespace ts {
|
||||
case SyntaxKind.BigIntLiteral:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
case SyntaxKind.ExtendsKeyword:
|
||||
|
||||
@ -272,6 +272,8 @@ namespace ts.server {
|
||||
CommandNames.PrepareCallHierarchy,
|
||||
CommandNames.ProvideCallHierarchyIncomingCalls,
|
||||
CommandNames.ProvideCallHierarchyOutgoingCalls,
|
||||
CommandNames.ToggleLineComment,
|
||||
CommandNames.ToggleMultilineComment
|
||||
];
|
||||
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
|
||||
@ -396,6 +396,9 @@ declare namespace FourSlashInterface {
|
||||
generateTypes(...options: GenerateTypesOptions[]): void;
|
||||
|
||||
organizeImports(newContent: string): void;
|
||||
|
||||
toggleLineComment(newFileContent: string): void;
|
||||
toggleBlockComment(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;`);
|
||||
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 uncomment then comment all lines again.
|
||||
|
||||
//// // 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;`);
|
||||
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
|
||||
\`;`);
|
||||
20
tests/cases/fourslash/toggleLineComment6.ts
Normal file
20
tests/cases/fourslash/toggleLineComment6.ts
Normal file
@ -0,0 +1,20 @@
|
||||
// Selection is at the start of jsx it's still considered js.
|
||||
|
||||
//// function a() {
|
||||
//// let foo = "bar";
|
||||
//// return (
|
||||
//// [|<div>
|
||||
//// {foo}|]
|
||||
//// </div>
|
||||
//// );
|
||||
//// }
|
||||
|
||||
verify.toggleLineComment(
|
||||
`function a() {
|
||||
let foo = "bar";
|
||||
return (
|
||||
// <div>
|
||||
// {foo}
|
||||
</div>
|
||||
);
|
||||
}`);
|
||||
26
tests/cases/fourslash/toggleMultilineComment1.ts
Normal file
26
tests/cases/fourslash/toggleMultilineComment1.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// Simple block 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;*/|]
|
||||
|
||||
verify.toggleBlockComment(
|
||||
`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;`);
|
||||
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 block 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.toggleBlockComment(
|
||||
`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 block 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.toggleBlockComment(
|
||||
`/*// 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 and because it is a string,
|
||||
// is 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";`);
|
||||
30
tests/cases/fourslash/toggleMultilineComment5.ts
Normal file
30
tests/cases/fourslash/toggleMultilineComment5.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// 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>;
|
||||
|
||||
verify.toggleBlockComment(
|
||||
`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>;`
|
||||
);
|
||||
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 block comments inserts block 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>;`
|
||||
);
|
||||
Loading…
x
Reference in New Issue
Block a user