Added jsx to singleLineComment

This commit is contained in:
Armando Aguirre 2020-02-24 17:24:08 -08:00
parent 97de811d48
commit fc9753473e
13 changed files with 198 additions and 77 deletions

View file

@ -1997,43 +1997,67 @@ namespace ts {
let leftMostPosition = Number.MAX_VALUE; let leftMostPosition = Number.MAX_VALUE;
let lineTextStarts = new Map<number>(); let lineTextStarts = new Map<number>();
const whiteSpaceRegex = new RegExp(/\S/); const whiteSpaceRegex = new RegExp(/\S/);
const isJsx = isInsideJsxElement(sourceFile, lineStarts[firstLine])
const openComment = isJsx ? "{/*" : "//";
const closeComment = "*/}";
// First check the lines before any text changes. // First check the lines before any text changes.
for (let i = firstLine; i <= lastLine; i++) { 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. 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. // Find the start of text and the left-most character. No-op on empty lines.
const regExec = whiteSpaceRegex.exec(lineText); const regExec = whiteSpaceRegex.exec(lineText);
if (regExec) { if (regExec) {
leftMostPosition = Math.min(leftMostPosition, regExec.index); leftMostPosition = Math.min(leftMostPosition, regExec.index);
lineTextStarts.set(i.toString(), 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. if (lineText.substr(regExec.index, openComment.length) !== openComment) { // 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; isCommenting = true;
} }
} }
} }
// Push all text changes.
for (let i = firstLine; i <= lastLine; i++) { for (let i = firstLine; i <= lastLine; i++) {
const lineTextStart = lineTextStarts.get(i.toString()); const lineTextStart = lineTextStarts.get(i.toString());
// If the line is not an empty line; otherwise no-op; // If the line is not an empty line; otherwise no-op;
if (lineTextStart !== undefined) { if (lineTextStart !== undefined) {
if (isCommenting) { if (isCommenting) {
textChanges.push({ textChanges.push({
newText: "// ", newText: openComment,
span: { span: {
length: 0, length: 0,
start: lineStarts[i] + leftMostPosition start: lineStarts[i] + leftMostPosition
} }
}); });
if (isJsx) {
textChanges.push({
newText: closeComment,
span: {
length: 0,
start: sourceFile.getLineEndOfPosition(lineStarts[i])
}
});
}
} else { } else {
textChanges.push({ textChanges.push({
newText: "", newText: "",
span: { span: {
length: 3, length: openComment.length,
start: lineStarts[i] + lineTextStart start: lineStarts[i] + lineTextStart
} }
}); });
if (isJsx) {
textChanges.push({
newText: "",
span: {
length: closeComment.length,
start: sourceFile.getLineEndOfPosition(lineStarts[i]) - closeComment.length
}
});
}
} }
} }
} }
@ -2052,7 +2076,7 @@ namespace ts {
const positions = [] as number[] as SortedArray<number>; const positions = [] as number[] as SortedArray<number>;
let pos = textRange.pos; let pos = textRange.pos;
const isJsx = isInsideJsxTags(sourceFile, pos); const isJsx = isInsideJsxElement(sourceFile, pos);
const openMultiline = isJsx ? "{/*" : "/*"; const openMultiline = isJsx ? "{/*" : "/*";
const closeMultiline = isJsx ? "*/}" : "*/"; const closeMultiline = isJsx ? "*/}" : "*/";

View file

@ -1320,23 +1320,29 @@ namespace ts {
return false; return false;
} }
export function isInsideJsxTags(sourceFile: SourceFile, position: number) { export function isInsideJsxElement(sourceFile: SourceFile, position: number): boolean {
const token = getTokenAtPosition(sourceFile, position); function isInsideJsxElementRecursion(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) {
return position > node.getStart(sourceFile) || isInsideJsxElementRecursion(node.parent);
} else {
return false;
}
}
switch (token.kind) { return false;
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; return isInsideJsxElementRecursion(getTokenAtPosition(sourceFile, position));
} }
export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind, sourceFile: SourceFile) { export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind, sourceFile: SourceFile) {

View file

@ -4,14 +4,14 @@
//// let var2 = 2; //// let var2 = 2;
//// let var3 |]= 3; //// let var3 |]= 3;
//// ////
//// // let var4[| = 1; //// //let var4[| = 1;
//// // let var5 = 2; //// //let var5 = 2;
//// // let var6 |]= 3; //// //let var6 |]= 3;
verify.toggleLineComment( verify.toggleLineComment(
`// let var1 = 1; `//let var1 = 1;
// let var2 = 2; //let var2 = 2;
// let var3 = 3; //let var3 = 3;
let var4 = 1; let var4 = 1;
let var5 = 2; let var5 = 2;

View file

@ -6,15 +6,15 @@
//// let var2 = 2; //// let var2 = 2;
//// let var3 |]= 3; //// let var3 |]= 3;
//// ////
//// // let var4[| = 1; //// // let var4[| = 1;
//// // let var5 = 2; //// //let var5 = 2;
//// // let var6 |]= 3; //// // let var6 |]= 3;
verify.toggleLineComment( verify.toggleLineComment(
`// let var1 = 1; ` // let var1 = 1;
// let var2 = 2; //let var2 = 2;
// let var3 = 3; // let var3 = 3;
let var4 = 1; let var4 = 1;
let var5 = 2; let var5 = 2;
let var6 = 3;`); let var6 = 3;`);

View file

@ -6,18 +6,18 @@
//// ////
//// let var3 |]= 3; //// let var3 |]= 3;
//// ////
//// // let var4[| = 1; //// //let var4[| = 1;
//// ////
//// // let var5 = 2; //// //let var5 = 2;
//// ////
//// // let var6 |]= 3; //// //let var6 |]= 3;
verify.toggleLineComment( verify.toggleLineComment(
`// let var1 = 1; `//let var1 = 1;
// let var2 = 2; //let var2 = 2;
// let var3 = 3; //let var3 = 3;
let var4 = 1; let var4 = 1;

View file

@ -1,18 +1,18 @@
// If at least one line is uncomment then comment all lines again. // If at least one line is uncomment then comment all lines again.
//// // let var1[| = 1; //// //const a[| = 1;
//// let var2 = 2; //// const b = 2
//// // let var3 |]= 3; //// //const c =|] 3;
//// ////
//// // // let var4[| = 1; //// ////const d[| = 4;
//// // let var5 = 2; //// //const e = 5;
//// // // let var6 |]= 3; //// ////const e =|] 6;
verify.toggleLineComment( verify.toggleLineComment(
`// // let var1 = 1; `// //const a = 1;
// let var2 = 2; //const b = 2
// // let var3 = 3; // //const c = 3;
// let var4 = 1; //const d = 4;
let var5 = 2; const e = 5;
// let var6 = 3;`); //const e = 6;`);

View file

@ -1,8 +1,8 @@
// Comments inside strings are still considered comments. // Comments inside strings are still considered comments.
//// let var1 = ` //// let var1 = `
//// // some stri[|ng //// //some stri[|ng
//// // some other|] string //// //some other|] string
//// `; //// `;
//// ////
//// let var2 = ` //// let var2 = `
@ -17,6 +17,6 @@ some other string
\`; \`;
let var2 = \` let var2 = \`
// some string //some string
// some other string //some other string
\`;`); \`;`);

View file

@ -1,20 +1,15 @@
// Selection is at the start of jsx it's still considered js. // Selection is at the start of jsx its still js.
//// function a() { //@Filename: file.tsx
//// let foo = "bar"; //// let a = (
//// return ( //// [|<div>
//// [|<div> //// some text|]
//// {foo}|] //// </div>
//// </div> //// );
//// );
//// }
verify.toggleLineComment( verify.toggleLineComment(
`function a() { `let a = (
let foo = "bar"; //<div>
return ( // some text
// <div> </div>
// {foo} );`);
</div>
);
}`);

View 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>;`);

View 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>;`);

View file

@ -1,5 +1,5 @@
// This is an edgecase. The string contains a multiline comment syntax and because it is a string, // This is an edgecase. The string contains a multiline comment syntax but it is a string
// is not actually a comment. When toggling it doesn't get escaped or appended comments. // 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". // The result would be a portion of the selection to be "not commented".
//// /*let s[|omeLongVa*/riable = "Some other /*long th*/in|]g"; //// /*let s[|omeLongVa*/riable = "Some other /*long th*/in|]g";

View file

@ -14,6 +14,8 @@
//// <MySecondComponent />|] //// <MySecondComponent />|]
//// </MyContainer>; //// </MyContainer>;
//// const e = <MyComponent>[|{'foo'}|]</MyComponent>; //// const e = <MyComponent>[|{'foo'}|]</MyComponent>;
//// const f = <div>Some text</div[|>;|]
//// const g = <div>Some text<[|/div>;|]
verify.toggleMultilineComment( verify.toggleMultilineComment(
`const a = <div tabIndex="0">{/*</div>;*/} `const a = <div tabIndex="0">{/*</div>;*/}
@ -26,5 +28,7 @@ const d = <MyContainer>
<MyFirstComp{/*onent /> <MyFirstComp{/*onent />
<MySecondComponent />*/} <MySecondComponent />*/}
</MyContainer>; </MyContainer>;
const e = <MyComponent>{/*{'foo'}*/}</MyComponent>;` const e = <MyComponent>{/*{'foo'}*/}</MyComponent>;
const f = <div>Some text</div{/*>;*/}
const g = <div>Some text<{/*/div>;*/}`
); );

View 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>,
];`);