From a617ca1b8a16e60d6bcacd3030f2ec56bc3c351a Mon Sep 17 00:00:00 2001
From: Tan Li Hau
Date: Wed, 24 Jun 2020 17:36:31 +0800
Subject: [PATCH] better error message for unclose tag due to autoclosing
---
src/compiler/parse/index.ts | 7 +++++++
src/compiler/parse/state/tag.ts | 19 ++++++++++++++++++-
.../error.json | 10 ++++++++++
.../input.svelte | 5 +++++
.../error.json | 10 ++++++++++
.../input.svelte | 3 +++
6 files changed, 53 insertions(+), 1 deletion(-)
create mode 100644 test/parser/samples/error-unmatched-closing-tag-autoclose-2/error.json
create mode 100644 test/parser/samples/error-unmatched-closing-tag-autoclose-2/input.svelte
create mode 100644 test/parser/samples/error-unmatched-closing-tag-autoclose/error.json
create mode 100644 test/parser/samples/error-unmatched-closing-tag-autoclose/input.svelte
diff --git a/src/compiler/parse/index.ts b/src/compiler/parse/index.ts
index a809eeebeb..b10bab35f3 100644
--- a/src/compiler/parse/index.ts
+++ b/src/compiler/parse/index.ts
@@ -8,6 +8,12 @@ import error from '../utils/error';
type ParserState = (parser: Parser) => (ParserState | void);
+interface LastAutoCloseTag {
+ tag: string;
+ reason: string;
+ depth: number;
+}
+
export class Parser {
readonly template: string;
readonly filename?: string;
@@ -20,6 +26,7 @@ export class Parser {
css: Style[] = [];
js: Script[] = [];
meta_tags = {};
+ last_auto_closed_tag?: LastAutoCloseTag;
constructor(template: string, options: ParserOptions) {
if (typeof template !== 'string') {
diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts
index ce8a0a9aa7..c04429ab91 100644
--- a/src/compiler/parse/state/tag.ts
+++ b/src/compiler/parse/state/tag.ts
@@ -133,11 +133,19 @@ export default function tag(parser: Parser) {
// close any elements that don't have their own closing tags, e.g.
while (parent.name !== name) {
- if (parent.type !== 'Element')
+ if (parent.type !== 'Element') {
+ if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) {
+ parser.error({
+ code: `invalid-closing-tag`,
+ message: `<${parser.last_auto_closed_tag.tag}> cannot have child element <${parser.last_auto_closed_tag.reason}>`,
+ }, start);
+ }
+
parser.error({
code: `invalid-closing-tag`,
message: `${name}> attempted to close an element that was not open`
}, start);
+ }
parent.end = start;
parser.stack.pop();
@@ -148,10 +156,19 @@ export default function tag(parser: Parser) {
parent.end = parser.index;
parser.stack.pop();
+ if (parser.last_auto_closed_tag && parser.stack.length < parser.last_auto_closed_tag.depth) {
+ parser.last_auto_closed_tag = null;
+ }
+
return;
} else if (closing_tag_omitted(parent.name, name)) {
parent.end = start;
parser.stack.pop();
+ parser.last_auto_closed_tag ={
+ tag: parent.name,
+ reason: name,
+ depth: parser.stack.length,
+ };
}
const unique_names: Set = new Set();
diff --git a/test/parser/samples/error-unmatched-closing-tag-autoclose-2/error.json b/test/parser/samples/error-unmatched-closing-tag-autoclose-2/error.json
new file mode 100644
index 0000000000..d24296bd96
--- /dev/null
+++ b/test/parser/samples/error-unmatched-closing-tag-autoclose-2/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "invalid-closing-tag",
+ "message": "
attempted to close an element that was not open",
+ "pos": 38,
+ "start": {
+ "character": 38,
+ "column": 0,
+ "line": 5
+ }
+}
diff --git a/test/parser/samples/error-unmatched-closing-tag-autoclose-2/input.svelte b/test/parser/samples/error-unmatched-closing-tag-autoclose-2/input.svelte
new file mode 100644
index 0000000000..5182577921
--- /dev/null
+++ b/test/parser/samples/error-unmatched-closing-tag-autoclose-2/input.svelte
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/test/parser/samples/error-unmatched-closing-tag-autoclose/error.json b/test/parser/samples/error-unmatched-closing-tag-autoclose/error.json
new file mode 100644
index 0000000000..cfd7fd8aa8
--- /dev/null
+++ b/test/parser/samples/error-unmatched-closing-tag-autoclose/error.json
@@ -0,0 +1,10 @@
+{
+ "code": "invalid-closing-tag",
+ "message": " cannot have child element
",
+ "pos": 24,
+ "start": {
+ "character": 24,
+ "column": 0,
+ "line": 3
+ }
+}
diff --git a/test/parser/samples/error-unmatched-closing-tag-autoclose/input.svelte b/test/parser/samples/error-unmatched-closing-tag-autoclose/input.svelte
new file mode 100644
index 0000000000..0bfd609736
--- /dev/null
+++ b/test/parser/samples/error-unmatched-closing-tag-autoclose/input.svelte
@@ -0,0 +1,3 @@
+
+
pre tag
+
\ No newline at end of file