From ca94766ee37b0c25faaa2ea6309dc2b890cfff98 Mon Sep 17 00:00:00 2001 From: Skn0tt Date: Tue, 12 May 2026 11:06:07 +0200 Subject: [PATCH] Highlight using / await using declarations in JS & TS Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/languages/javascript.js | 5 ++ .../languages/javascript/keyword_feature.test | 88 +++++++++++++++++++ .../languages/typescript/keyword_feature.test | 88 +++++++++++++++++++ 3 files changed, 181 insertions(+) diff --git a/src/languages/javascript.js b/src/languages/javascript.js index 737edae8b6..35712fd724 100644 --- a/src/languages/javascript.js +++ b/src/languages/javascript.js @@ -29,6 +29,11 @@ export default { }, ], 'keyword': [ + { + pattern: + /(^|[^.]|\.\.\.\s*)\busing(?=\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*(?:=(?!=)|\bof\b))/, + lookbehind: true, + }, { pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|export|from(?=\s*(?:['"]|$))|import)\b/, diff --git a/tests/languages/javascript/keyword_feature.test b/tests/languages/javascript/keyword_feature.test index b303733569..40de138bad 100644 --- a/tests/languages/javascript/keyword_feature.test +++ b/tests/languages/javascript/keyword_feature.test @@ -53,6 +53,11 @@ async (a,b,c) => {} import {} from "foo" import {} from 'foo' class { get foo(){} set baz(){} get [value](){} } +using file = openFile(); +await using conn = getConn(); +using x = a, y = b; +for (using x of arr) {} +for (await using y of arr) {} // import assertion import json from "./foo.json" assert { type: "json" }; @@ -60,6 +65,11 @@ import json from "./foo.json" assert { type: "json" }; // variables, not keywords const { async, from, to } = bar; +const using = 1; +obj.using; +using(); +using {x} = obj; +import using from "foo"; promise.catch(foo).finally(bar); assert.equal(foo, bar); @@ -199,6 +209,54 @@ assert.equal(foo, bar); ["punctuation", "}"], ["punctuation", "}"], + ["keyword", "using"], + " file ", + ["operator", "="], + ["function", "openFile"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "await"], + ["keyword", "using"], + " conn ", + ["operator", "="], + ["function", "getConn"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "using"], + " x ", + ["operator", "="], + " a", + ["punctuation", ","], + " y ", + ["operator", "="], + " b", + ["punctuation", ";"], + + ["keyword", "for"], + ["punctuation", "("], + ["keyword", "using"], + " x ", + ["keyword", "of"], + " arr", + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "for"], + ["punctuation", "("], + ["keyword", "await"], + ["keyword", "using"], + " y ", + ["keyword", "of"], + " arr", + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + ["comment", "// import assertion"], ["keyword", "import"], @@ -227,6 +285,36 @@ assert.equal(foo, bar); " bar", ["punctuation", ";"], + ["keyword", "const"], + " using ", + ["operator", "="], + ["number", "1"], + ["punctuation", ";"], + + "\r\nobj", + ["punctuation", "."], + "using", + ["punctuation", ";"], + + ["function", "using"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + "\r\nusing ", + ["punctuation", "{"], + "x", + ["punctuation", "}"], + ["operator", "="], + " obj", + ["punctuation", ";"], + + ["keyword", "import"], + " using ", + ["keyword", "from"], + ["string", "\"foo\""], + ["punctuation", ";"], + "\r\npromise", ["punctuation", "."], ["function", "catch"], diff --git a/tests/languages/typescript/keyword_feature.test b/tests/languages/typescript/keyword_feature.test index 1456df034e..d6be977768 100644 --- a/tests/languages/typescript/keyword_feature.test +++ b/tests/languages/typescript/keyword_feature.test @@ -55,10 +55,20 @@ async (a,b,c) => {} import {} from "foo" import {} from 'foo' class { get foo(){} set baz(){} get [value](){} } +using file = openFile(); +await using conn = getConn(); +using x = a, y = b; +for (using x of arr) {} +for (await using y of arr) {} // variables, not keywords const { async, from, to } = bar; +const using = 1; +obj.using; +using(); +using {x} = obj; +import using from "foo"; promise.catch(foo).finally(bar); // TypeScript keywords @@ -220,6 +230,54 @@ import type *, {} ["punctuation", "}"], ["punctuation", "}"], + ["keyword", "using"], + " file ", + ["operator", "="], + ["function", "openFile"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "await"], + ["keyword", "using"], + " conn ", + ["operator", "="], + ["function", "getConn"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "using"], + " x ", + ["operator", "="], + " a", + ["punctuation", ","], + " y ", + ["operator", "="], + " b", + ["punctuation", ";"], + + ["keyword", "for"], + ["punctuation", "("], + ["keyword", "using"], + " x ", + ["keyword", "of"], + " arr", + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["keyword", "for"], + ["punctuation", "("], + ["keyword", "await"], + ["keyword", "using"], + " y ", + ["keyword", "of"], + " arr", + ["punctuation", ")"], + ["punctuation", "{"], + ["punctuation", "}"], + ["comment", "// variables, not keywords"], ["keyword", "const"], @@ -234,6 +292,36 @@ import type *, {} " bar", ["punctuation", ";"], + ["keyword", "const"], + " using ", + ["operator", "="], + ["number", "1"], + ["punctuation", ";"], + + "\r\nobj", + ["punctuation", "."], + "using", + ["punctuation", ";"], + + ["function", "using"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + "\r\nusing ", + ["punctuation", "{"], + "x", + ["punctuation", "}"], + ["operator", "="], + " obj", + ["punctuation", ";"], + + ["keyword", "import"], + " using ", + ["keyword", "from"], + ["string", "\"foo\""], + ["punctuation", ";"], + "\r\npromise", ["punctuation", "."], ["function", "catch"],