From efe7774c5dc90063232b4c561fea6d79f365feaf Mon Sep 17 00:00:00 2001 From: Jacob Bandes-Storch Date: Sat, 4 Nov 2023 21:58:02 -0700 Subject: [PATCH] Fix backreference and subpattern highlighting in VS Code Workaround for https://github.com/microsoft/vscode-textmate/issues/164 and similar issues --- Swift.tmLanguage.json | 113 ++++++++++--- Swift.tmLanguage.yaml | 102 ++++++++---- Syntaxes/Swift.tmLanguage | 328 ++++++++++++++++++++++++++------------ 3 files changed, 387 insertions(+), 156 deletions(-) diff --git a/Swift.tmLanguage.json b/Swift.tmLanguage.json index 7e1f855..fe255d1 100644 --- a/Swift.tmLanguage.json +++ b/Swift.tmLanguage.json @@ -2312,30 +2312,95 @@ }, "literals-regular-expression-literal-backreference-or-subpattern": { - "match": "(?x)\n(?\\\\g)(? (?[+-]?\\d+)(?:(?[+-])(?\\d+))? )\n| (?\\\\k\\{)(? (?(?!\\d)\\w+) (?:(?[+-])(?\\d+))? )(?\\})\n| (?\\\\g\\{)(?:\\g|\\g)(?\\})\n| (?\\\\[gk]<)(?:\\g|\\g)(?>)\n| (?\\\\[gk]')(?:\\g|\\g)(?')\n| (?\\(\\?(?:P[=>]|&))\\g(?\\))\n| (?\\(\\?R\\))\n| (?\\(\\?)\\g(?\\))\n| (?\\\\[1-9][0-9]+)", - "captures": { - "1": { "name": "constant.character.escape.backslash.regexp" }, - "3": { "name": "constant.numeric.integer.decimal.regexp" }, - "4": { "name": "keyword.operator.recursion-level.regexp" }, - "5": { "name": "constant.numeric.integer.decimal.regexp" }, - "6": { "name": "constant.character.escape.backslash.regexp" }, - "8": { "name": "variable.language.group-name.regexp" }, - "9": { "name": "keyword.operator.recursion-level.regexp" }, - "10": { "name": "constant.numeric.integer.decimal.regexp" }, - "11": { "name": "constant.character.escape.backslash.regexp" }, - "12": { "name": "constant.character.escape.backslash.regexp" }, - "13": { "name": "constant.character.escape.backslash.regexp" }, - "14": { "name": "constant.character.escape.backslash.regexp" }, - "15": { "name": "constant.character.escape.backslash.regexp" }, - "16": { "name": "constant.character.escape.backslash.regexp" }, - "17": { "name": "constant.character.escape.backslash.regexp" }, - "18": { "name": "keyword.other.back-reference.regexp" }, - "19": { "name": "keyword.other.back-reference.regexp" }, - "20": { "name": "keyword.other.back-reference.regexp" }, - "21": { "name": "keyword.other.back-reference.regexp" }, - "22": { "name": "keyword.other.back-reference.regexp" }, - "23": { "name": "keyword.other.back-reference.regexp" } - } + "comment": "These patterns are separated to work around issues like https://github.com/microsoft/vscode-textmate/issues/164", + "patterns": [ + { + "comment": "'\\g{' NamedOrNumberRef '}'", + "match": "(?x)(\\\\g\\{) (?: ((?!\\d)\\w+) (?:([+-])(\\d+))? | ([+-]?\\d+) (?:([+-])(\\d+))? ) (\\})", + "captures": { + "1": { "name": "constant.character.escape.backslash.regexp" }, + "2": { "name": "variable.language.group-name.regexp" }, + "3": { "name": "keyword.operator.recursion-level.regexp" }, + "4": { "name": "constant.numeric.integer.decimal.regexp" }, + "5": { "name": "constant.numeric.integer.decimal.regexp" }, + "6": { "name": "keyword.operator.recursion-level.regexp" }, + "7": { "name": "constant.numeric.integer.decimal.regexp" }, + "8": { "name": "constant.character.escape.backslash.regexp" } + } + }, + + { + "comment": "'\\g' NumberRef", + "match": "(?x)(\\\\g) ([+-]?\\d+) (?:([+-])(\\d+))?", + "captures": { + "1": { "name": "constant.character.escape.backslash.regexp" }, + "2": { "name": "constant.numeric.integer.decimal.regexp" }, + "3": { "name": "keyword.operator.recursion-level.regexp" }, + "4": { "name": "constant.numeric.integer.decimal.regexp" } + } + }, + + { + "comment": "'\\k<' NamedOrNumberRef '>'\n \"\\k'\" NamedOrNumberRef \"'\"\n '\\g<' NamedOrNumberRef '>'\n \"\\g'\" NamedOrNumberRef \"'\"", + "match": "(?x)(\\\\[gk](<)|\\\\[gk]') (?: ((?!\\d)\\w+) (?:([+-])(\\d+))? | ([+-]?\\d+) (?:([+-])(\\d+))? ) ((?(2)>|'))", + "captures": { + "1": { "name": "constant.character.escape.backslash.regexp" }, + "3": { "name": "variable.language.group-name.regexp" }, + "4": { "name": "keyword.operator.recursion-level.regexp" }, + "5": { "name": "constant.numeric.integer.decimal.regexp" }, + "6": { "name": "constant.numeric.integer.decimal.regexp" }, + "7": { "name": "keyword.operator.recursion-level.regexp" }, + "8": { "name": "constant.numeric.integer.decimal.regexp" }, + "9": { "name": "constant.character.escape.backslash.regexp" } + } + }, + + { + "comment": "'\\k{' NamedRef '}'", + "match": "(?x)(\\\\k\\{) ((?!\\d)\\w+) (?:([+-])(\\d+))? (\\})", + "captures": { + "1": { "name": "constant.character.escape.backslash.regexp" }, + "2": { "name": "variable.language.group-name.regexp" }, + "3": { "name": "keyword.operator.recursion-level.regexp" }, + "4": { "name": "constant.numeric.integer.decimal.regexp" }, + "5": { "name": "constant.character.escape.backslash.regexp" } + } + }, + + { + "name": "keyword.other.back-reference.regexp", + "match": "\\\\[1-9][0-9]+" + }, + + { + "comment": "'(?P=' NamedRef ')'", + "match": "(?x)(\\(\\?(?:P[=>]|&)) ((?!\\d)\\w+) (?:([+-])(\\d+))? (\\))", + "captures": { + "1": { "name": "keyword.other.back-reference.regexp" }, + "2": { "name": "variable.language.group-name.regexp" }, + "3": { "name": "keyword.operator.recursion-level.regexp" }, + "4": { "name": "constant.numeric.integer.decimal.regexp" }, + "5": { "name": "keyword.other.back-reference.regexp" } + } + }, + + { + "name": "keyword.other.back-reference.regexp", + "match": "\\(\\?R\\)" + }, + + { + "comment": "'(?' NumberRef ')'", + "match": "(?x)(\\(\\?) ([+-]?\\d+) (?:([+-])(\\d+))? (\\))", + "captures": { + "1": { "name": "keyword.other.back-reference.regexp" }, + "2": { "name": "constant.numeric.integer.decimal.regexp" }, + "3": { "name": "keyword.operator.recursion-level.regexp" }, + "4": { "name": "constant.numeric.integer.decimal.regexp" }, + "5": { "name": "keyword.other.back-reference.regexp" } + } + } + ] }, "literals-regular-expression-literal-backtracking-directive-or-global-matching-option": { diff --git a/Swift.tmLanguage.yaml b/Swift.tmLanguage.yaml index 8dadb7b..40668dd 100644 --- a/Swift.tmLanguage.yaml +++ b/Swift.tmLanguage.yaml @@ -1866,39 +1866,75 @@ repository: 13: { name: invalid.illegal.returns-not-allowed.regexp } literals-regular-expression-literal-backreference-or-subpattern: - match: |- - (?x) - (?\\g)(? (?[+-]?\d+)(?:(?[+-])(?\d+))? ) - | (?\\k\{)(? (?(?!\d)\w+) (?:(?[+-])(?\d+))? )(?\}) - | (?\\g\{)(?:\g|\g)(?\}) - | (?\\[gk]<)(?:\g|\g)(?>) - | (?\\[gk]')(?:\g|\g)(?') - | (?\(\?(?:P[=>]|&))\g(?\)) - | (?\(\?R\)) - | (?\(\?)\g(?\)) - | (?\\[1-9][0-9]+) - captures: - 1: { name: constant.character.escape.backslash.regexp } - 3: { name: constant.numeric.integer.decimal.regexp } - 4: { name: keyword.operator.recursion-level.regexp } - 5: { name: constant.numeric.integer.decimal.regexp } - 6: { name: constant.character.escape.backslash.regexp } - 8: { name: variable.language.group-name.regexp } - 9: { name: keyword.operator.recursion-level.regexp } - 10: { name: constant.numeric.integer.decimal.regexp } - 11: { name: constant.character.escape.backslash.regexp } - 12: { name: constant.character.escape.backslash.regexp } - 13: { name: constant.character.escape.backslash.regexp } - 14: { name: constant.character.escape.backslash.regexp } - 15: { name: constant.character.escape.backslash.regexp } - 16: { name: constant.character.escape.backslash.regexp } - 17: { name: constant.character.escape.backslash.regexp } - 18: { name: keyword.other.back-reference.regexp } - 19: { name: keyword.other.back-reference.regexp } - 20: { name: keyword.other.back-reference.regexp } - 21: { name: keyword.other.back-reference.regexp } - 22: { name: keyword.other.back-reference.regexp } - 23: { name: keyword.other.back-reference.regexp } + # These patterns are separated to work around issues like https://github.com/microsoft/vscode-textmate/issues/164 + patterns: + # '\g{' NamedOrNumberRef '}' + - match: '(?x)(\\g\{) (?: ((?!\d)\w+) (?:([+-])(\d+))? | ([+-]?\d+) (?:([+-])(\d+))? ) (\})' + captures: + 1: { name: constant.character.escape.backslash.regexp } + 2: { name: variable.language.group-name.regexp } + 3: { name: keyword.operator.recursion-level.regexp } + 4: { name: constant.numeric.integer.decimal.regexp } + 5: { name: constant.numeric.integer.decimal.regexp } + 6: { name: keyword.operator.recursion-level.regexp } + 7: { name: constant.numeric.integer.decimal.regexp } + 8: { name: constant.character.escape.backslash.regexp } + + # '\g' NumberRef + - match: (?x)(\\g) ([+-]?\d+) (?:([+-])(\d+))? + captures: + 1: { name: constant.character.escape.backslash.regexp } + 2: { name: constant.numeric.integer.decimal.regexp } + 3: { name: keyword.operator.recursion-level.regexp } + 4: { name: constant.numeric.integer.decimal.regexp } + + # '\k<' NamedOrNumberRef '>' + # "\k'" NamedOrNumberRef "'" + # '\g<' NamedOrNumberRef '>' + # "\g'" NamedOrNumberRef "'" + - match: '(?x)(\\[gk](<)|\\[gk]'') (?: ((?!\d)\w+) (?:([+-])(\d+))? | ([+-]?\d+) (?:([+-])(\d+))? ) ((?(2)>|''))' + captures: + 1: { name: constant.character.escape.backslash.regexp } + 3: { name: variable.language.group-name.regexp } + 4: { name: keyword.operator.recursion-level.regexp } + 5: { name: constant.numeric.integer.decimal.regexp } + 6: { name: constant.numeric.integer.decimal.regexp } + 7: { name: keyword.operator.recursion-level.regexp } + 8: { name: constant.numeric.integer.decimal.regexp } + 9: { name: constant.character.escape.backslash.regexp } + + # '\k{' NamedRef '}' + - match: (?x)(\\k\{) ((?!\d)\w+) (?:([+-])(\d+))? (\}) + captures: + 1: { name: constant.character.escape.backslash.regexp } + 2: { name: variable.language.group-name.regexp } + 3: { name: keyword.operator.recursion-level.regexp } + 4: { name: constant.numeric.integer.decimal.regexp } + 5: { name: constant.character.escape.backslash.regexp } + + - name: keyword.other.back-reference.regexp + match: \\[1-9][0-9]+ + + # '(?P=' NamedRef ')' + - match: (?x)(\(\?(?:P[=>]|&)) ((?!\d)\w+) (?:([+-])(\d+))? (\)) + captures: + 1: { name: keyword.other.back-reference.regexp } + 2: { name: variable.language.group-name.regexp } + 3: { name: keyword.operator.recursion-level.regexp } + 4: { name: constant.numeric.integer.decimal.regexp } + 5: { name: keyword.other.back-reference.regexp } + + - name: keyword.other.back-reference.regexp + match: \(\?R\) + + # '(?' NumberRef ')' + - match: (?x)(\(\?) ([+-]?\d+) (?:([+-])(\d+))? (\)) + captures: + 1: { name: keyword.other.back-reference.regexp } + 2: { name: constant.numeric.integer.decimal.regexp } + 3: { name: keyword.operator.recursion-level.regexp } + 4: { name: constant.numeric.integer.decimal.regexp } + 5: { name: keyword.other.back-reference.regexp } literals-regular-expression-literal-backtracking-directive-or-global-matching-option: match: |- diff --git a/Syntaxes/Swift.tmLanguage b/Syntaxes/Swift.tmLanguage index a1dbee2..842ea21 100644 --- a/Syntaxes/Swift.tmLanguage +++ b/Syntaxes/Swift.tmLanguage @@ -5019,125 +5019,255 @@ literals-regular-expression-literal-backreference-or-subpattern - match - (?x) -(?<esc>\\g)(?<NumberRef> (?<num>[+-]?\d+)(?:(?<op>[+-])(?<num>\d+))? ) -| (?<esc>\\k\{)(?<NamedRef> (?<name>(?!\d)\w+) (?:(?<op>[+-])(?<num>\d+))? )(?<esc>\}) -| (?<esc>\\g\{)(?:\g<NamedRef>|\g<NumberRef>)(?<esc>\}) -| (?<esc>\\[gk]<)(?:\g<NamedRef>|\g<NumberRef>)(?<esc>>) -| (?<esc>\\[gk]')(?:\g<NamedRef>|\g<NumberRef>)(?<esc>') -| (?<keyw>\(\?(?:P[=>]|&))\g<NamedRef>(?<keyw>\)) -| (?<keyw>\(\?R\)) -| (?<keyw>\(\?)\g<NumberRef>(?<keyw>\)) -| (?<keyw>\\[1-9][0-9]+) - captures - - 1 - - name - constant.character.escape.backslash.regexp - - 3 - - name - constant.numeric.integer.decimal.regexp - - 4 - - name - keyword.operator.recursion-level.regexp - - 5 - - name - constant.numeric.integer.decimal.regexp - - 6 - - name - constant.character.escape.backslash.regexp - - 8 - - name - variable.language.group-name.regexp - - 9 - - name - keyword.operator.recursion-level.regexp - - 10 - - name - constant.numeric.integer.decimal.regexp - - 11 - - name - constant.character.escape.backslash.regexp - - 12 - - name - constant.character.escape.backslash.regexp - - 13 - - name - constant.character.escape.backslash.regexp - - 14 - - name - constant.character.escape.backslash.regexp - - 15 - - name - constant.character.escape.backslash.regexp - - 16 + comment + These patterns are separated to work around issues like https://github.com/microsoft/vscode-textmate/issues/164 + patterns + - name - constant.character.escape.backslash.regexp + comment + '\g{' NamedOrNumberRef '}' + match + (?x)(\\g\{) (?: ((?!\d)\w+) (?:([+-])(\d+))? | ([+-]?\d+) (?:([+-])(\d+))? ) (\}) + captures + + 1 + + name + constant.character.escape.backslash.regexp + + 2 + + name + variable.language.group-name.regexp + + 3 + + name + keyword.operator.recursion-level.regexp + + 4 + + name + constant.numeric.integer.decimal.regexp + + 5 + + name + constant.numeric.integer.decimal.regexp + + 6 + + name + keyword.operator.recursion-level.regexp + + 7 + + name + constant.numeric.integer.decimal.regexp + + 8 + + name + constant.character.escape.backslash.regexp + + - 17 - name - constant.character.escape.backslash.regexp + comment + '\g' NumberRef + match + (?x)(\\g) ([+-]?\d+) (?:([+-])(\d+))? + captures + + 1 + + name + constant.character.escape.backslash.regexp + + 2 + + name + constant.numeric.integer.decimal.regexp + + 3 + + name + keyword.operator.recursion-level.regexp + + 4 + + name + constant.numeric.integer.decimal.regexp + + - 18 - name - keyword.other.back-reference.regexp + comment + '\k<' NamedOrNumberRef '>' + "\k'" NamedOrNumberRef "'" + '\g<' NamedOrNumberRef '>' + "\g'" NamedOrNumberRef "'" + match + (?x)(\\[gk](<)|\\[gk]') (?: ((?!\d)\w+) (?:([+-])(\d+))? | ([+-]?\d+) (?:([+-])(\d+))? ) ((?(2)>|')) + captures + + 1 + + name + constant.character.escape.backslash.regexp + + 3 + + name + variable.language.group-name.regexp + + 4 + + name + keyword.operator.recursion-level.regexp + + 5 + + name + constant.numeric.integer.decimal.regexp + + 6 + + name + constant.numeric.integer.decimal.regexp + + 7 + + name + keyword.operator.recursion-level.regexp + + 8 + + name + constant.numeric.integer.decimal.regexp + + 9 + + name + constant.character.escape.backslash.regexp + + - 19 - name - keyword.other.back-reference.regexp + comment + '\k{' NamedRef '}' + match + (?x)(\\k\{) ((?!\d)\w+) (?:([+-])(\d+))? (\}) + captures + + 1 + + name + constant.character.escape.backslash.regexp + + 2 + + name + variable.language.group-name.regexp + + 3 + + name + keyword.operator.recursion-level.regexp + + 4 + + name + constant.numeric.integer.decimal.regexp + + 5 + + name + constant.character.escape.backslash.regexp + + - 20 name keyword.other.back-reference.regexp + match + \\[1-9][0-9]+ - 21 - name - keyword.other.back-reference.regexp + comment + '(?P=' NamedRef ')' + match + (?x)(\(\?(?:P[=>]|&)) ((?!\d)\w+) (?:([+-])(\d+))? (\)) + captures + + 1 + + name + keyword.other.back-reference.regexp + + 2 + + name + variable.language.group-name.regexp + + 3 + + name + keyword.operator.recursion-level.regexp + + 4 + + name + constant.numeric.integer.decimal.regexp + + 5 + + name + keyword.other.back-reference.regexp + + - 22 name keyword.other.back-reference.regexp + match + \(\?R\) - 23 - name - keyword.other.back-reference.regexp + comment + '(?' NumberRef ')' + match + (?x)(\(\?) ([+-]?\d+) (?:([+-])(\d+))? (\)) + captures + + 1 + + name + keyword.other.back-reference.regexp + + 2 + + name + constant.numeric.integer.decimal.regexp + + 3 + + name + keyword.operator.recursion-level.regexp + + 4 + + name + constant.numeric.integer.decimal.regexp + + 5 + + name + keyword.other.back-reference.regexp + + - + literals-regular-expression-literal-backtracking-directive-or-global-matching-option