Added jsx to singleLineComment
This commit is contained in:
parent
97de811d48
commit
fc9753473e
|
@ -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 ? "*/}" : "*/";
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;`);
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;`);
|
|
@ -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
|
||||||
\`;`);
|
\`;`);
|
|
@ -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>
|
|
||||||
);
|
|
||||||
}`);
|
|
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>;`);
|
|
@ -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";
|
||||||
|
|
|
@ -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>;*/}`
|
||||||
);
|
);
|
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>,
|
||||||
|
];`);
|
Loading…
Reference in a new issue