mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix poor error span for unclosed JSX tags in the presence of whitespace/comments (#37419)
* Improve jsx tag error span * Move solution to parseJsxChild func * Add tests and update baselines * Update comment in src/compiler/parser.ts Co-Authored-By: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> * Use skipTrivia to check for whitespaces and other trivia * Import React into errorSpanForUnclosedJsxTag.tsx * . * . Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
co-authored by
Daniel Rosenwasser
parent
e2156a1535
commit
a83ce339c9
@@ -4545,7 +4545,11 @@ namespace ts {
|
||||
parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag);
|
||||
}
|
||||
else {
|
||||
parseErrorAtRange(openingTag.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName));
|
||||
// We want the error span to cover only 'Foo.Bar' in < Foo.Bar >
|
||||
// or to cover only 'Foo' in < Foo >
|
||||
const tag = openingTag.tagName;
|
||||
const start = skipTrivia(sourceText, tag.pos);
|
||||
parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName));
|
||||
}
|
||||
return undefined;
|
||||
case SyntaxKind.LessThanSlashToken:
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx(9,14): error TS17008: JSX element 'Foo.Bar' has no corresponding closing tag.
|
||||
tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx(11,13): error TS17008: JSX element 'Baz' has no corresponding closing tag.
|
||||
tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx(11,23): error TS1005: '</' expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx (3 errors) ====
|
||||
declare const React: any
|
||||
|
||||
let Foo = {
|
||||
Bar() {}
|
||||
}
|
||||
|
||||
let Baz = () => {}
|
||||
|
||||
let x = < Foo.Bar >Hello
|
||||
~~~~~~~
|
||||
!!! error TS17008: JSX element 'Foo.Bar' has no corresponding closing tag.
|
||||
|
||||
let y = < Baz >Hello
|
||||
~~~
|
||||
!!! error TS17008: JSX element 'Baz' has no corresponding closing tag.
|
||||
|
||||
!!! error TS1005: '</' expected.
|
||||
@@ -0,0 +1,21 @@
|
||||
//// [errorSpanForUnclosedJsxTag.tsx]
|
||||
declare const React: any
|
||||
|
||||
let Foo = {
|
||||
Bar() {}
|
||||
}
|
||||
|
||||
let Baz = () => {}
|
||||
|
||||
let x = < Foo.Bar >Hello
|
||||
|
||||
let y = < Baz >Hello
|
||||
|
||||
//// [errorSpanForUnclosedJsxTag.js]
|
||||
var Foo = {
|
||||
Bar: function () { }
|
||||
};
|
||||
var Baz = function () { };
|
||||
var x = React.createElement(Foo.Bar, null,
|
||||
"Hello let y = ",
|
||||
React.createElement(Baz, null, "Hello"));
|
||||
@@ -0,0 +1,23 @@
|
||||
=== tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx ===
|
||||
declare const React: any
|
||||
>React : Symbol(React, Decl(errorSpanForUnclosedJsxTag.tsx, 0, 13))
|
||||
|
||||
let Foo = {
|
||||
>Foo : Symbol(Foo, Decl(errorSpanForUnclosedJsxTag.tsx, 2, 3))
|
||||
|
||||
Bar() {}
|
||||
>Bar : Symbol(Bar, Decl(errorSpanForUnclosedJsxTag.tsx, 2, 11))
|
||||
}
|
||||
|
||||
let Baz = () => {}
|
||||
>Baz : Symbol(Baz, Decl(errorSpanForUnclosedJsxTag.tsx, 6, 3))
|
||||
|
||||
let x = < Foo.Bar >Hello
|
||||
>x : Symbol(x, Decl(errorSpanForUnclosedJsxTag.tsx, 8, 3))
|
||||
>Foo.Bar : Symbol(Bar, Decl(errorSpanForUnclosedJsxTag.tsx, 2, 11))
|
||||
>Foo : Symbol(Foo, Decl(errorSpanForUnclosedJsxTag.tsx, 2, 3))
|
||||
>Bar : Symbol(Bar, Decl(errorSpanForUnclosedJsxTag.tsx, 2, 11))
|
||||
|
||||
let y = < Baz >Hello
|
||||
>Baz : Symbol(Baz, Decl(errorSpanForUnclosedJsxTag.tsx, 6, 3))
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
=== tests/cases/compiler/errorSpanForUnclosedJsxTag.tsx ===
|
||||
declare const React: any
|
||||
>React : any
|
||||
|
||||
let Foo = {
|
||||
>Foo : { Bar(): void; }
|
||||
>{ Bar() {}} : { Bar(): void; }
|
||||
|
||||
Bar() {}
|
||||
>Bar : () => void
|
||||
}
|
||||
|
||||
let Baz = () => {}
|
||||
>Baz : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
let x = < Foo.Bar >Hello
|
||||
>x : any
|
||||
>< Foo.Bar >Hellolet y = < Baz >Hello : any
|
||||
>Foo.Bar : () => void
|
||||
>Foo : { Bar(): void; }
|
||||
>Bar : () => void
|
||||
|
||||
let y = < Baz >Hello
|
||||
>< Baz >Hello : any
|
||||
>Baz : () => void
|
||||
> : any
|
||||
> : any
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// @jsx: react
|
||||
declare const React: any
|
||||
|
||||
let Foo = {
|
||||
Bar() {}
|
||||
}
|
||||
|
||||
let Baz = () => {}
|
||||
|
||||
let x = < Foo.Bar >Hello
|
||||
|
||||
let y = < Baz >Hello
|
||||
Reference in New Issue
Block a user