From fce63f6dbf4d1de8fdabde6531f536529c41ab03 Mon Sep 17 00:00:00 2001 From: rootile Date: Mon, 15 Jun 2026 21:33:37 +0200 Subject: [PATCH] parser: improve error message for ill-defined escape sequences fixes #1169 Change-Id: Ic93e0cb5442b717964de3ae9eb22f4cd48e4ad0a --- lix/libexpr/parser/state.hh | 14 ++++++++++++-- .../lang/string-indented/eval-okay-escapes.err.exp | 10 +++++----- .../lang/string/eval-okay-escapes.err.exp | 8 ++++---- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lix/libexpr/parser/state.hh b/lix/libexpr/parser/state.hh index fb038dfb9..65ebb7b34 100644 --- a/lix/libexpr/parser/state.hh +++ b/lix/libexpr/parser/state.hh @@ -133,14 +133,24 @@ inline void State::badEscapeFound(const PosIdx pos, char found, bool isIndented) { auto escape = std::string(isIndented ? "''\\" : "\\"); auto interpolEscape = std::string(isIndented ? "''${" : "\\${"); + auto backslashChar = std::string("\\") + found; + + HintFmt dedicatedInsert = isIndented + ? HintFmt("you can simply write it as %s in the string", backslashChar) + : HintFmt("you need to escape the %s itself: %s", escape, escape + escape + found); + HintFmt msg = HintFmt( - "%s is an ill-defined escape. You can drop the %s and simply write %s instead. " + "%s is an ill-defined escape sequence. In Nix, it simply means %s, therefore the %s is redundant and " + "should be removed. If the intent of the string was to mean %s instead (e.g. in a regex), %s. " "Use %s to silence this warning.", escape + found, - escape, found, + escape, + backslashChar, + Uncolored(dedicatedInsert.str()), "--extra-deprecated-features broken-string-escape" ); + /* Special case some common escapes to provide better messages */ if (found == '$' || found == '{') { /* Someone possibly tried to escape an interpolation but used the wrong sequence. diff --git a/tests/functional2/lang/string-indented/eval-okay-escapes.err.exp b/tests/functional2/lang/string-indented/eval-okay-escapes.err.exp index 89faf4f66..ee6b39737 100644 --- a/tests/functional2/lang/string-indented/eval-okay-escapes.err.exp +++ b/tests/functional2/lang/string-indented/eval-okay-escapes.err.exp @@ -1,10 +1,10 @@ -warning: ''\a is an ill-defined escape. You can drop the ''\ and simply write a instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: ''\a is an ill-defined escape sequence. In Nix, it simply means a, therefore the ''\ is redundant and should be removed. If the intent of the string was to mean \a instead (e.g. in a regex), you can simply write it as \a in the string. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:2:4: 1| '' 2| ''\a''\n | ^ 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t -warning: ''\f is an ill-defined escape. You can drop the ''\ and simply write f instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: ''\f is an ill-defined escape sequence. In Nix, it simply means f, therefore the ''\ is redundant and should be removed. If the intent of the string was to mean \f instead (e.g. in a regex), you can simply write it as \f in the string. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:3:4: 2| ''\a''\n 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t @@ -22,19 +22,19 @@ warning: ''\$ is an ill-defined escape. You can drop the ''\ and simply write $ 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t | ^ 4| ''\'''${"x"} -warning: ''\" is an ill-defined escape. You can drop the ''\ and simply write " instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: ''\" is an ill-defined escape sequence. In Nix, it simply means ", therefore the ''\ is redundant and should be removed. If the intent of the string was to mean \" instead (e.g. in a regex), you can simply write it as \" in the string. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:3:16: 2| ''\a''\n 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t | ^ 4| ''\'''${"x"} -warning: ''\v is an ill-defined escape. You can drop the ''\ and simply write v instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: ''\v is an ill-defined escape sequence. In Nix, it simply means v, therefore the ''\ is redundant and should be removed. If the intent of the string was to mean \v instead (e.g. in a regex), you can simply write it as \v in the string. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:3:28: 2| ''\a''\n 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t | ^ 4| ''\'''${"x"} -warning: ''\\ is an ill-defined escape. You can drop the ''\ and simply write \ instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: ''\\ is an ill-defined escape sequence. In Nix, it simply means \, therefore the ''\ is redundant and should be removed. If the intent of the string was to mean \\ instead (e.g. in a regex), you can simply write it as \\ in the string. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:3:32: 2| ''\a''\n 3| ''\f''\{''\$''\"''\'''\r''\v''\\''\t diff --git a/tests/functional2/lang/string/eval-okay-escapes.err.exp b/tests/functional2/lang/string/eval-okay-escapes.err.exp index 4655a6711..83d552e40 100644 --- a/tests/functional2/lang/string/eval-okay-escapes.err.exp +++ b/tests/functional2/lang/string/eval-okay-escapes.err.exp @@ -1,4 +1,4 @@ -warning: \a is an ill-defined escape. You can drop the \ and simply write a instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: \a is an ill-defined escape sequence. In Nix, it simply means a, therefore the \ is redundant and should be removed. If the intent of the string was to mean \a instead (e.g. in a regex), you need to escape the \ itself: \\a. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:1:3: 1| "\a\n\{\$\"\'\r\v\\\t | ^ @@ -8,17 +8,17 @@ warning: \{ is an ill-defined escape. You can drop the \ and simply write { inst 1| "\a\n\{\$\"\'\r\v\\\t | ^ 2| \f" -warning: \' is an ill-defined escape. You can drop the \ and simply write ' instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: \' is an ill-defined escape sequence. In Nix, it simply means ', therefore the \ is redundant and should be removed. If the intent of the string was to mean \' instead (e.g. in a regex), you need to escape the \ itself: \\'. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:1:13: 1| "\a\n\{\$\"\'\r\v\\\t | ^ 2| \f" -warning: \v is an ill-defined escape. You can drop the \ and simply write v instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: \v is an ill-defined escape sequence. In Nix, it simply means v, therefore the \ is redundant and should be removed. If the intent of the string was to mean \v instead (e.g. in a regex), you need to escape the \ itself: \\v. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:1:17: 1| "\a\n\{\$\"\'\r\v\\\t | ^ 2| \f" -warning: \f is an ill-defined escape. You can drop the \ and simply write f instead. Use --extra-deprecated-features broken-string-escape to silence this warning. +warning: \f is an ill-defined escape sequence. In Nix, it simply means f, therefore the \ is redundant and should be removed. If the intent of the string was to mean \f instead (e.g. in a regex), you need to escape the \ itself: \\f. Use --extra-deprecated-features broken-string-escape to silence this warning. at /pwd/in.nix:2:2: 1| "\a\n\{\$\"\'\r\v\\\t 2| \f"