mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #6291 from RyanCavanaugh/fix6280
Issue correct errors for missing JSX closing tags
This commit is contained in:
+2
-21
@@ -7954,31 +7954,12 @@ namespace ts {
|
||||
return jsxElementType || anyType;
|
||||
}
|
||||
|
||||
function tagNamesAreEquivalent(lhs: EntityName, rhs: EntityName): boolean {
|
||||
if (lhs.kind !== rhs.kind) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lhs.kind === SyntaxKind.Identifier) {
|
||||
return (<Identifier>lhs).text === (<Identifier>rhs).text;
|
||||
}
|
||||
|
||||
return (<QualifiedName>lhs).right.text === (<QualifiedName>rhs).right.text &&
|
||||
tagNamesAreEquivalent((<QualifiedName>lhs).left, (<QualifiedName>rhs).left);
|
||||
}
|
||||
|
||||
function checkJsxElement(node: JsxElement) {
|
||||
// Check attributes
|
||||
checkJsxOpeningLikeElement(node.openingElement);
|
||||
|
||||
// Check that the closing tag matches
|
||||
if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) {
|
||||
error(node.closingElement, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNode(node.openingElement.tagName));
|
||||
}
|
||||
else {
|
||||
// Perform resolution on the closing tag so that rename/go to definition/etc work
|
||||
getJsxElementTagSymbol(node.closingElement);
|
||||
}
|
||||
// Perform resolution on the closing tag so that rename/go to definition/etc work
|
||||
getJsxElementTagSymbol(node.closingElement);
|
||||
|
||||
// Check children
|
||||
for (const child of node.children) {
|
||||
|
||||
@@ -2586,5 +2586,9 @@
|
||||
"A type assertion expression is not allowed in the left-hand side of an exponentiation expression. Consider enclosing the expression in parentheses.": {
|
||||
"category": "Error",
|
||||
"code": 17007
|
||||
},
|
||||
"JSX element '{0}' has no corresponding closing tag.": {
|
||||
"category": "Error",
|
||||
"code": 17008
|
||||
}
|
||||
}
|
||||
|
||||
+23
-1
@@ -3497,6 +3497,20 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function tagNamesAreEquivalent(lhs: EntityName, rhs: EntityName): boolean {
|
||||
if (lhs.kind !== rhs.kind) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lhs.kind === SyntaxKind.Identifier) {
|
||||
return (<Identifier>lhs).text === (<Identifier>rhs).text;
|
||||
}
|
||||
|
||||
return (<QualifiedName>lhs).right.text === (<QualifiedName>rhs).right.text &&
|
||||
tagNamesAreEquivalent((<QualifiedName>lhs).left, (<QualifiedName>rhs).left);
|
||||
}
|
||||
|
||||
|
||||
function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement {
|
||||
const opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext);
|
||||
let result: JsxElement | JsxSelfClosingElement;
|
||||
@@ -3506,6 +3520,11 @@ namespace ts {
|
||||
|
||||
node.children = parseJsxChildren(node.openingElement.tagName);
|
||||
node.closingElement = parseJsxClosingElement(inExpressionContext);
|
||||
|
||||
if (!tagNamesAreEquivalent(node.openingElement.tagName, node.closingElement.tagName)) {
|
||||
parseErrorAtPosition(node.closingElement.pos, node.closingElement.end - node.closingElement.pos, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, node.openingElement.tagName));
|
||||
}
|
||||
|
||||
result = finishNode(node);
|
||||
}
|
||||
else {
|
||||
@@ -3565,10 +3584,13 @@ namespace ts {
|
||||
while (true) {
|
||||
token = scanner.reScanJsxToken();
|
||||
if (token === SyntaxKind.LessThanSlashToken) {
|
||||
// Closing tag
|
||||
break;
|
||||
}
|
||||
else if (token === SyntaxKind.EndOfFileToken) {
|
||||
parseErrorAtCurrentToken(Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, openingTagName));
|
||||
// If we hit EOF, issue the error at the tag that lacks the closing element
|
||||
// rather than at the end of the file (which is useless)
|
||||
parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName));
|
||||
break;
|
||||
}
|
||||
result.push(parseJsxChild());
|
||||
|
||||
Reference in New Issue
Block a user