From f6c0638fcec361dbbbf85d83471b30d03a5fca6a Mon Sep 17 00:00:00 2001 From: TheAfroOfDoom Date: Thu, 23 May 2024 22:18:55 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A5=85=20Add=20parse=20error=20for=20line?= =?UTF-8?q?=20continuation=20at=20end=20of=20file=20-=20it=20doesn't=20cou?= =?UTF-8?q?nt=20as=20end=20of=20file=20iff=20there=20is=20any=20content=20?= =?UTF-8?q?after=20the=20newline=20after=20the=20backslash=20(including=20?= =?UTF-8?q?spaces),=20so=20catch=20that=20in=20an=20explicit=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/test-out/parser/util.spec.js | 76 +++++++++++++++++++ packages/core/src/parser/util.ts | 17 ++++- packages/core/test/parser/util.spec.ts | 3 + packages/locales/src/locales/en.json | 1 + 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/__snapshots__/packages/core/test-out/parser/util.spec.js b/__snapshots__/packages/core/test-out/parser/util.spec.js index bdd771064..55a444c2f 100644 --- a/__snapshots__/packages/core/test-out/parser/util.spec.js +++ b/__snapshots__/packages/core/test-out/parser/util.spec.js @@ -117,6 +117,26 @@ exports['concatOnTrailingBackslash() Parse "true↓" 1'] = { "errors": [] } +exports['concatOnTrailingBackslash() Parse "tru⧵ ↓ " 1'] = { + "node": { + "type": "boolean", + "range": { + "start": 0, + "end": 0 + } + }, + "errors": [ + { + "range": { + "start": 0, + "end": 0 + }, + "message": "Expected “false” or “true”", + "severity": 3 + } + ] +} + exports['concatOnTrailingBackslash() Parse "tru⧵ ↓ e" 1'] = { "node": { "type": "boolean", @@ -141,6 +161,34 @@ exports['concatOnTrailingBackslash() Parse "tru⧵ ↓ ⧵↓ e" 1'] = { "errors": [] } +exports['concatOnTrailingBackslash() Parse "tru⧵ ↓" 1'] = { + "node": { + "type": "boolean", + "range": { + "start": 0, + "end": 0 + } + }, + "errors": [ + { + "range": { + "start": 3, + "end": 6 + }, + "message": "A line continuation cannot be the end of the file", + "severity": 3 + }, + { + "range": { + "start": 0, + "end": 0 + }, + "message": "Expected “false” or “true”", + "severity": 3 + } + ] +} + exports['concatOnTrailingBackslash() Parse "tru⧵ ↓e" 1'] = { "node": { "type": "boolean", @@ -153,6 +201,34 @@ exports['concatOnTrailingBackslash() Parse "tru⧵ ↓e" 1'] = { "errors": [] } +exports['concatOnTrailingBackslash() Parse "tru⧵" 1'] = { + "node": { + "type": "boolean", + "range": { + "start": 0, + "end": 0 + } + }, + "errors": [ + { + "range": { + "start": 3, + "end": 4 + }, + "message": "A line continuation cannot be the end of the file", + "severity": 3 + }, + { + "range": { + "start": 0, + "end": 0 + }, + "message": "Expected “false” or “true”", + "severity": 3 + } + ] +} + exports['concatOnTrailingBackslash() Parse "tru⧵e ⧵ ↓ e" 1'] = { "node": { "type": "boolean", diff --git a/packages/core/src/parser/util.ts b/packages/core/src/parser/util.ts index ed87eb0c0..6a3bca014 100644 --- a/packages/core/src/parser/util.ts +++ b/packages/core/src/parser/util.ts @@ -1,4 +1,5 @@ -import type { AstNode } from '../node/index.js' +import { localize } from '@spyglassmc/locales' +import type { AstNode, ErrorNode } from '../node/index.js' import { SequenceUtil, SequenceUtilDiscriminator } from '../node/index.js' import type { ParserContext } from '../service/index.js' import { ErrorReporter } from '../service/index.js' @@ -544,6 +545,20 @@ export function concatOnTrailingBackslash( // next line's first non-whitespace character const from = src.getCharRange() src.nextLine() + + // Minecraft raises a `Line continuation at end of file` if a backslash + // (+ optional whitespace to the next line) is right before the end of the file + if (!src.canRead()) { + const ans: ErrorNode = { + type: 'error', + range: Range.span(from, src), + } + ctx.err.report( + localize('mcfunction.parser.line-continuation-end-of-file'), + ans, + ) + } + src.skipSpace() const to = src.getCharRange(-1) indexMap.push({ diff --git a/packages/core/test/parser/util.spec.ts b/packages/core/test/parser/util.spec.ts index 8cac53539..bb3d6b99c 100644 --- a/packages/core/test/parser/util.spec.ts +++ b/packages/core/test/parser/util.spec.ts @@ -146,6 +146,9 @@ describe('concatOnTrailingBackslash()', () => { { content: 'tru\\ \n \\\n e' }, { content: 'tru\\e \\ \n e' }, { content: 'tru\\\n\ne' }, + { content: 'tru\\' }, + { content: 'tru\\ \n' }, + { content: 'tru\\ \n ' }, ], }, ] diff --git a/packages/locales/src/locales/en.json b/packages/locales/src/locales/en.json index bed4277cf..20cc04879 100644 --- a/packages/locales/src/locales/en.json +++ b/packages/locales/src/locales/en.json @@ -75,6 +75,7 @@ "mcfunction.parser.entity-selector.player-name.too-long": "Player names cannot be longer than %0% characters", "mcfunction.parser.eoc-unexpected": "Expected more arguments", "mcfunction.parser.leading-slash": "a leading slash %0%", + "mcfunction.parser.line-continuation-end-of-file": "A line continuation cannot be the end of the file", "mcfunction.parser.no-permission": "Permission level %0% is required, which is higher than %1% defined in config", "mcfunction.parser.objective.too-long": "Objective names cannot be longer than %0% characters", "mcfunction.parser.range.min>max": "The minimum value %0% is larger than the maximum value %1%",