diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts
index 0d45039f5b1..b9a13fc5420 100644
--- a/src/services/textChanges.ts
+++ b/src/services/textChanges.ts
@@ -1075,7 +1075,7 @@ namespace ts.textChanges {
}
export function isValidLocationToAddComment(sourceFile: SourceFile, position: number) {
- return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position);
+ return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position) && !isInJSXText(sourceFile, position);
}
function needSemicolonBetween(a: Node, b: Node): boolean {
diff --git a/src/services/utilities.ts b/src/services/utilities.ts
index f0326599ad0..7a713fed749 100644
--- a/src/services/utilities.ts
+++ b/src/services/utilities.ts
@@ -909,6 +909,20 @@ namespace ts {
return isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile);
}
+ export function isInJSXText(sourceFile: SourceFile, position: number) {
+ const token = getTokenAtPosition(sourceFile, position);
+ if (isJsxText(token)) {
+ return true;
+ }
+ if (token.kind === SyntaxKind.OpenBraceToken && isJsxExpression(token.parent) && isJsxElement(token.parent.parent)) {
+ return true;
+ }
+ if (token.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(token.parent) && isJsxElement(token.parent.parent)) {
+ return true;
+ }
+ return false;
+ }
+
export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind, sourceFile: SourceFile) {
const tokenKind = token.kind;
let remainingMatchingTokens = 0;
diff --git a/tests/cases/fourslash/jsxTsIgnoreOnJSXExpressionsAndChildren.ts b/tests/cases/fourslash/jsxTsIgnoreOnJSXExpressionsAndChildren.ts
new file mode 100644
index 00000000000..9670a88cc3d
--- /dev/null
+++ b/tests/cases/fourslash/jsxTsIgnoreOnJSXExpressionsAndChildren.ts
@@ -0,0 +1,95 @@
+///