diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index aae3ccb7297..d77dbbd2e0f 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -77,6 +77,23 @@ steps: yarn postinstall displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + env: + OSS_GITHUB_ID: "a5d3c261b032765a78de" + OSS_GITHUB_SECRET: $(oss-github-client-secret) + INSIDERS_GITHUB_ID: "31f02627809389d9f111" + INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret) + STABLE_GITHUB_ID: "baa8a44b5e861d918709" + STABLE_GITHUB_SECRET: $(stable-github-client-secret) + EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea" + EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret) + VSO_GITHUB_ID: "3d4be8f37a0325b5817d" + VSO_GITHUB_SECRET: $(vso-github-client-secret) + VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492" + VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) + VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" + VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) + GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" + GITHUB_APP_SECRET: $(github-app-client-secret) - script: | set -e diff --git a/build/azure-pipelines/linux/product-build-linux-multiarch.yml b/build/azure-pipelines/linux/product-build-linux-multiarch.yml index 68ae4ee8b67..066e42af3d0 100644 --- a/build/azure-pipelines/linux/product-build-linux-multiarch.yml +++ b/build/azure-pipelines/linux/product-build-linux-multiarch.yml @@ -86,6 +86,23 @@ steps: yarn postinstall displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + env: + OSS_GITHUB_ID: "a5d3c261b032765a78de" + OSS_GITHUB_SECRET: $(oss-github-client-secret) + INSIDERS_GITHUB_ID: "31f02627809389d9f111" + INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret) + STABLE_GITHUB_ID: "baa8a44b5e861d918709" + STABLE_GITHUB_SECRET: $(stable-github-client-secret) + EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea" + EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret) + VSO_GITHUB_ID: "3d4be8f37a0325b5817d" + VSO_GITHUB_SECRET: $(vso-github-client-secret) + VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492" + VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) + VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" + VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) + GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" + GITHUB_APP_SECRET: $(github-app-client-secret) - script: | set -e diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index cbe3bf051e6..119f80cd929 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -76,6 +76,23 @@ steps: yarn postinstall displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + env: + OSS_GITHUB_ID: "a5d3c261b032765a78de" + OSS_GITHUB_SECRET: $(oss-github-client-secret) + INSIDERS_GITHUB_ID: "31f02627809389d9f111" + INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret) + STABLE_GITHUB_ID: "baa8a44b5e861d918709" + STABLE_GITHUB_SECRET: $(stable-github-client-secret) + EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea" + EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret) + VSO_GITHUB_ID: "3d4be8f37a0325b5817d" + VSO_GITHUB_SECRET: $(vso-github-client-secret) + VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492" + VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) + VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" + VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) + GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" + GITHUB_APP_SECRET: $(github-app-client-secret) - script: | set -e diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index 48916189326..6c28724824d 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -92,6 +92,8 @@ steps: VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) + GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" + GITHUB_APP_SECRET: $(github-app-client-secret) # Mixin must run before optimize, because the CSS loader will # inline small SVGs diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 7a8a12aa280..20699bf9225 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -86,6 +86,23 @@ steps: exec { yarn postinstall } displayName: Run postinstall scripts condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) + env: + OSS_GITHUB_ID: "a5d3c261b032765a78de" + OSS_GITHUB_SECRET: $(oss-github-client-secret) + INSIDERS_GITHUB_ID: "31f02627809389d9f111" + INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret) + STABLE_GITHUB_ID: "baa8a44b5e861d918709" + STABLE_GITHUB_SECRET: $(stable-github-client-secret) + EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea" + EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret) + VSO_GITHUB_ID: "3d4be8f37a0325b5817d" + VSO_GITHUB_SECRET: $(vso-github-client-secret) + VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492" + VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret) + VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c" + VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret) + GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" + GITHUB_APP_SECRET: $(github-app-client-secret) - powershell: | . build/azure-pipelines/win32/exec.ps1 diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json index b2eddad5ebe..1a868959ca1 100644 --- a/build/builtInExtensions.json +++ b/build/builtInExtensions.json @@ -1,7 +1,7 @@ [ { "name": "ms-vscode.node-debug", - "version": "1.44.2", + "version": "1.44.3", "repo": "https://github.com/Microsoft/vscode-node-debug", "metadata": { "id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6", diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index df81f2c3908..8e560b96cb8 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -349,6 +349,10 @@ { "name": "vs/workbench/contrib/timeline", "project": "vscode-workbench" + }, + { + "name": "vs/workbench/services/authentication", + "project": "vscode-workbench" } ] } diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index eca72654382..cb88d37adef 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -23,7 +23,7 @@ if (majorYarnVersion < 1 || minorYarnVersion < 10) { err = true; } -if (!/yarn\.js$|yarnpkg$/.test(process.env['npm_execpath'])) { +if (!/yarn[\w-.]*\.js$|yarnpkg$/.test(process.env['npm_execpath'])) { console.error('\033[1;31m*** Please use yarn to install dependencies.\033[0;0m'); err = true; } diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 0defd3aee6f..f929c260fd5 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -96,6 +96,10 @@ "fileMatch": "%APP_SETTINGS_HOME%/snippets/*.json", "url": "vscode://schemas/snippets" }, + { + "fileMatch": "%APP_SETTINGS_HOME%/sync/snippets/preview/*.json", + "url": "vscode://schemas/snippets" + }, { "fileMatch": "**/*.code-snippets", "url": "vscode://schemas/global-snippets" diff --git a/extensions/cpp/cgmanifest.json b/extensions/cpp/cgmanifest.json index ec3db51a008..d1a66777a23 100644 --- a/extensions/cpp/cgmanifest.json +++ b/extensions/cpp/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "jeff-hykin/cpp-textmate-grammar", "repositoryUrl": "https://github.com/jeff-hykin/cpp-textmate-grammar", - "commitHash": "7d3fe7ab806374a3b11ddd8ac4f674cdff20a647" + "commitHash": "213d6b9941e6d0f6a7274306ef2a47ec8d93cc27" } }, "license": "MIT", - "version": "1.14.23", + "version": "1.14.26", "description": "The files syntaxes/c.json and syntaxes/c++.json were derived from https://github.com/atom/language-c which was originally converted from the C TextMate bundle https://github.com/textmate/c.tmbundle." }, { diff --git a/extensions/cpp/syntaxes/c.tmLanguage.json b/extensions/cpp/syntaxes/c.tmLanguage.json index acf62fab955..bac1ea275b8 100644 --- a/extensions/cpp/syntaxes/c.tmLanguage.json +++ b/extensions/cpp/syntaxes/c.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/85b9008b406cc9d3b1c9e779e94cc071116c8426", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/b23ed8d4bc4e1db4e7c7c2e8c4699c542c7c6cdf", "name": "C", "scopeName": "source.c", "patterns": [ @@ -1028,7 +1028,7 @@ } ] }, - "evalutation_context": { + "evaluation_context": { "patterns": [ { "include": "#function-call-innards" diff --git a/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json b/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json index a97fe923b8d..f1b9f06776c 100644 --- a/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json +++ b/extensions/cpp/syntaxes/cpp.embedded.macro.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/7d3fe7ab806374a3b11ddd8ac4f674cdff20a647", + "version": "https://github.com/jeff-hykin/cpp-textmate-grammar/commit/213d6b9941e6d0f6a7274306ef2a47ec8d93cc27", "name": "C++", "scopeName": "source.cpp.embedded.macro", "patterns": [ @@ -525,172 +525,22 @@ "name": "comment.block.cpp" }, "builtin_storage_type_initilizer": { - "begin": "((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()", + "begin": "(?:\\s)*+(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?(\\()", "end": "\\)|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", + "begin": "\\s*+((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?=(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?(\\()", "end": "\\)|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\{)", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\{)", "end": "\\}|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))~\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", + "begin": "((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))~\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?=(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?(::))?(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?(::))?(?:(?:\\s)+)?((?|\\?\\?>)(?:(?:\\s)+)?(;)|(;))|(?=[;>\\[\\]=]))|(?=(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:\\s)*+)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:\\s)*+)?(\\()", "end": "\\)|(?=(?))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\()", + "begin": "(?:(?:^|\\G|(?<=;|\\}))|(?<=>))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)(?:\\s)*+)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\()", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()|(?=(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))", + "match": "(?<=protected|virtual|private|public|,|:)(?:(?:\\s)+)?(?!(?:(?:(?:protected)|(?:private)|(?:public))|virtual))(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)?(?![\\w<:.]))", "captures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "10": {}, - "11": { - "name": "entity.name.scope-resolution.cpp" - }, - "12": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, - "13": {}, - "14": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "15": { + "9": {}, + "10": { "patterns": [ { "include": "source.cpp#inline_comment" } ] }, - "16": { + "11": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -5245,18 +4998,7 @@ } ] }, - "17": { - "name": "entity.name.type.cpp" - }, - "18": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "19": {} + "12": {} } } ] @@ -5811,7 +5553,7 @@ "include": "#attributes_context" }, { - "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<4>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<4>?)+>)(?:\\s)*+)?::)*\\s*+)(?:(?:\\s)+)?((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*)(operator)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*)(?:(?:((?:(?:delete\\[\\])|(?:delete)|(?:new\\[\\])|(?:<=>)|(?:<<=)|(?:new)|(?:>>=)|(?:\\->\\*)|(?:\\/=)|(?:%=)|(?:&=)|(?:>=)|(?:\\|=)|(?:\\+\\+)|(?:\\-\\-)|(?:\\(\\))|(?:\\[\\])|(?:\\->)|(?:\\+\\+)|(?:<<)|(?:>>)|(?:\\-\\-)|(?:<=)|(?:\\^=)|(?:==)|(?:!=)|(?:&&)|(?:\\|\\|)|(?:\\+=)|(?:\\-=)|(?:\\*=)|,|(?:\\+)|(?:\\-)|!|~|(?:\\*)|&|(?:\\*)|(?:\\/)|%|(?:\\+)|(?:\\-)|<|>|&|(?:\\^)|(?:\\|)|=))|((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\<|\\()", + "begin": "(?:(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)(operator)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)(?:(?:((?:(?:delete\\[\\])|(?:delete)|(?:new\\[\\])|(?:<=>)|(?:<<=)|(?:new)|(?:>>=)|(?:\\->\\*)|(?:\\/=)|(?:%=)|(?:&=)|(?:>=)|(?:\\|=)|(?:\\+\\+)|(?:\\-\\-)|(?:\\(\\))|(?:\\[\\])|(?:\\->)|(?:\\+\\+)|(?:<<)|(?:>>)|(?:\\-\\-)|(?:<=)|(?:\\^=)|(?:==)|(?:!=)|(?:&&)|(?:\\|\\|)|(?:\\+=)|(?:\\-=)|(?:\\*=)|,|(?:\\+)|(?:\\-)|!|~|(?:\\*)|&|(?:\\*)|(?:\\/)|%|(?:\\+)|(?:\\-)|<|>|&|(?:\\^)|(?:\\|)|=))|((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\<|\\()", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))|(?=(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", + "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:\\s)*+(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", "captures": { "1": { "patterns": [ @@ -7099,159 +6820,34 @@ ] }, "11": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "12": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "13": { - "name": "comment.block.cpp" - }, - "14": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "15": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "16": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "17": { - "name": "comment.block.cpp" - }, - "18": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "19": { "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" }, - "20": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "21": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "22": { - "name": "comment.block.cpp" - }, - "23": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "24": { + "12": { "name": "storage.type.cpp storage.type.built-in.cpp" }, - "25": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "26": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "27": { - "name": "comment.block.cpp" - }, - "28": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "29": { + "13": { "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" }, - "30": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "31": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "32": { - "name": "comment.block.cpp" - }, - "33": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "34": { + "14": { "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" }, - "35": { + "15": { "name": "entity.name.type.parameter.cpp" }, - "36": { + "16": { "patterns": [ { "include": "source.cpp#inline_comment" } ] }, - "37": { + "17": { "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" }, - "38": { + "18": { "name": "comment.block.cpp" }, - "39": { + "19": { "patterns": [ { "match": "\\*\\/", @@ -7541,7 +7137,7 @@ "include": "source.cpp#vararg_ellipses" }, { - "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", + "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:\\s)*+(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", "captures": { "1": { "patterns": [ @@ -7604,159 +7200,34 @@ ] }, "11": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "12": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "13": { - "name": "comment.block.cpp" - }, - "14": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "15": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "16": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "17": { - "name": "comment.block.cpp" - }, - "18": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "19": { "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" }, - "20": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "21": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "22": { - "name": "comment.block.cpp" - }, - "23": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "24": { + "12": { "name": "storage.type.cpp storage.type.built-in.cpp" }, - "25": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "26": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "27": { - "name": "comment.block.cpp" - }, - "28": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "29": { + "13": { "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" }, - "30": { - "patterns": [ - { - "include": "source.cpp#inline_comment" - } - ] - }, - "31": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "32": { - "name": "comment.block.cpp" - }, - "33": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "34": { + "14": { "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" }, - "35": { + "15": { "name": "entity.name.type.parameter.cpp" }, - "36": { + "16": { "patterns": [ { "include": "source.cpp#inline_comment" } ] }, - "37": { + "17": { "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" }, - "38": { + "18": { "name": "comment.block.cpp" }, - "39": { + "19": { "patterns": [ { "match": "\\*\\/", @@ -8447,16 +7918,10 @@ "include": "source.cpp#storage_specifiers" }, { - "include": "source.cpp#primitive_types" + "include": "#pthread_types" }, { - "include": "source.cpp#non_primitive_types" - }, - { - "include": "source.cpp#pthread_types" - }, - { - "include": "source.cpp#posix_reserved_types" + "include": "source.cpp#inline_builtin_storage_type" }, { "include": "#decltype" @@ -9225,9 +8690,6 @@ { "include": "#storage_types" }, - { - "include": "#misc_storage_modifiers" - }, { "include": "#lambdas" }, @@ -9252,7 +8714,8 @@ { "include": "source.cpp#comma" } - ] + ], + "applyEndPatternLast": 1 }, "typedef_class": { "begin": "((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()|(?=(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<6>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<6>?)+>)(?:\\s)*+)?::)*\\s*+)?((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()", + "begin": "(?:\\s)*+(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?(\\()", "end": "\\)", "beginCaptures": { "1": { @@ -1940,7 +1790,7 @@ ] }, "constructor_root": { - "begin": "\\s*+((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", + "begin": "\\s*+((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", "beginCaptures": { "0": { @@ -2015,7 +1865,6 @@ ] }, "11": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" @@ -2186,7 +2035,7 @@ "endCaptures": {}, "patterns": [ { - "begin": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?(\\()", "end": "\\)", "beginCaptures": { "1": { @@ -2308,7 +2157,7 @@ ] }, "control_flow_keywords": { - "match": "((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\{)", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\{)", "end": "\\}", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))~\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", + "begin": "((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)(((?>(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))::((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))~\\14((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\())", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", "beginCaptures": { "0": { @@ -3586,7 +3417,6 @@ ] }, "11": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" @@ -3925,7 +3755,7 @@ "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:(?:\\s)+)?)?(::))?(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?(::))?(?:(?:\\s)+)?((?|\\?\\?>)(?:(?:\\s)+)?(;)|(;))|(?=[;>\\[\\]=]))", "beginCaptures": { "0": { @@ -3964,7 +3794,6 @@ "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" }, "8": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" @@ -4381,9 +4210,6 @@ { "include": "#storage_types" }, - { - "include": "#misc_storage_modifiers" - }, { "include": "#lambdas" }, @@ -4664,7 +4490,7 @@ ] }, "function_call": { - "begin": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:(?:\\s)+)?)?(\\()", + "begin": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:\\s)*+)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:\\s)*+)?(\\()", "end": "\\)", "beginCaptures": { "1": { @@ -4678,7 +4504,6 @@ "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.function.call.cpp" }, "3": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" @@ -4739,7 +4564,7 @@ ] }, "function_definition": { - "begin": "(?:(?:^|\\G|(?<=;|\\}))|(?<=>))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<67>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\()", + "begin": "(?:(?:^|\\G|(?<=;|\\}))|(?<=>))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<60>?)+>)(?:\\s)*+)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\()", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", "beginCaptures": { "0": { @@ -4876,6 +4701,10 @@ "17": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))", + "match": "(?<=protected|virtual|private|public|,|:)(?:(?:\\s)+)?(?!(?:(?:(?:protected)|(?:private)|(?:public))|virtual))(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)?(?![\\w<:.]))", "captures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "10": {}, - "11": { - "name": "entity.name.scope-resolution.cpp" - }, - "12": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, - "13": {}, - "14": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "15": { + "9": {}, + "10": { "patterns": [ { "include": "#inline_comment" } ] }, - "16": { + "11": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -6698,22 +6451,28 @@ } ] }, - "17": { - "name": "entity.name.type.cpp" - }, - "18": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "19": {} + "12": {} } } ] }, + "inline_builtin_storage_type": { + "match": "(?:\\s)*+(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?\\*|->)))((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*(?:(?:\\s)+)?(?:(?:\\.\\*|\\.)|(?:->\\*|->))(?:(?:\\s)+)?)*)(?:(?:\\s)+)?(\\b(?!uint_least64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|suseconds_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|useconds_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|in_addr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintptr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|blksize_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|in_port_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|unsigned[^Pattern.new(\n match: \\/\\w\\/,\n)]|blkcnt_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_quad_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intptr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|swblk_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|wchar_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_short[^Pattern.new(\n match: \\/\\w\\/,\n)]|qaddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|caddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|daddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|fixpt_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|nlink_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|segsz_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|clock_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ssize_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|mode_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|quad_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ushort[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_long[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_char[^Pattern.new(\n match: \\/\\w\\/,\n)]|double[^Pattern.new(\n match: \\/\\w\\/,\n)]|size_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|signed[^Pattern.new(\n match: \\/\\w\\/,\n)]|time_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|key_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ino_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|gid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|dev_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|div_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|float[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_int[^Pattern.new(\n match: \\/\\w\\/,\n)]|uid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|short[^Pattern.new(\n match: \\/\\w\\/,\n)]|off_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|pid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|id_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|bool[^Pattern.new(\n match: \\/\\w\\/,\n)]|char[^Pattern.new(\n match: \\/\\w\\/,\n)]|id_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint[^Pattern.new(\n match: \\/\\w\\/,\n)]|void[^Pattern.new(\n match: \\/\\w\\/,\n)]|long[^Pattern.new(\n match: \\/\\w\\/,\n)]|auto[^Pattern.new(\n match: \\/\\w\\/,\n)]|int[^Pattern.new(\n match: \\/\\w\\/,\n)])(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b(?!\\())", + "match": "(?:((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?\\*|->)))((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*(?:(?:\\s)+)?(?:(?:\\.\\*|\\.)|(?:->\\*|->))(?:(?:\\s)+)?)*)(?:(?:\\s)+)?(\\b(?!uint_least32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_least8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_least8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint_fast8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int_fast8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|suseconds_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|useconds_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|in_addr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|in_port_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uintptr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|blksize_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_quad_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intmax_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|unsigned[^Pattern.new(\n match: \\/\\w\\/,\n)]|blkcnt_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|intptr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|swblk_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|wchar_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_short[^Pattern.new(\n match: \\/\\w\\/,\n)]|qaddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|caddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|daddr_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|fixpt_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|nlink_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|segsz_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|clock_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ssize_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int16_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int32_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int64_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int8_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|mode_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|quad_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ushort[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_long[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_char[^Pattern.new(\n match: \\/\\w\\/,\n)]|double[^Pattern.new(\n match: \\/\\w\\/,\n)]|signed[^Pattern.new(\n match: \\/\\w\\/,\n)]|time_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|size_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|key_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|div_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|ino_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|gid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|off_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|pid_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|float[^Pattern.new(\n match: \\/\\w\\/,\n)]|dev_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|u_int[^Pattern.new(\n match: \\/\\w\\/,\n)]|short[^Pattern.new(\n match: \\/\\w\\/,\n)]|bool[^Pattern.new(\n match: \\/\\w\\/,\n)]|id_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|uint[^Pattern.new(\n match: \\/\\w\\/,\n)]|long[^Pattern.new(\n match: \\/\\w\\/,\n)]|char[^Pattern.new(\n match: \\/\\w\\/,\n)]|void[^Pattern.new(\n match: \\/\\w\\/,\n)]|auto[^Pattern.new(\n match: \\/\\w\\/,\n)]|id_t[^Pattern.new(\n match: \\/\\w\\/,\n)]|int[^Pattern.new(\n match: \\/\\w\\/,\n)])(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b(?!\\())", "captures": { "1": { "patterns": [ @@ -7599,7 +7358,7 @@ ] }, "namespace_alias": { - "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<8>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<8>?)+>)(?:\\s)*+)?::)*\\s*+)(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -7682,7 +7430,7 @@ "include": "#attributes_context" }, { - "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<4>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)(?:(?:\\s)+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<4>?)+>)(?:\\s)*+)?::)*\\s*+)(?:(?:\\s)+)?((?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "3": { - "name": "storage.type.cpp storage.type.built-in.cpp" - } - } - }, "number_literal": { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*)(operator)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<62>?)+>)(?:(?:\\s)+)?)?::)*)(?:(?:((?:(?:delete\\[\\])|(?:delete)|(?:new\\[\\])|(?:<=>)|(?:<<=)|(?:new)|(?:>>=)|(?:\\->\\*)|(?:\\/=)|(?:%=)|(?:&=)|(?:>=)|(?:\\|=)|(?:\\+\\+)|(?:\\-\\-)|(?:\\(\\))|(?:\\[\\])|(?:\\->)|(?:\\+\\+)|(?:<<)|(?:>>)|(?:\\-\\-)|(?:<=)|(?:\\^=)|(?:==)|(?:!=)|(?:&&)|(?:\\|\\|)|(?:\\+=)|(?:\\-=)|(?:\\*=)|,|(?:\\+)|(?:\\-)|!|~|(?:\\*)|&|(?:\\*)|(?:\\/)|%|(?:\\+)|(?:\\-)|<|>|&|(?:\\^)|(?:\\|)|=))|((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\<|\\()", + "begin": "(?:(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:__cdecl|__clrcall|__stdcall|__fastcall|__thiscall|__vectorcall)?)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)(operator)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<55>?)+>)(?:\\s)*+)?::)*+)(?:(?:((?:(?:delete\\[\\])|(?:delete)|(?:new\\[\\])|(?:<=>)|(?:<<=)|(?:new)|(?:>>=)|(?:\\->\\*)|(?:\\/=)|(?:%=)|(?:&=)|(?:>=)|(?:\\|=)|(?:\\+\\+)|(?:\\-\\-)|(?:\\(\\))|(?:\\[\\])|(?:\\->)|(?:\\+\\+)|(?:<<)|(?:>>)|(?:\\-\\-)|(?:<=)|(?:\\^=)|(?:==)|(?:!=)|(?:&&)|(?:\\|\\|)|(?:\\+=)|(?:\\-=)|(?:\\*=)|,|(?:\\+)|(?:\\-)|!|~|(?:\\*)|&|(?:\\*)|(?:\\/)|%|(?:\\+)|(?:\\-)|<|>|&|(?:\\^)|(?:\\|)|=))|((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?:\\[\\])?)))|(\"\")((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=\\<|\\()", "end": "(?:(?<=\\}|%>|\\?\\?>)|(?=[;>\\[\\]=]))", "beginCaptures": { "0": { @@ -8119,6 +7824,10 @@ "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", + "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:\\s)*+(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", "captures": { "1": { "patterns": [ @@ -10605,159 +10290,34 @@ ] }, "11": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "12": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "13": { - "name": "comment.block.cpp" - }, - "14": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "15": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "16": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "17": { - "name": "comment.block.cpp" - }, - "18": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "19": { "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" }, - "20": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "21": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "22": { - "name": "comment.block.cpp" - }, - "23": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "24": { + "12": { "name": "storage.type.cpp storage.type.built-in.cpp" }, - "25": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "26": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "27": { - "name": "comment.block.cpp" - }, - "28": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "29": { + "13": { "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" }, - "30": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "31": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "32": { - "name": "comment.block.cpp" - }, - "33": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "34": { + "14": { "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" }, - "35": { + "15": { "name": "entity.name.type.parameter.cpp" }, - "36": { + "16": { "patterns": [ { "include": "#inline_comment" } ] }, - "37": { + "17": { "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" }, - "38": { + "18": { "name": "comment.block.cpp" }, - "39": { + "19": { "patterns": [ { "match": "\\*\\/", @@ -11705,7 +11265,7 @@ "include": "#vararg_ellipses" }, { - "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", + "match": "((?:((?:(?:volatile)|(?:register)|(?:restrict)|(?:static)|(?:extern)|(?:const)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))+)((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:\\s)*+(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=,|\\)|=)", "captures": { "1": { "patterns": [ @@ -11768,159 +11328,34 @@ ] }, "11": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "12": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "13": { - "name": "comment.block.cpp" - }, - "14": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "15": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "16": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "17": { - "name": "comment.block.cpp" - }, - "18": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "19": { "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" }, - "20": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "21": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "22": { - "name": "comment.block.cpp" - }, - "23": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "24": { + "12": { "name": "storage.type.cpp storage.type.built-in.cpp" }, - "25": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "26": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "27": { - "name": "comment.block.cpp" - }, - "28": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "29": { + "13": { "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" }, - "30": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "31": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "32": { - "name": "comment.block.cpp" - }, - "33": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - }, - "34": { + "14": { "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" }, - "35": { + "15": { "name": "entity.name.type.parameter.cpp" }, - "36": { + "16": { "patterns": [ { "include": "#inline_comment" } ] }, - "37": { + "17": { "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" }, - "38": { + "18": { "name": "comment.block.cpp" }, - "39": { + "19": { "patterns": [ { "match": "\\*\\/", @@ -12838,48 +12273,6 @@ } ] }, - "posix_reserved_types": { - "match": "((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "3": { - "name": "support.type.posix-reserved.cpp support.type.built-in.posix-reserved.cpp" - } - } - }, "pragma": { "begin": "^((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(#)(?:(?:\\s)+)?pragma\\b", "end": "(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "3": { - "name": "storage.type.primitive.cpp storage.type.built-in.primitive.cpp" - } - } - }, - "pthread_types": { - "match": "((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "3": { - "name": "support.type.posix-reserved.pthread.cpp support.type.built-in.posix-reserved.pthread.cpp" - } - } - }, "qualified_type": { - "match": "\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.])", + "match": "\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<11>?)+>)?(?![\\w<:.])", "captures": { "0": { "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "10": { - "name": "entity.name.scope-resolution.cpp" - }, - "11": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, - "13": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "14": { + "9": { "patterns": [ { "include": "#inline_comment" } ] }, - "15": { + "10": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -13499,17 +12792,6 @@ } } ] - }, - "16": { - "name": "entity.name.type.cpp" - }, - "17": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] } }, "name": "meta.qualified_type.cpp" @@ -13557,7 +12839,7 @@ } }, "scope_resolution": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13572,25 +12854,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_function_call": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13605,25 +12876,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_function_call_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -13638,18 +12898,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -13672,7 +12921,7 @@ } }, "scope_resolution_function_definition": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13687,25 +12936,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_function_definition_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -13720,18 +12958,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -13754,7 +12981,7 @@ } }, "scope_resolution_function_definition_operator_overload": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13769,25 +12996,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_function_definition_operator_overload_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -13802,18 +13018,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -13836,7 +13041,7 @@ } }, "scope_resolution_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -13851,18 +13056,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -13885,7 +13079,7 @@ } }, "scope_resolution_namespace_alias": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13900,25 +13094,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_namespace_alias_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -13933,18 +13116,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -13967,7 +13139,7 @@ } }, "scope_resolution_namespace_block": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -13982,25 +13154,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_namespace_block_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -14015,18 +13176,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -14049,7 +13199,7 @@ } }, "scope_resolution_namespace_using": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -14064,25 +13214,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_namespace_using_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -14097,18 +13236,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -14131,7 +13259,7 @@ } }, "scope_resolution_parameter": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -14146,25 +13274,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_parameter_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -14179,18 +13296,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -14213,7 +13319,7 @@ } }, "scope_resolution_template_call": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -14228,25 +13334,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_template_call_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -14261,18 +13356,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -14295,7 +13379,7 @@ } }, "scope_resolution_template_definition": { - "match": "(::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+", + "match": "(::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<3>?)+>)(?:\\s)*+)?::)*\\s*+", "captures": { "0": { "patterns": [ @@ -14310,25 +13394,14 @@ "2": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] } } }, "scope_resolution_template_definition_inner_generated": { - "match": "((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:(?:\\s)+)?)?(::)", + "match": "((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?::)*\\s*+)((?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<7>?)+>)(?:\\s)*+)?(::)", "captures": { "1": { "patterns": [ @@ -14343,18 +13416,7 @@ "3": { "patterns": [ { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } + "include": "#template_call_range" } ] }, @@ -14381,11 +13443,15 @@ "name": "punctuation.terminator.statement.cpp" }, "simple_type": { - "match": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<19>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?", + "match": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<12>?)+>)?(?![\\w<:.]))(((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?", "captures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "10": {}, - "11": { - "name": "entity.name.scope-resolution.cpp" - }, - "12": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, - "13": {}, - "14": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "15": { + "9": {}, + "10": { "patterns": [ { "include": "#inline_comment" } ] }, - "16": { + "11": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -14593,19 +13638,8 @@ } ] }, - "17": { - "name": "entity.name.type.cpp" - }, - "18": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "19": {}, - "20": { + "12": {}, + "13": { "patterns": [ { "match": "\\*", @@ -14648,14 +13682,14 @@ } ] }, - "21": { + "14": { "patterns": [ { "include": "#inline_comment" } ] }, - "22": { + "15": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -14682,14 +13716,14 @@ } ] }, - "23": { + "16": { "patterns": [ { "include": "#inline_comment" } ] }, - "24": { + "17": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -15972,17 +15006,11 @@ { "include": "#storage_specifiers" }, - { - "include": "#primitive_types" - }, - { - "include": "#non_primitive_types" - }, { "include": "#pthread_types" }, { - "include": "#posix_reserved_types" + "include": "#inline_builtin_storage_type" }, { "include": "#decltype" @@ -16860,7 +15888,7 @@ ] }, "template_call_innards": { - "match": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<1>?)+>)(?:(?:\\s)+)?", + "match": "((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<1>?)+>)(?:\\s)*+", "captures": { "0": { "patterns": [ @@ -17108,9 +16136,6 @@ { "include": "#storage_types" }, - { - "include": "#misc_storage_modifiers" - }, { "include": "#lambdas" }, @@ -17135,7 +16160,8 @@ { "include": "#comma" } - ] + ], + "applyEndPatternLast": 1 }, "the_this_keyword": { "match": "((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))((?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(?:(?:\\s)+)?(\\=)(?:(?:\\s)+)?((?:typename)?)(?:(?:\\s)+)?((?:(?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<43>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))|(.*(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)?(?:(?:\\s)+)?(?:(;)|\\n)", + "match": "(using)(?:(?:\\s)+)?(?!namespace)(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<29>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<29>?)+>)?(?![\\w<:.]))(?:(?:\\s)+)?(\\=)(?:(?:\\s)+)?((?:typename)?)(?:(?:\\s)+)?((?:(?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<29>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<29>?)+>)?(?![\\w<:.]))|(.*(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)?(?:(?:\\s)+)?(?:(;)|\\n)", "captures": { "1": { "name": "keyword.other.using.directive.cpp" @@ -17188,6 +16214,10 @@ "2": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "12": { - "name": "entity.name.scope-resolution.cpp" - }, - "13": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, + "11": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "12": { + "patterns": [ + { + "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", + "captures": { + "1": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "2": { + "name": "comment.block.cpp" + }, + "3": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + } + ] + }, + "14": { + "name": "keyword.operator.assignment.cpp" + }, "15": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + "name": "keyword.other.typename.cpp" }, "16": { "patterns": [ { - "include": "#inline_comment" + "include": "#storage_specifiers" } ] }, @@ -17394,59 +16444,12 @@ ] }, "18": { - "name": "entity.name.type.cpp" - }, - "19": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "21": { - "name": "keyword.operator.assignment.cpp" - }, - "22": { - "name": "keyword.other.typename.cpp" - }, - "23": { - "patterns": [ - { - "include": "#storage_specifiers" - } - ] - }, - "24": { - "patterns": [ - { - "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "25": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", + "captures": { + "1": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "2": { + "name": "comment.block.cpp" + }, + "3": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + } + ] + }, + "22": { + "patterns": [ + { + "include": "#inline_comment" + } + ] + }, + "23": { + "patterns": [ + { + "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", + "captures": { + "1": { + "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" + }, + "2": { + "name": "comment.block.cpp" + }, + "3": { + "patterns": [ + { + "match": "\\*\\/", + "name": "comment.block.cpp punctuation.definition.comment.end.cpp" + }, + { + "match": "\\*", + "name": "comment.block.cpp" + } + ] + } + } + } + ] + }, + "24": { + "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.type.cpp" + }, + { + "match": "(?(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "31": { - "patterns": [ - { - "include": "#scope_resolution_inner_generated" - } - ] - }, - "32": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "33": { - "patterns": [ - { - "match": "(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "35": { - "name": "entity.name.scope-resolution.cpp" - }, - "36": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "38": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "39": { - "patterns": [ - { - "include": "#inline_comment" - } - ] - }, - "40": { - "patterns": [ - { - "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", - "captures": { - "1": { - "name": "comment.block.cpp punctuation.definition.comment.begin.cpp" - }, - "2": { - "name": "comment.block.cpp" - }, - "3": { - "patterns": [ - { - "match": "\\*\\/", - "name": "comment.block.cpp punctuation.definition.comment.end.cpp" - }, - { - "match": "\\*", - "name": "comment.block.cpp" - } - ] - } - } - } - ] - }, - "41": { - "name": "entity.name.type.cpp" - }, - "42": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "44": { "name": "meta.declaration.type.alias.value.unknown.cpp", "patterns": [ { @@ -17671,7 +16643,7 @@ } ] }, - "45": { + "31": { "patterns": [ { "match": "\\*", @@ -17714,14 +16686,14 @@ } ] }, - "46": { + "32": { "patterns": [ { "include": "#inline_comment" } ] }, - "47": { + "33": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -17748,14 +16720,14 @@ } ] }, - "48": { + "34": { "patterns": [ { "include": "#inline_comment" } ] }, - "49": { + "35": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -17782,14 +16754,14 @@ } ] }, - "50": { + "36": { "patterns": [ { "include": "#inline_comment" } ] }, - "51": { + "37": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -17816,20 +16788,20 @@ } ] }, - "52": { + "38": { "name": "punctuation.definition.begin.bracket.square.cpp" }, - "53": { + "39": { "patterns": [ { "include": "#evaluation_context" } ] }, - "54": { + "40": { "name": "punctuation.definition.end.bracket.square.cpp" }, - "55": { + "41": { "name": "punctuation.terminator.statement.cpp" } }, @@ -18318,12 +17290,16 @@ "endCaptures": {}, "patterns": [ { - "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(::))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<25>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", + "begin": "(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)(?:\\s)*+)?::)*+)?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<18>?)+>)?(?![\\w<:.]))(((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))?(?:(?:&|(?:\\*))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:&|(?:\\*)))?((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\()(\\*)(?:(?:\\s)+)?((?:(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)?)(?:(?:\\s)+)?(?:(\\[)(\\w*)(\\])(?:(?:\\s)+)?)*(\\))(?:(?:\\s)+)?(\\()", "end": "(\\))((?:(?:(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?=[{=,);>]|\\n)(?!\\()", "beginCaptures": { "1": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*(?:((::)?((?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\s*+(?:((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<24>?)+>)(?:(?:\\s)+)?)?::)*)\\s*+)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\s*+(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<24>?)+>)(?:(?:\\s)+)?)?(::))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)((?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*)\\b(((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<24>?)+>)(?:(?:\\s)+)?)?(?![\\w<:.]))", + "match": "(((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(\\s*+((?:(?:(?:\\[\\[.*?\\]\\]|__attribute(?:__)?\\(\\(.*?\\)\\))|__declspec\\(.*?\\))|alignas\\(.*?\\))(?!\\)))?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?:(?:(?:(?:unsigned)|(?:signed)|(?:short)|(?:long))|(?:(?:struct)|(?:class)|(?:union)|(?:enum)))((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z))))*((?:::)?(?:(?!\\b(?:__has_cpp_attribute|reinterpret_cast|atomic_noexcept|atomic_commit|atomic_cancel|__has_include|synchronized|dynamic_cast|thread_local|static_cast|const_cast|co_return|constexpr|constexpr|constexpr|co_return|protected|namespace|consteval|noexcept|decltype|template|operator|noexcept|co_yield|co_await|reflexpr|continue|co_await|co_yield|requires|volatile|register|restrict|explicit|volatile|noexcept|typename|default|_Pragma|mutable|include|concept|alignas|virtual|alignof|__asm__|defined|mutable|typedef|warning|private|and_eq|define|pragma|typeid|switch|bitand|return|ifndef|export|struct|sizeof|module|static|public|extern|inline|friend|delete|xor_eq|import|not_eq|class|compl|bitor|throw|or_eq|while|catch|break|union|const|const|endif|ifdef|undef|error|using|else|line|goto|else|elif|this|enum|case|new|asm|not|try|for|and|xor|or|if|do|if)\\b)(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<17>?)+>)(?:\\s)*+)?::)*+)?((?:((?:(?>(?:\\s)+)|\\/\\*(?:[^\\*]|(?:\\*)++[^\\/])*+(?:\\*)++\\/)+)|(?:\\b)|(?=\\W)|(?<=\\W)|(?:\\A)|(?:\\Z)))(?!(?:(?:transaction_safe_dynamic)|(?:__has_cpp_attribute)|(?:reinterpret_cast)|(?:transaction_safe)|(?:atomic_noexcept)|(?:atomic_commit)|(?:atomic_cancel)|(?:__has_include)|(?:dynamic_cast)|(?:synchronized)|(?:thread_local)|(?:static_cast)|(?:const_cast)|(?:constexpr)|(?:consteval)|(?:co_return)|(?:co_return)|(?:constexpr)|(?:protected)|(?:constexpr)|(?:namespace)|(?:noexcept)|(?:typename)|(?:decltype)|(?:template)|(?:operator)|(?:noexcept)|(?:co_yield)|(?:co_await)|(?:continue)|(?:co_await)|(?:co_yield)|(?:volatile)|(?:register)|(?:restrict)|(?:explicit)|(?:override)|(?:volatile)|(?:reflexpr)|(?:noexcept)|(?:requires)|(?:alignas)|(?:typedef)|(?:nullptr)|(?:alignof)|(?:mutable)|(?:concept)|(?:virtual)|(?:defined)|(?:__asm__)|(?:include)|(?:_Pragma)|(?:mutable)|(?:default)|(?:warning)|(?:private)|(?:module)|(?:return)|(?:not_eq)|(?:xor_eq)|(?:and_eq)|(?:ifndef)|(?:pragma)|(?:export)|(?:import)|(?:sizeof)|(?:static)|(?:delete)|(?:public)|(?:define)|(?:extern)|(?:inline)|(?:typeid)|(?:switch)|(?:friend)|(?:bitand)|(?:false)|(?:compl)|(?:bitor)|(?:throw)|(?:or_eq)|(?:while)|(?:catch)|(?:break)|(?:const)|(?:final)|(?:const)|(?:endif)|(?:ifdef)|(?:undef)|(?:error)|(?:using)|(?:audit)|(?:axiom)|(?:line)|(?:else)|(?:elif)|(?:true)|(?:NULL)|(?:case)|(?:goto)|(?:else)|(?:this)|(?:new)|(?:asm)|(?:not)|(?:and)|(?:xor)|(?:try)|(?:for)|(?:if)|(?:do)|(?:or)|(?:if))\\b)(?:[a-zA-Z_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))(?:[a-zA-Z0-9_]|(?:\\\\u[0-9a-fA-F]{4}|\\\\U[0-9a-fA-F]{8}))*\\b((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<17>?)+>)?(?![\\w<:.]))", "captures": { "1": { "name": "storage.modifier.cpp" @@ -19676,6 +18630,10 @@ "6": { "name": "meta.qualified_type.cpp", "patterns": [ + { + "match": "::", + "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" + }, { "match": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<2>?)+>)(?:(?:\\s)+)?)?::", - "captures": { - "1": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "2": {} - } - } - ] - }, - "15": {}, - "16": { - "name": "entity.name.scope-resolution.cpp" - }, - "17": { - "name": "meta.template.call.cpp", "patterns": [ { "include": "#template_call_range" } ] }, - "18": {}, - "19": { - "name": "punctuation.separator.namespace.access.cpp punctuation.separator.scope-resolution.cpp" - }, - "20": { + "14": {}, + "15": { "patterns": [ { "include": "#inline_comment" } ] }, - "21": { + "16": { "patterns": [ { "match": "(?:(?>(?:\\s)+)|(\\/\\*)((?:[^\\*]|(?:\\*)++[^\\/])*+((?:\\*)++\\/)))", @@ -19883,18 +18820,7 @@ } ] }, - "22": { - "name": "entity.name.type.cpp" - }, - "23": { - "name": "meta.template.call.cpp", - "patterns": [ - { - "include": "#template_call_range" - } - ] - }, - "24": {} + "17": {} } }, "undef": { @@ -20508,7 +19434,7 @@ } }, "using_namespace": { - "begin": "(?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<6>?)+>)(?:(?:\\s)+)?)?::)*\\s*+)?((?]*+|\"(?:[^\"]*|\\\\\")\")|'(?:[^']*|\\\\')')\\g<6>?)+>)(?:\\s)*+)?::)*\\s*+)?((?= limit; const paging = commits.length ? { - more: more, - cursor: more ? commits[commits.length - 1]?.hash : undefined + cursor: limit === undefined ? undefined : (commits.length >= limit ? commits[commits.length - 1]?.hash : undefined) } : undefined; // If we asked for an extra commit, strip it off @@ -148,12 +146,12 @@ export class GitTimelineProvider implements TimelineProvider { } let dateFormatter: dayjs.Dayjs; - const items = commits.map(c => { + const items = commits.map((c, i) => { const date = c.commitDate; // c.authorDate dateFormatter = dayjs(date); - const item = new GitTimelineItem(c.hash, `${c.hash}^`, c.message, date?.getTime() ?? 0, c.hash, 'git:file:commit'); + const item = new GitTimelineItem(c.hash, commits[i + 1]?.hash ?? `${c.hash}^`, c.message, date?.getTime() ?? 0, c.hash, 'git:file:commit'); item.iconPath = new (ThemeIcon as any)('git-commit'); item.description = c.authorName; item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n\n${c.message}`; diff --git a/extensions/github-authentication/build/postinstall.js b/extensions/github-authentication/build/postinstall.js index e12fd05f191..2f311efc223 100644 --- a/extensions/github-authentication/build/postinstall.js +++ b/extensions/github-authentication/build/postinstall.js @@ -20,7 +20,16 @@ function main() { } } - fs.writeFileSync(path.join(__dirname, '../src/common/config.json'), JSON.stringify(content)); + const githubAppId = process.env.GITHUB_APP_ID; + const githubAppSecret = process.env.GITHUB_APP_SECRET; + + if (githubAppId && githubAppSecret) { + content.GITHUB_APP = { id: githubAppId, secret: githubAppSecret } + } + + if (Object.keys(content).length > 0) { + fs.writeFileSync(path.join(__dirname, '../src/common/config.json'), JSON.stringify(content)); + } } main(); diff --git a/extensions/github-authentication/src/common/clientRegistrar.ts b/extensions/github-authentication/src/common/clientRegistrar.ts index c16c7221ff2..4666ec6a6c0 100644 --- a/extensions/github-authentication/src/common/clientRegistrar.ts +++ b/extensions/github-authentication/src/common/clientRegistrar.ts @@ -3,7 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Uri } from 'vscode'; +import { Uri, env } from 'vscode'; +import * as fs from 'fs'; +import * as path from 'path'; export interface ClientDetails { id?: string; @@ -19,6 +21,8 @@ export interface ClientConfig { VSO: ClientDetails; VSO_PPE: ClientDetails; VSO_DEV: ClientDetails; + + GITHUB_APP: ClientDetails; } export class Registrar { @@ -26,7 +30,8 @@ export class Registrar { constructor() { try { - this._config = require('./config.json') as ClientConfig; + const fileContents = fs.readFileSync(path.join(env.appRoot, 'extensions/github-authentication/src/common/config.json')).toString(); + this._config = JSON.parse(fileContents); } catch (e) { this._config = { OSS: {}, @@ -35,10 +40,20 @@ export class Registrar { EXPLORATION: {}, VSO: {}, VSO_PPE: {}, - VSO_DEV: {} + VSO_DEV: {}, + GITHUB_APP: {} }; } } + + getGitHubAppDetails(): ClientDetails { + if (!this._config.GITHUB_APP.id || !this._config.GITHUB_APP.secret) { + throw new Error(`No GitHub App client configuration available`); + } + + return this._config.GITHUB_APP; + } + getClientDetails(callbackUri: Uri): ClientDetails { let details: ClientDetails | undefined; switch (callbackUri.scheme) { diff --git a/extensions/github-authentication/src/extension.ts b/extensions/github-authentication/src/extension.ts index c377e020939..a8d9da01944 100644 --- a/extensions/github-authentication/src/extension.ts +++ b/extensions/github-authentication/src/extension.ts @@ -20,9 +20,9 @@ export async function activate(context: vscode.ExtensionContext) { displayName: 'GitHub', onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), - login: async (scopes: string[]) => { + login: async (scopeList: string[]) => { try { - const session = await loginService.login(scopes.join(' ')); + const session = await loginService.login(scopeList.join(' ')); Logger.info('Login success!'); return session; } catch (e) { diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index 52c7c4e333a..a8d06a86019 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -8,7 +8,7 @@ import { keychain } from './common/keychain'; import { GitHubServer } from './githubServer'; import Logger from './common/logger'; -export const onDidChangeSessions = new vscode.EventEmitter(); +export const onDidChangeSessions = new vscode.EventEmitter(); interface SessionData { id: string; @@ -29,14 +29,16 @@ export class GitHubAuthenticationProvider { private pollForChange() { setTimeout(async () => { const storedSessions = await this.readSessions(); - let didChange = false; + + const added: string[] = []; + const removed: string[] = []; storedSessions.forEach(session => { const matchesExisting = this._sessions.some(s => s.id === session.id); // Another window added a session to the keychain, add it to our state as well if (!matchesExisting) { this._sessions.push(session); - didChange = true; + added.push(session.id); } }); @@ -49,12 +51,12 @@ export class GitHubAuthenticationProvider { this._sessions.splice(sessionIndex, 1); } - didChange = true; + removed.push(session.id); } }); - if (didChange) { - onDidChangeSessions.fire(); + if (added.length || removed.length) { + onDidChangeSessions.fire({ added, removed, changed: [] }); } this.pollForChange(); @@ -101,12 +103,22 @@ export class GitHubAuthenticationProvider { } public async login(scopes: string): Promise { - const token = await this._githubServer.login(scopes); + const token = scopes === 'vso' ? await this.loginAndInstallApp(scopes) : await this._githubServer.login(scopes); const session = await this.tokenToSession(token, scopes.split(' ')); await this.setToken(session); return session; } + public async loginAndInstallApp(scopes: string): Promise { + const token = await this._githubServer.login(scopes); + const hasUserInstallation = await this._githubServer.hasUserInstallation(token); + if (hasUserInstallation) { + return token; + } else { + return this._githubServer.installApp(); + } + } + private async tokenToSession(token: string, scopes: string[]): Promise { const userInfo = await this._githubServer.getUserInfo(token); return { diff --git a/extensions/github-authentication/src/githubServer.ts b/extensions/github-authentication/src/githubServer.ts index 336a27b2392..bdb2cf1ba83 100644 --- a/extensions/github-authentication/src/githubServer.ts +++ b/extensions/github-authentication/src/githubServer.ts @@ -71,13 +71,58 @@ export class GitHubServer { Logger.info('Logging in...'); const state = uuid(); const callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.github-authentication/did-authenticate`)); - const clientDetails = ClientRegistrar.getClientDetails(callbackUri); + const clientDetails = scopes === 'vso' ? ClientRegistrar.getGitHubAppDetails() : ClientRegistrar.getClientDetails(callbackUri); const uri = vscode.Uri.parse(`https://github.com/login/oauth/authorize?redirect_uri=${encodeURIComponent(callbackUri.toString())}&scope=${scopes}&state=${state}&client_id=${clientDetails.id}`); vscode.env.openExternal(uri); return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, clientDetails)); } + public async hasUserInstallation(token: string): Promise { + return new Promise((resolve, reject) => { + Logger.info('Getting user installations...'); + const post = https.request({ + host: 'api.github.com', + path: `/user/installations`, + method: 'GET', + headers: { + Accept: 'application/vnd.github.machine-man-preview+json', + Authorization: `token ${token}`, + 'User-Agent': 'Visual-Studio-Code' + } + }, result => { + const buffer: Buffer[] = []; + result.on('data', (chunk: Buffer) => { + buffer.push(chunk); + }); + result.on('end', () => { + if (result.statusCode === 200) { + const json = JSON.parse(Buffer.concat(buffer).toString()); + Logger.info('Got installation info!'); + const hasInstallation = json.installations.some((installation: { app_slug: string }) => installation.app_slug === 'microsoft-visual-studio-code'); + resolve(hasInstallation); + } else { + reject(new Error(result.statusMessage)); + } + }); + }); + + post.end(); + post.on('error', err => { + reject(err); + }); + }); + } + + public async installApp(): Promise { + const clientDetails = ClientRegistrar.getGitHubAppDetails(); + const state = uuid(); + const uri = vscode.Uri.parse(`https://github.com/apps/microsoft-visual-studio-code/installations/new?state=${state}`); + + vscode.env.openExternal(uri); + return promiseFromEvent(uriHandler.event, exchangeCodeForToken(state, clientDetails)); + } + public async getUserInfo(token: string): Promise<{ id: string, accountName: string }> { return new Promise((resolve, reject) => { Logger.info('Getting account info...'); diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index 38f6f5231b5..90b5fbd4c96 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -27,8 +27,8 @@ export class PreviewManager implements vscode.CustomEditorProvider { private readonly zoomStatusBarEntry: ZoomStatusBarEntry, ) { } - public async resolveCustomDocument(_document: vscode.CustomDocument): Promise { - // noop + public async openCustomDocument(uri: vscode.Uri) { + return new vscode.CustomDocument(PreviewManager.viewType, uri); } public async resolveCustomEditor( diff --git a/extensions/markdown-language-features/src/features/previewManager.ts b/extensions/markdown-language-features/src/features/previewManager.ts index a9403313931..78b2aa65107 100644 --- a/extensions/markdown-language-features/src/features/previewManager.ts +++ b/extensions/markdown-language-features/src/features/previewManager.ts @@ -63,6 +63,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview private _activePreview: DynamicMarkdownPreview | undefined = undefined; + private readonly customEditorViewType = 'vscode.markdown.preview.editor'; + public constructor( private readonly _contentProvider: MarkdownContentProvider, private readonly _logger: Logger, @@ -70,7 +72,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview ) { super(); this._register(vscode.window.registerWebviewPanelSerializer(DynamicMarkdownPreview.viewType, this)); - this._register(vscode.window.registerCustomEditorProvider('vscode.markdown.preview.editor', this)); + this._register(vscode.window.registerCustomEditorProvider(this.customEditorViewType, this)); } public refresh() { @@ -148,8 +150,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this.registerDynamicPreview(preview); } - public async resolveCustomDocument(_document: vscode.CustomDocument): Promise { - // noop + public async openCustomDocument(uri: vscode.Uri) { + return new vscode.CustomDocument(this.customEditorViewType, uri); } public async resolveCustomTextEditor( diff --git a/extensions/markdown-language-features/src/telemetryReporter.ts b/extensions/markdown-language-features/src/telemetryReporter.ts index d00dca386d1..1104332512d 100644 --- a/extensions/markdown-language-features/src/telemetryReporter.ts +++ b/extensions/markdown-language-features/src/telemetryReporter.ts @@ -48,12 +48,12 @@ export function loadDefaultTelemetryReporter(): TelemetryReporter { } function getPackageInfo(): IPackageInfo | null { - const extention = vscode.extensions.getExtension('Microsoft.vscode-markdown'); - if (extention && extention.packageJSON) { + const extension = vscode.extensions.getExtension('Microsoft.vscode-markdown'); + if (extension && extension.packageJSON) { return { - name: extention.packageJSON.name, - version: extention.packageJSON.version, - aiKey: extention.packageJSON.aiKey + name: extension.packageJSON.name, + version: extension.packageJSON.version, + aiKey: extension.packageJSON.aiKey }; } return null; diff --git a/extensions/vscode-account/src/AADHelper.ts b/extensions/vscode-account/src/AADHelper.ts index ac588b76a6b..d822b449230 100644 --- a/extensions/vscode-account/src/AADHelper.ts +++ b/extensions/vscode-account/src/AADHelper.ts @@ -54,7 +54,7 @@ function parseQuery(uri: vscode.Uri) { }, {}); } -export const onDidChangeSessions = new vscode.EventEmitter(); +export const onDidChangeSessions = new vscode.EventEmitter(); export const REFRESH_NETWORK_FAILURE = 'Network failure'; @@ -129,7 +129,8 @@ export class AzureActiveDirectoryService { private pollForChange() { setTimeout(async () => { - let didChange = false; + const addedIds: string[] = []; + let removedIds: string[] = []; const storedData = await keychain.getToken(); if (storedData) { try { @@ -139,7 +140,7 @@ export class AzureActiveDirectoryService { if (!matchesExisting) { try { await this.refreshToken(session.refreshToken, session.scope); - didChange = true; + addedIds.push(session.id); } catch (e) { if (e.message === REFRESH_NETWORK_FAILURE) { // Ignore, will automatically retry on next poll. @@ -154,7 +155,7 @@ export class AzureActiveDirectoryService { const matchesExisting = sessions.some(session => token.scope === session.scope && token.sessionId === session.id); if (!matchesExisting) { await this.logout(token.sessionId); - didChange = true; + removedIds.push(token.sessionId); } })); @@ -162,19 +163,19 @@ export class AzureActiveDirectoryService { } catch (e) { Logger.error(e.message); // if data is improperly formatted, remove all of it and send change event + removedIds = this._tokens.map(token => token.sessionId); this.clearSessions(); - didChange = true; } } else { if (this._tokens.length) { // Log out all + removedIds = this._tokens.map(token => token.sessionId); await this.clearSessions(); - didChange = true; } } - if (didChange) { - onDidChangeSessions.fire(); + if (addedIds.length || removedIds.length) { + onDidChangeSessions.fire({ added: addedIds, removed: removedIds, changed: [] }); } this.pollForChange(); @@ -377,7 +378,7 @@ export class AzureActiveDirectoryService { this._refreshTimeouts.set(token.sessionId, setTimeout(async () => { try { await this.refreshToken(token.refreshToken, scope); - onDidChangeSessions.fire(); + onDidChangeSessions.fire({ added: [], removed: [], changed: [token.sessionId] }); } catch (e) { if (e.message === REFRESH_NETWORK_FAILURE) { const didSucceedOnRetry = await this.handleRefreshNetworkError(token.sessionId, token.refreshToken, scope); @@ -386,7 +387,7 @@ export class AzureActiveDirectoryService { } } else { await this.logout(token.sessionId); - onDidChangeSessions.fire(); + onDidChangeSessions.fire({ added: [], removed: [token.sessionId], changed: [] }); } } }, 1000 * (parseInt(token.expiresIn) - 30))); @@ -548,9 +549,8 @@ export class AzureActiveDirectoryService { const token = this._tokens.find(token => token.sessionId === sessionId); if (token) { token.accessToken = undefined; + onDidChangeSessions.fire({ added: [], removed: [], changed: [token.sessionId] }); } - - onDidChangeSessions.fire(); } const delayBeforeRetry = 5 * attempts * attempts; diff --git a/extensions/vscode-account/src/extension.ts b/extensions/vscode-account/src/extension.ts index e70fbe59cb0..55cd8b4499b 100644 --- a/extensions/vscode-account/src/extension.ts +++ b/extensions/vscode-account/src/extension.ts @@ -25,13 +25,17 @@ export async function activate(context: vscode.ExtensionContext) { login: async (scopes: string[]) => { try { await loginService.login(scopes.sort().join(' ')); + const session = loginService.sessions[loginService.sessions.length - 1]; + onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] }); return loginService.sessions[0]!; } catch (e) { throw e; } }, logout: async (id: string) => { - return loginService.logout(id); + await loginService.logout(id); + onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); + vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out.")); } })); @@ -46,8 +50,9 @@ export async function activate(context: vscode.ExtensionContext) { } if (sessions.length === 1) { - await loginService.logout(loginService.sessions[0].id); - onDidChangeSessions.fire(); + const id = loginService.sessions[0].id; + await loginService.logout(id); + onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out.")); return; } @@ -61,7 +66,7 @@ export async function activate(context: vscode.ExtensionContext) { if (selectedSession) { await loginService.logout(selectedSession.id); - onDidChangeSessions.fire(); + onDidChangeSessions.fire({ added: [], removed: [selectedSession.id], changed: [] }); vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out.")); return; } diff --git a/package.json b/package.json index d463750469d..c4c429487d3 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "vinyl": "^2.0.0", "vinyl-fs": "^3.0.0", "vsce": "1.48.0", - "vscode-debugprotocol": "1.39.0", + "vscode-debugprotocol": "1.40.0-pre.1", "vscode-nls-dev": "^3.3.1", "webpack": "^4.16.5", "webpack-cli": "^3.3.8", diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index c8ae939e455..19233efb75c 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -354,7 +354,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: ${this.styles.selectBackground} !important; }`); } - // Match quickOpen outline styles - ignore for disabled options + // Match quick input outline styles - ignore for disabled options if (this.styles.listFocusOutline) { content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.focused { outline: 1.6px dotted ${this.styles.listFocusOutline} !important; outline-offset: -1.6px !important; }`); } diff --git a/src/vs/base/browser/ui/splitview/paneview.ts b/src/vs/base/browser/ui/splitview/paneview.ts index 5fc898e82f0..f72d80c58c9 100644 --- a/src/vs/base/browser/ui/splitview/paneview.ts +++ b/src/vs/base/browser/ui/splitview/paneview.ts @@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { $, append, addClass, removeClass, toggleClass, trackFocus, EventHelper } from 'vs/base/browser/dom'; +import { $, append, addClass, removeClass, toggleClass, trackFocus, EventHelper, clearNode } from 'vs/base/browser/dom'; import { firstIndex } from 'vs/base/common/arrays'; import { Color, RGBA } from 'vs/base/common/color'; import { SplitView, IView } from './splitview'; @@ -52,7 +52,6 @@ export abstract class Pane extends Disposable implements IView { protected _expanded: boolean; protected _orientation: Orientation; - protected _preventCollapse?: boolean; private expandedSize: number | undefined = undefined; private _headerVisible = true; @@ -106,7 +105,7 @@ export abstract class Pane extends Disposable implements IView { get minimumSize(): number { const headerSize = this.headerSize; const expanded = !this.headerVisible || this.isExpanded(); - const minimumBodySize = expanded ? this._minimumBodySize : 0; + const minimumBodySize = expanded ? this._minimumBodySize : this._orientation === Orientation.HORIZONTAL ? 50 : 0; return headerSize + minimumBodySize; } @@ -114,7 +113,7 @@ export abstract class Pane extends Disposable implements IView { get maximumSize(): number { const headerSize = this.headerSize; const expanded = !this.headerVisible || this.isExpanded(); - const maximumBodySize = expanded ? this._maximumBodySize : 0; + const maximumBodySize = expanded ? this._maximumBodySize : this._orientation === Orientation.HORIZONTAL ? 50 : 0; return headerSize + maximumBodySize; } @@ -174,6 +173,18 @@ export abstract class Pane extends Disposable implements IView { this._onDidChange.fire(undefined); } + get orientation(): Orientation { + return this._orientation; + } + + set orientation(orientation: Orientation) { + if (this._orientation === orientation) { + return; + } + + this._orientation = orientation; + } + render(): void { this.header = $('.pane-header'); append(this.element, this.header); @@ -190,22 +201,20 @@ export abstract class Pane extends Disposable implements IView { this.updateHeader(); - if (!this._preventCollapse) { - const onHeaderKeyDown = Event.chain(domEvent(this.header, 'keydown')) - .map(e => new StandardKeyboardEvent(e)); + const onHeaderKeyDown = Event.chain(domEvent(this.header, 'keydown')) + .map(e => new StandardKeyboardEvent(e)); - this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) - .event(() => this.setExpanded(!this.isExpanded()), null)); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space) + .event(() => this.setExpanded(!this.isExpanded()), null)); - this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) - .event(() => this.setExpanded(false), null)); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.LeftArrow) + .event(() => this.setExpanded(false), null)); - this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) - .event(() => this.setExpanded(true), null)); + this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow) + .event(() => this.setExpanded(true), null)); - this._register(domEvent(this.header, 'click') - (() => this.setExpanded(!this.isExpanded()), null)); - } + this._register(domEvent(this.header, 'click') + (() => this.setExpanded(!this.isExpanded()), null)); this.body = append(this.element, $('.pane-body')); this.renderBody(this.body); @@ -402,13 +411,14 @@ export class PaneView extends Disposable { private el: HTMLElement; private paneItems: IPaneItem[] = []; private orthogonalSize: number = 0; + private size: number = 0; private splitview: SplitView; - private orientation: Orientation; private animationTimer: number | undefined = undefined; private _onDidDrop = this._register(new Emitter<{ from: Pane, to: Pane }>()); readonly onDidDrop: Event<{ from: Pane, to: Pane }> = this._onDidDrop.event; + orientation: Orientation; readonly onDidSashChange: Event; constructor(container: HTMLElement, options: IPaneViewOptions = {}) { @@ -427,6 +437,7 @@ export class PaneView extends Disposable { const paneItem = { pane: pane, disposable: disposables }; this.paneItems.splice(index, 0, paneItem); + pane.orientation = this.orientation; pane.orthogonalSize = this.orthogonalSize; this.splitview.addView(pane, size, index); @@ -485,12 +496,39 @@ export class PaneView extends Disposable { layout(height: number, width: number): void { this.orthogonalSize = this.orientation === Orientation.VERTICAL ? width : height; + this.size = this.orientation === Orientation.HORIZONTAL ? width : height; for (const paneItem of this.paneItems) { paneItem.pane.orthogonalSize = this.orthogonalSize; } - this.splitview.layout(this.orientation === Orientation.HORIZONTAL ? width : height); + this.splitview.layout(this.size); + } + + flipOrientation(height: number, width: number): void { + this.orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; + const paneSizes = this.paneItems.map(pane => this.getPaneSize(pane.pane)); + + this.splitview.dispose(); + clearNode(this.el); + + this.splitview = this._register(new SplitView(this.el, { orientation: this.orientation })); + + const newOrthogonalSize = this.orientation === Orientation.VERTICAL ? width : height; + const newSize = this.orientation === Orientation.HORIZONTAL ? width : height; + + this.paneItems.forEach((pane, index) => { + pane.pane.orthogonalSize = newOrthogonalSize; + pane.pane.orientation = this.orientation; + + const viewSize = this.size === 0 ? 0 : (newSize * paneSizes[index]) / this.size; + this.splitview.addView(pane.pane, viewSize, index); + }); + + this.size = newSize; + this.orthogonalSize = newOrthogonalSize; + + this.splitview.layout(this.size); } private setupAnimation(): void { diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts index 1126f89c7d8..8a6a6860b22 100644 --- a/src/vs/base/common/buffer.ts +++ b/src/vs/base/common/buffer.ts @@ -115,6 +115,19 @@ export class VSBuffer { } } +export function readUInt16LE(source: Uint8Array, offset: number): number { + return ( + source[offset] + + source[offset + 1] * 2 ** 8 + ); +} + +export function writeUInt16LE(destination: Uint8Array, value: number, offset: number): void { + destination[offset] = value; + value = value >>> 8; + destination[offset + 1] = value; +} + export function readUInt32BE(source: Uint8Array, offset: number): number { return ( source[offset] * 2 ** 24 @@ -134,11 +147,11 @@ export function writeUInt32BE(destination: Uint8Array, value: number, offset: nu destination[offset] = value; } -function readUInt8(source: Uint8Array, offset: number): number { +export function readUInt8(source: Uint8Array, offset: number): number { return source[offset]; } -function writeUInt8(destination: Uint8Array, value: number, offset: number): void { +export function writeUInt8(destination: Uint8Array, value: number, offset: number): void { destination[offset] = value; } diff --git a/src/vs/base/common/fuzzyScorer.ts b/src/vs/base/common/fuzzyScorer.ts index c43b4f20e85..a36aa821f13 100644 --- a/src/vs/base/common/fuzzyScorer.ts +++ b/src/vs/base/common/fuzzyScorer.ts @@ -321,6 +321,8 @@ export function prepareQuery(original: string): IPreparedQuery { let value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace if (isWindows) { value = value.replace(/\//g, sep); // Help Windows users to search for paths when using slash + } else { + value = value.replace(/\\/g, sep); // Help macOS/Linux users to search for paths when using backslash } const lowercase = value.toLowerCase(); @@ -451,7 +453,7 @@ function doScoreItem(label: string, description: string | undefined, path: strin return NO_ITEM_SCORE; } -export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache, fallbackComparer = fallbackCompare): number { +export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor, cache: ScorerCache): number { const itemScoreA = scoreItem(itemA, query, fuzzy, accessor, cache); const itemScoreB = scoreItem(itemB, query, fuzzy, accessor, cache); @@ -517,7 +519,16 @@ export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery return scoreA > scoreB ? -1 : 1; } - // 6.) scores are identical, prefer more compact matches (label and description) + // 6.) prefer matches in label over non-label matches + const itemAHasLabelMatches = Array.isArray(itemScoreA.labelMatch) && itemScoreA.labelMatch.length > 0; + const itemBHasLabelMatches = Array.isArray(itemScoreB.labelMatch) && itemScoreB.labelMatch.length > 0; + if (itemAHasLabelMatches && !itemBHasLabelMatches) { + return -1; + } else if (itemBHasLabelMatches && !itemAHasLabelMatches) { + return 1; + } + + // 7.) scores are identical, prefer more compact matches (label and description) const itemAMatchDistance = computeLabelAndDescriptionMatchDistance(itemA, itemScoreA, accessor); const itemBMatchDistance = computeLabelAndDescriptionMatchDistance(itemB, itemScoreB, accessor); if (itemAMatchDistance && itemBMatchDistance && itemAMatchDistance !== itemBMatchDistance) { @@ -526,7 +537,7 @@ export function compareItemsByScore(itemA: T, itemB: T, query: IPreparedQuery // 7.) at this point, scores are identical and match compactness as well // for both items so we start to use the fallback compare - return fallbackComparer(itemA, itemB, query, accessor); + return fallbackCompare(itemA, itemB, query, accessor); } function computeLabelAndDescriptionMatchDistance(item: T, score: IItemScore, accessor: IItemAccessor): number { diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index fb146b969f5..d633d611a32 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -28,11 +28,17 @@ export class HistoryNavigator implements INavigator { } public next(): T | null { - return this._navigator.next(); + if (this._currentPosition() !== this._elements.length - 1) { + return this._navigator.next(); + } + return null; } public previous(): T | null { - return this._navigator.previous(); + if (this._currentPosition() !== 0) { + return this._navigator.previous(); + } + return null; } public current(): T | null { @@ -73,6 +79,15 @@ export class HistoryNavigator implements INavigator { } } + private _currentPosition(): number { + const currentElement = this._navigator.current(); + if (!currentElement) { + return -1; + } + + return this._elements.indexOf(currentElement); + } + private _initialize(history: readonly T[]): void { this._history = new Set(); for (const entry of history) { diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index a68e020f9f1..e4546b2cf60 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts @@ -53,6 +53,12 @@ export namespace Schemas { export const vscodeRemoteResource = 'vscode-remote-resource'; export const userData = 'vscode-userdata'; + + export const vscodeCustomEditor = 'vscode-custom-editor'; + + export const vscodeSettings = 'vscode-settings'; + + export const webviewPanel = 'webview-panel'; } class RemoteAuthoritiesImpl { diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 5a631e0b395..2c30aaa188f 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -209,3 +209,17 @@ export const enum OperatingSystem { Linux = 3 } export const OS = (_isMacintosh ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux)); + +let _isLittleEndian = true; +let _isLittleEndianComputed = false; +export function isLittleEndian(): boolean { + if (!_isLittleEndianComputed) { + _isLittleEndianComputed = true; + const test = new Uint8Array(2); + test[0] = 1; + test[1] = 2; + const view = new Uint16Array(test.buffer); + _isLittleEndian = (view[0] === (2 << 8) + 1); + } + return _isLittleEndian; +} diff --git a/src/vs/base/common/resources.ts b/src/vs/base/common/resources.ts index d42666ebcc0..6de22b4778b 100644 --- a/src/vs/base/common/resources.ts +++ b/src/vs/base/common/resources.ts @@ -5,7 +5,7 @@ import * as extpath from 'vs/base/common/extpath'; import * as paths from 'vs/base/common/path'; -import { URI, originalFSPath as uriOriginalFSPath } from 'vs/base/common/uri'; +import { URI } from 'vs/base/common/uri'; import { equalsIgnoreCase } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; import { isLinux, isWindows } from 'vs/base/common/platform'; @@ -13,10 +13,39 @@ import { CharCode } from 'vs/base/common/charCode'; import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob'; import { TernarySearchTree } from 'vs/base/common/map'; -export const originalFSPath = uriOriginalFSPath; +export function originalFSPath(uri: URI): string { + let value: string; + const uriPath = uri.path; + if (uri.authority && uriPath.length > 1 && uri.scheme === 'file') { + // unc path: file://shares/c$/far/boo + value = `//${uri.authority}${uriPath}`; + } else if ( + isWindows + && uriPath.charCodeAt(0) === CharCode.Slash + && extpath.isWindowsDriveLetter(uriPath.charCodeAt(1)) + && uriPath.charCodeAt(2) === CharCode.Colon + ) { + value = uriPath.substr(1); + } else { + // other path + value = uriPath; + } + if (isWindows) { + value = value.replace(/\//g, '\\'); + } + return value; +} -export function getComparisonKey(resource: URI): string { - return hasToIgnoreCase(resource) ? resource.toString().toLowerCase() : resource.toString(); +/** + * Creates a key from a resource URI to be used to resource comparison and for resource maps. + * URI queries are included, fragments are ignored. + */ +export function getComparisonKey(resource: URI, caseInsensitivePath = hasToIgnoreCase(resource)): string { + let path = resource.path || '/'; + if (caseInsensitivePath) { + path = path.toLowerCase(); + } + return `${resource.scheme}://${resource.authority.toLowerCase()}/${path}?${resource.query}`; } export function hasToIgnoreCase(resource: URI | undefined): boolean { @@ -31,29 +60,33 @@ export function basenameOrAuthority(resource: URI): string { /** * Tests whether a `candidate` URI is a parent or equal of a given `base` URI. + * URI queries must match, fragments are ignored. * @param base A uri which is "longer" * @param parentCandidate A uri which is "shorter" then `base` */ export function isEqualOrParent(base: URI, parentCandidate: URI, ignoreCase = hasToIgnoreCase(base)): boolean { if (base.scheme === parentCandidate.scheme) { if (base.scheme === Schemas.file) { - return extpath.isEqualOrParent(originalFSPath(base), originalFSPath(parentCandidate), ignoreCase); + return extpath.isEqualOrParent(originalFSPath(base), originalFSPath(parentCandidate), ignoreCase) && base.query === parentCandidate.query; } if (isEqualAuthority(base.authority, parentCandidate.authority)) { - return extpath.isEqualOrParent(base.path, parentCandidate.path, ignoreCase, '/'); + return extpath.isEqualOrParent(base.path || '/', parentCandidate.path || '/', ignoreCase, '/') && base.query === parentCandidate.query; } } return false; } /** - * Tests wheter the two authorities are the same + * Tests whether the two authorities are the same */ export function isEqualAuthority(a1: string, a2: string) { return a1 === a2 || equalsIgnoreCase(a1, a2); } -export function isEqual(first: URI | undefined, second: URI | undefined, ignoreCase = hasToIgnoreCase(first)): boolean { +/** + * Tests whether two resources are the same. URI queries must match, fragments are ignored unless requested. + */ +export function isEqual(first: URI | undefined, second: URI | undefined, caseInsensitivePath = hasToIgnoreCase(first), ignoreFragment = true): boolean { if (first === second) { return true; } @@ -67,7 +100,7 @@ export function isEqual(first: URI | undefined, second: URI | undefined, ignoreC } const p1 = first.path || '/', p2 = second.path || '/'; - return p1 === p2 || ignoreCase && equalsIgnoreCase(p1 || '/', p2 || '/'); + return (p1 === p2 || caseInsensitivePath && equalsIgnoreCase(p1, p2)) && first.query === second.query && (ignoreFragment || first.fragment === second.fragment); } export function basename(resource: URI): string { @@ -88,13 +121,15 @@ export function dirname(resource: URI): URI { if (resource.path.length === 0) { return resource; } + let dirname; if (resource.scheme === Schemas.file) { - return URI.file(paths.dirname(originalFSPath(resource))); - } - let dirname = paths.posix.dirname(resource.path); - if (resource.authority && dirname.length && dirname.charCodeAt(0) !== CharCode.Slash) { - console.error(`dirname("${resource.toString})) resulted in a relative path`); - dirname = '/'; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash ("/") character + dirname = URI.file(paths.dirname(originalFSPath(resource))).path; + } else { + dirname = paths.posix.dirname(resource.path); + if (resource.authority && dirname.length && dirname.charCodeAt(0) !== CharCode.Slash) { + console.error(`dirname("${resource.toString})) resulted in a relative path`); + dirname = '/'; // If a URI contains an authority component, then the path component must either be empty or begin with a CharCode.Slash ("/") character + } } return resource.with({ path: dirname @@ -109,7 +144,15 @@ export function dirname(resource: URI): URI { * @returns The resulting URI. */ export function joinPath(resource: URI, ...pathFragment: string[]): URI { - return URI.joinPaths(resource, ...pathFragment); + let joinedPath: string; + if (resource.scheme === 'file') { + joinedPath = URI.file(paths.join(originalFSPath(resource), ...pathFragment)).path; + } else { + joinedPath = paths.posix.join(resource.path || '/', ...pathFragment); + } + return resource.with({ + path: joinedPath + }); } /** @@ -189,7 +232,7 @@ export function addTrailingPathSeparator(resource: URI, sep: string = paths.sep) * Returns a relative path between two URIs. If the URIs don't have the same schema or authority, `undefined` is returned. * The returned relative path always uses forward slashes. */ -export function relativePath(from: URI, to: URI, ignoreCase = hasToIgnoreCase(from)): string | undefined { +export function relativePath(from: URI, to: URI, caseInsensitivePath = hasToIgnoreCase(from)): string | undefined { if (from.scheme !== to.scheme || !isEqualAuthority(from.authority, to.authority)) { return undefined; } @@ -198,7 +241,7 @@ export function relativePath(from: URI, to: URI, ignoreCase = hasToIgnoreCase(fr return isWindows ? extpath.toSlashes(relativePath) : relativePath; } let fromPath = from.path || '/', toPath = to.path || '/'; - if (ignoreCase) { + if (caseInsensitivePath) { // make casing of fromPath match toPath let i = 0; for (const len = Math.min(fromPath.length, toPath.length); i < len; i++) { diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 0108b531460..f3a93bdf189 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -6,7 +6,6 @@ import { isWindows } from 'vs/base/common/platform'; import { CharCode } from 'vs/base/common/charCode'; import * as paths from 'vs/base/common/path'; -import * as extpath from 'vs/base/common/extpath'; const _schemePattern = /^\w[\w\d+.-]*$/; const _singleSlashStart = /^\//; @@ -340,19 +339,16 @@ export class URI implements UriComponents { /** * Join a URI path with path fragments and normalizes the resulting path. * - * @param resource The input URI. + * @param uri The input URI. * @param pathFragment The path fragment to add to the URI path. * @returns The resulting URI. */ - static joinPaths(resource: URI, ...pathFragment: string[]): URI { - let joinedPath: string; - if (resource.scheme === 'file') { - joinedPath = URI.file(paths.join(originalFSPath(resource), ...pathFragment)).path; - } else { - joinedPath = paths.posix.join(resource.path || '/', ...pathFragment); + static joinPath(uri: URI, ...pathFragment: string[]): URI { + if (!uri.path) { + throw new Error(`[UriError]: cannot call joinPaths on URI without path`); } - return resource.with({ - path: joinedPath + return uri.with({ + path: paths.posix.join(uri.path, ...pathFragment) }); } @@ -694,29 +690,3 @@ function percentDecode(str: string): string { } return str.replace(_rEncodedAsHex, (match) => decodeURIComponentGraceful(match)); } - - -// --- utils - -export function originalFSPath(uri: URI): string { - let value: string; - const uriPath = uri.path; - if (uri.authority && uriPath.length > 1 && uri.scheme === 'file') { - // unc path: file://shares/c$/far/boo - value = `//${uri.authority}${uriPath}`; - } else if ( - isWindows - && uriPath.charCodeAt(0) === CharCode.Slash - && extpath.isWindowsDriveLetter(uriPath.charCodeAt(1)) - && uriPath.charCodeAt(2) === CharCode.Colon - ) { - value = uriPath.substr(1); - } else { - // other path - value = uriPath; - } - if (isWindows) { - value = value.replace(/\//g, '\\'); - } - return value; -} diff --git a/src/vs/base/parts/quickinput/browser/media/quickInput.css b/src/vs/base/parts/quickinput/browser/media/quickInput.css index 94237b63913..0685569f91c 100644 --- a/src/vs/base/parts/quickinput/browser/media/quickInput.css +++ b/src/vs/base/parts/quickinput/browser/media/quickInput.css @@ -55,8 +55,8 @@ margin-bottom: -2px; } -.quick-input-widget.quick-navigate-mode .quick-input-header { - /* reduce margins and paddings in quick navigate mode */ +.quick-input-widget.hidden-input .quick-input-header { + /* reduce margins and paddings when input box hidden */ padding: 0; margin-bottom: 0; } @@ -132,8 +132,8 @@ margin-top: 6px; } -.quick-input-widget.quick-navigate-mode .quick-input-list { - margin-top: 0; /* reduce margins in quick navigate mode */ +.quick-input-widget.hidden-input .quick-input-list { + margin-top: 0; /* reduce margins when input box hidden */ } .quick-input-list .monaco-list { diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 19250a185f3..367449e2b85 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/quickInput'; -import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS } from 'vs/base/parts/quickinput/common/quickInput'; +import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation } from 'vs/base/parts/quickinput/common/quickInput'; import * as dom from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { QuickInputList, QuickInputListFocus } from './quickInputList'; @@ -364,7 +364,7 @@ class QuickInput extends Disposable implements IQuickInput { readonly onDispose = this.onDisposeEmitter.event; - public dispose(): void { + dispose(): void { this.hide(); this.onDisposeEmitter.fire(); @@ -391,6 +391,7 @@ class QuickPick extends QuickInput implements IQuickPi private _matchOnLabel = true; private _sortByLabel = true; private _autoFocusOnList = true; + private _itemActivation = ItemActivation.FIRST; private _activeItems: T[] = []; private activeItemsUpdated = false; private activeItemsToConfirm: T[] | null = []; @@ -408,6 +409,7 @@ class QuickPick extends QuickInput implements IQuickPi private _customButtonLabel: string | undefined; private _customButtonHover: string | undefined; private _quickNavigate: IQuickNavigateConfiguration | undefined; + private _hideInput: boolean | undefined; get quickNavigate() { return this._quickNavigate; @@ -460,10 +462,6 @@ class QuickPick extends QuickInput implements IQuickPi set items(items: Array) { this._items = items; this.itemsUpdated = true; - if (this._items.length === 0) { - // quick-navigate requires at least 1 item - this._quickNavigate = undefined; - } this.update(); } @@ -520,7 +518,6 @@ class QuickPick extends QuickInput implements IQuickPi this.update(); } - get autoFocusOnList() { return this._autoFocusOnList; } @@ -530,6 +527,14 @@ class QuickPick extends QuickInput implements IQuickPi this.update(); } + get itemActivation() { + return this._itemActivation; + } + + set itemActivation(itemActivation: ItemActivation) { + this._itemActivation = itemActivation; + } + get activeItems() { return this._activeItems; } @@ -614,14 +619,23 @@ class QuickPick extends QuickInput implements IQuickPi this.update(); } - public inputHasFocus(): boolean { + inputHasFocus(): boolean { return this.visible ? this.ui.inputBox.hasFocus() : false; } - public focusOnInput() { + focusOnInput() { this.ui.inputBox.setFocus(); } + get hideInput() { + return !!this._hideInput; + } + + set hideInput(hideInput: boolean) { + this._hideInput = hideInput; + this.update(); + } + onDidChangeSelection = this.onDidChangeSelectionEmitter.event; onDidTriggerItemButton = this.onDidTriggerItemButtonEmitter.event; @@ -721,7 +735,7 @@ class QuickPick extends QuickInput implements IQuickPi this.onDidAcceptEmitter.fire({ inBackground: false }); })); this.visibleDisposables.add(this.ui.onDidCustom(() => { - this.onDidCustomEmitter.fire(undefined); + this.onDidCustomEmitter.fire(); })); this.visibleDisposables.add(this.ui.list.onDidChangeFocus(focusedItems => { if (this.activeItemsUpdated) { @@ -806,10 +820,16 @@ class QuickPick extends QuickInput implements IQuickPi return false; }); - if (wasTriggerKeyPressed && this.activeItems[0]) { - this._selectedItems = [this.activeItems[0]]; - this.onDidChangeSelectionEmitter.fire(this.selectedItems); - this.onDidAcceptEmitter.fire({ inBackground: false }); + if (wasTriggerKeyPressed) { + if (this.activeItems[0]) { + this._selectedItems = [this.activeItems[0]]; + this.onDidChangeSelectionEmitter.fire(this.selectedItems); + this.onDidAcceptEmitter.fire({ inBackground: false }); + } + // Unset quick navigate after press. It is only valid once + // and should not result in any behaviour change afterwards + // if the picker remains open because there was no active item + this._quickNavigate = undefined; } }); } @@ -818,11 +838,21 @@ class QuickPick extends QuickInput implements IQuickPi if (!this.visible) { return; } - dom.toggleClass(this.ui.container, 'quick-navigate-mode', !!this._quickNavigate); - const ok = this.ok === 'default' ? this.canSelectMany : this.ok; - const visibilities: Visibilities = this.canSelectMany ? - { title: !!this.title || !!this.step, description: !!this.description, checkAll: true, inputBox: !this._quickNavigate, progressBar: !this._quickNavigate, visibleCount: true, count: true, ok, list: true, message: !!this.validationMessage, customButton: this.customButton } : - { title: !!this.title || !!this.step, description: !!this.description, inputBox: !this._quickNavigate, progressBar: !this._quickNavigate, visibleCount: true, list: true, message: !!this.validationMessage, customButton: this.customButton, ok }; + const hideInput = !!this._hideInput && this._items.length > 0; // do not allow to hide input without items + dom.toggleClass(this.ui.container, 'hidden-input', hideInput); + const visibilities: Visibilities = { + title: !!this.title || !!this.step, + description: !!this.description, + checkAll: this.canSelectMany, + inputBox: !hideInput, + progressBar: !hideInput, + visibleCount: true, + count: this.canSelectMany, + ok: this.ok === 'default' ? this.canSelectMany : this.ok, + list: true, + message: !!this.validationMessage, + customButton: this.customButton + }; this.ui.setVisibilities(visibilities); super.update(); if (this.ui.inputBox.value !== this.value) { @@ -844,18 +874,23 @@ class QuickPick extends QuickInput implements IQuickPi this.ui.list.sortByLabel = this.sortByLabel; if (this.itemsUpdated) { this.itemsUpdated = false; - const previousItemCount = this.ui.list.getElementsCount(); this.ui.list.setElements(this.items); this.ui.list.filter(this.filterValue(this.ui.inputBox.value)); this.ui.checkAll.checked = this.ui.list.getAllVisibleChecked(); this.ui.visibleCount.setCount(this.ui.list.getVisibleCount()); this.ui.count.setCount(this.ui.list.getCheckedCount()); - if (this._quickNavigate && previousItemCount === 0 && this.items.length > 1) { - // quick navigate: automatically focus the second entry - // so that upon release the item is picked directly - this.ui.list.focus(QuickInputListFocus.Second); - } else { - this.trySelectFirst(); + switch (this._itemActivation) { + case ItemActivation.SECOND: + this.ui.list.focus(QuickInputListFocus.Second); + this._itemActivation = ItemActivation.FIRST; // only valid once, then unset + break; + case ItemActivation.LAST: + this.ui.list.focus(QuickInputListFocus.Last); + this._itemActivation = ItemActivation.FIRST; // only valid once, then unset + break; + default: + this.trySelectFirst(); + break; } } if (this.ui.container.classList.contains('show-checkboxes') !== !!this.canSelectMany) { @@ -986,7 +1021,7 @@ class InputBox extends QuickInput implements IInputBox { this._value = value; this.onDidValueChangeEmitter.fire(value); })); - this.visibleDisposables.add(this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire(undefined))); + this.visibleDisposables.add(this.ui.onDidAccept(() => this.onDidAcceptEmitter.fire())); this.valueSelectionUpdated = true; } super.show(); @@ -1040,10 +1075,12 @@ export class QuickInputController extends Disposable { private parentElement: HTMLElement; private styles: IQuickInputStyles; + private onShowEmitter = new Emitter(); + readonly onShow = this.onShowEmitter.event; + private onHideEmitter = new Emitter(); - public onShow = this.onShowEmitter.event; - public onHide = this.onHideEmitter.event; + readonly onHide = this.onHideEmitter.event; constructor(private options: IQuickInputOptions) { super(); @@ -1518,7 +1555,7 @@ export class QuickInputController extends Disposable { } } - public hide(focusLost?: boolean) { + hide(focusLost?: boolean) { const controller = this.controller; if (controller) { this.controller = null; @@ -1552,7 +1589,14 @@ export class QuickInputController extends Disposable { } } - async accept() { + async accept(keyMods: IKeyMods = { alt: false, ctrlCmd: false }) { + // When accepting the item programmatically, it is important that + // we update `keyMods` either from the provided set or unset it + // because the accept did not happen from mouse or keyboard + // interaction on the list itself + this.keyMods.alt = keyMods.alt; + this.keyMods.ctrlCmd = keyMods.ctrlCmd; + this.onDidAcceptEmitter.fire(); } @@ -1584,7 +1628,7 @@ export class QuickInputController extends Disposable { } } - public applyStyles(styles: IQuickInputStyles) { + applyStyles(styles: IQuickInputStyles) { this.styles = styles; this.updateStyles(); } diff --git a/src/vs/base/parts/quickinput/browser/quickInputList.ts b/src/vs/base/parts/quickinput/browser/quickInputList.ts index 0f3303cafe1..e4179ea8c76 100644 --- a/src/vs/base/parts/quickinput/browser/quickInputList.ts +++ b/src/vs/base/parts/quickinput/browser/quickInputList.ts @@ -317,6 +317,18 @@ export class QuickInputList { this._onLeave.fire(); } })); + this.disposables.push(this.list.onContextMenu(e => { + if (typeof e.index === 'number') { + e.browserEvent.preventDefault(); + + // we want to treat a context menu event as + // a gesture to open the item at the index + // since we do not have any context menu + // this enables for example macOS to Ctrl- + // click on an item to open it. + this.list.setSelection([e.index]); + } + })); } @memoize @@ -440,7 +452,10 @@ export class QuickInputList { .filter(item => this.elementsToIndexes.has(item)) .map(item => this.elementsToIndexes.get(item)!)); if (items.length > 0) { - this.list.reveal(this.list.getFocus()[0]); + const focused = this.list.getFocus()[0]; + if (typeof focused === 'number') { + this.list.reveal(focused); + } } } @@ -492,10 +507,15 @@ export class QuickInputList { if ((what === QuickInputListFocus.Next || what === QuickInputListFocus.NextPage) && this.list.getFocus()[0] === this.list.length - 1) { what = QuickInputListFocus.First; } + if ((what === QuickInputListFocus.Previous || what === QuickInputListFocus.PreviousPage) && this.list.getFocus()[0] === 0) { what = QuickInputListFocus.Last; } + if (what === QuickInputListFocus.Second && this.list.length < 2) { + what = QuickInputListFocus.First; + } + switch (what) { case QuickInputListFocus.First: this.list.focusFirst(); @@ -520,7 +540,10 @@ export class QuickInputList { break; } - this.list.reveal(this.list.getFocus()[0]); + const focused = this.list.getFocus()[0]; + if (typeof focused === 'number') { + this.list.reveal(focused); + } } clearFocus() { diff --git a/src/vs/base/parts/quickinput/common/quickInput.ts b/src/vs/base/parts/quickinput/common/quickInput.ts index 398a7e6b922..e24bff6d117 100644 --- a/src/vs/base/parts/quickinput/common/quickInput.ts +++ b/src/vs/base/parts/quickinput/common/quickInput.ts @@ -182,6 +182,12 @@ export interface IQuickPickAcceptEvent { inBackground: boolean; } +export enum ItemActivation { + FIRST = 1, + SECOND, + LAST +} + export interface IQuickPick extends IQuickInput { value: string; @@ -243,6 +249,11 @@ export interface IQuickPick extends IQuickInput { readonly onDidChangeActive: Event; + /** + * Allows to control which entry should be activated by default. + */ + itemActivation: ItemActivation; + selectedItems: ReadonlyArray; readonly onDidChangeSelection: Event; @@ -256,6 +267,13 @@ export interface IQuickPick extends IQuickInput { inputHasFocus(): boolean; focusOnInput(): void; + + /** + * Hides the input box from the picker UI. This is typically used + * in combination with quick-navigation where no search UI should + * be presented. + */ + hideInput: boolean; } export interface IInputBox extends IQuickInput { diff --git a/src/vs/base/test/common/fuzzyScorer.test.ts b/src/vs/base/test/common/fuzzyScorer.test.ts index 43cb8756d3e..b9c84a730bc 100644 --- a/src/vs/base/test/common/fuzzyScorer.test.ts +++ b/src/vs/base/test/common/fuzzyScorer.test.ts @@ -8,6 +8,7 @@ import * as scorer from 'vs/base/common/fuzzyScorer'; import { URI } from 'vs/base/common/uri'; import { basename, dirname, sep } from 'vs/base/common/path'; import { isWindows } from 'vs/base/common/platform'; +import { Schemas } from 'vs/base/common/network'; class ResourceAccessorClass implements scorer.IItemAccessor { @@ -49,8 +50,8 @@ function scoreItem(item: T, query: string, fuzzy: boolean, accessor: scorer.I return scorer.scoreItem(item, scorer.prepareQuery(query), fuzzy, accessor, cache); } -function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache, fallbackComparer?: (itemA: T, itemB: T, query: scorer.IPreparedQuery, accessor: scorer.IItemAccessor) => number): number { - return scorer.compareItemsByScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache, fallbackComparer as any); +function compareItemsByScore(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor, cache: scorer.ScorerCache): number { + return scorer.compareItemsByScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, cache); } const NullAccessor = new NullAccessorClass(); @@ -279,6 +280,19 @@ suite('Fuzzy Scorer', () => { assert.ok(!res.score); }); + test('scoreItem - match if using slash or backslash (local, remote resource)', function () { + const localResource = URI.file('abcde/super/duper'); + const remoteResource = URI.from({ scheme: Schemas.vscodeRemote, path: 'abcde/super/duper' }); + + for (const resource of [localResource, remoteResource]) { + let res = scoreItem(resource, 'abcde\\super\\duper', true, ResourceAccessor, cache); + assert.ok(res.score); + + res = scoreItem(resource, 'abcde/super/duper', true, ResourceAccessor, cache); + assert.ok(res.score); + } + }); + test('compareItemsByScore - identity', function () { const resourceA = URI.file('/some/path/fileA.txt'); const resourceB = URI.file('/some/path/other/fileB.txt'); @@ -509,33 +523,13 @@ suite('Fuzzy Scorer', () => { assert.equal(res[2], resourceC); }); - test('compareFilesByScore - allow to provide fallback sorter (bug #31591)', function () { - const resourceA = URI.file('virtual/vscode.d.ts'); - const resourceB = URI.file('vscode/src/vs/vscode.d.ts'); + test('compareFilesByScore - prefer matches in label over description if scores are otherwise equal', function () { + const resourceA = URI.file('parts/quick/arrow-left-dark.svg'); + const resourceB = URI.file('parts/quickopen/quickopen.ts'); - let query = 'vscode'; + let query = 'partsquick'; - let res = [resourceA, resourceB].sort((r1, r2) => { - return compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => { - if (r1 as any /* TS fail */ === resourceA) { - return -1; - } - - return 1; - }); - }); - assert.equal(res[0], resourceA); - assert.equal(res[1], resourceB); - - res = [resourceB, resourceA].sort((r1, r2) => { - return compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache, (r1, r2, query, ResourceAccessor) => { - if (r1 as any /* TS fail */ === resourceB) { - return -1; - } - - return 1; - }); - }); + let res = [resourceA, resourceB].sort((r1, r2) => compareItemsByScore(r1, r2, query, true, ResourceAccessor, cache)); assert.equal(res[0], resourceB); assert.equal(res[1], resourceA); }); diff --git a/src/vs/base/test/common/history.test.ts b/src/vs/base/test/common/history.test.ts index fc32e74324b..8b92348be6f 100644 --- a/src/vs/base/test/common/history.test.ts +++ b/src/vs/base/test/common/history.test.ts @@ -106,6 +106,40 @@ suite('History Navigator', () => { assert.deepEqual(['2', '3', '1'], toArray(testObject)); }); + test('previous returns null if the current position is the first one', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); + + testObject.first(); + + assert.deepEqual(testObject.previous(), null); + }); + + test('previous returns object if the current position is not the first one', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); + + testObject.first(); + testObject.next(); + + assert.deepEqual(testObject.previous(), '1'); + }); + + test('next returns null if the current position is the last one', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); + + testObject.last(); + + assert.deepEqual(testObject.next(), null); + }); + + test('next returns object if the current position is not the last one', () => { + const testObject = new HistoryNavigator(['1', '2', '3']); + + testObject.last(); + testObject.previous(); + + assert.deepEqual(testObject.next(), '3'); + }); + test('clear', () => { const testObject = new HistoryNavigator(['a', 'b', 'c']); assert.equal(testObject.previous(), 'c'); diff --git a/src/vs/base/test/common/resources.test.ts b/src/vs/base/test/common/resources.test.ts index b45ea4fc2f8..9732aacf05a 100644 --- a/src/vs/base/test/common/resources.test.ts +++ b/src/vs/base/test/common/resources.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, relativePath, removeTrailingPathSeparator, hasTrailingPathSeparator, resolvePath, addTrailingPathSeparator } from 'vs/base/common/resources'; +import { dirname, basename, distinctParents, joinPath, isEqual, isEqualOrParent, hasToIgnoreCase, normalizePath, isAbsolutePath, relativePath, removeTrailingPathSeparator, hasTrailingPathSeparator, resolvePath, addTrailingPathSeparator, getComparisonKey } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { isWindows } from 'vs/base/common/platform'; import { toSlashes } from 'vs/base/common/extpath'; @@ -66,6 +66,8 @@ suite('Resources', () => { // does not explode (https://github.com/Microsoft/vscode/issues/41987) dirname(URI.from({ scheme: 'file', authority: '/users/someone/portal.h' })); + + assert.equal(dirname(URI.parse('foo://a/b/c?q')).toString(), 'foo://a/b?q'); }); test('basename', () => { @@ -156,6 +158,7 @@ suite('Resources', () => { assert.equal(normalizePath(URI.parse('foo://a/foo/foo/./../some/../bar')).toString(), 'foo://a/foo/bar'); assert.equal(normalizePath(URI.parse('foo://a')).toString(), 'foo://a'); assert.equal(normalizePath(URI.parse('foo://a/')).toString(), 'foo://a/'); + assert.equal(normalizePath(URI.parse('foo://a/foo/./bar?q=1')).toString(), URI.parse('foo://a/foo/bar?q%3D1').toString()); }); test('isAbsolute', () => { @@ -233,7 +236,7 @@ suite('Resources', () => { }); function assertEqualURI(actual: URI, expected: URI, message?: string) { - if (!isEqual(expected, actual)) { + if (!isEqual(expected, actual, hasToIgnoreCase(expected), false)) { assert.equal(actual.toString(), expected.toString(), message); } } @@ -259,7 +262,7 @@ suite('Resources', () => { assertRelativePath(URI.parse('foo://a'), URI.parse('foo://a'), ''); assertRelativePath(URI.parse('foo://a/'), URI.parse('foo://a/'), ''); assertRelativePath(URI.parse('foo://a/'), URI.parse('foo://a'), ''); - assertRelativePath(URI.parse('foo://a/foo?q'), URI.parse('foo://a/foo/bar#h'), 'bar'); + assertRelativePath(URI.parse('foo://a/foo?q'), URI.parse('foo://a/foo/bar#h'), 'bar', true); assertRelativePath(URI.parse('foo://'), URI.parse('foo://a/b'), undefined); assertRelativePath(URI.parse('foo://a2/b'), URI.parse('foo://a/b'), undefined); assertRelativePath(URI.parse('goo://a/b'), URI.parse('foo://a/b'), undefined); @@ -343,26 +346,44 @@ suite('Resources', () => { }); + function assertIsEqual(u1: URI, u2: URI, ignoreCase: boolean, expected: boolean) { + assert.equal(isEqual(u1, u2, ignoreCase), expected, `${u1.toString()}${expected ? '===' : '!=='}${u2.toString()}`); + assert.equal(getComparisonKey(u1, ignoreCase) === getComparisonKey(u2, ignoreCase), expected, `comparison keys ${u1.toString()}, ${u2.toString()}`); + assert.equal(isEqualOrParent(u1, u2, ignoreCase), expected, `isEqualOrParent ${u1.toString()}, ${u2.toString()}`); + } + + test('isEqual', () => { let fileURI = isWindows ? URI.file('c:\\foo\\bar') : URI.file('/foo/bar'); let fileURI2 = isWindows ? URI.file('C:\\foo\\Bar') : URI.file('/foo/Bar'); - assert.equal(isEqual(fileURI, fileURI, true), true); - assert.equal(isEqual(fileURI, fileURI, false), true); - assert.equal(isEqual(fileURI, fileURI, hasToIgnoreCase(fileURI)), true); - assert.equal(isEqual(fileURI, fileURI2, true), true); - assert.equal(isEqual(fileURI, fileURI2, false), false); + assertIsEqual(fileURI, fileURI, true, true); + assertIsEqual(fileURI, fileURI, false, true); + assertIsEqual(fileURI, fileURI, hasToIgnoreCase(fileURI), true); + assertIsEqual(fileURI, fileURI2, true, true); + assertIsEqual(fileURI, fileURI2, false, false); let fileURI3 = URI.parse('foo://server:453/foo/bar'); let fileURI4 = URI.parse('foo://server:453/foo/Bar'); - assert.equal(isEqual(fileURI3, fileURI3, true), true); - assert.equal(isEqual(fileURI3, fileURI3, false), true); - assert.equal(isEqual(fileURI3, fileURI3, hasToIgnoreCase(fileURI3)), true); - assert.equal(isEqual(fileURI3, fileURI4, true), true); - assert.equal(isEqual(fileURI3, fileURI4, false), false); + assertIsEqual(fileURI3, fileURI3, true, true); + assertIsEqual(fileURI3, fileURI3, false, true); + assertIsEqual(fileURI3, fileURI3, hasToIgnoreCase(fileURI3), true); + assertIsEqual(fileURI3, fileURI4, true, true); + assertIsEqual(fileURI3, fileURI4, false, false); - assert.equal(isEqual(fileURI, fileURI3, true), false); + assertIsEqual(fileURI, fileURI3, true, false); - assert.equal(isEqual(URI.parse('foo://server'), URI.parse('foo://server/')), true); + assertIsEqual(URI.parse('foo://server'), URI.parse('foo://server/'), true, true); + assertIsEqual(URI.parse('foo://server/foo'), URI.parse('foo://server/foo/'), true, false); + assertIsEqual(URI.parse('foo://server/foo'), URI.parse('foo://server/foo?'), true, true); + + let fileURI5 = URI.parse('foo://server:453/foo/bar?q=1'); + let fileURI6 = URI.parse('foo://server:453/foo/bar#xy'); + + assertIsEqual(fileURI5, fileURI5, true, true); + assertIsEqual(fileURI5, fileURI3, true, false); + assertIsEqual(fileURI6, fileURI6, true, true); + assertIsEqual(fileURI6, fileURI5, true, false); + assertIsEqual(fileURI6, fileURI3, true, true); }); test('isEqualOrParent', () => { @@ -388,5 +409,12 @@ suite('Resources', () => { assert.equal(isEqualOrParent(fileURI3, fileURI4, false), true, '14'); assert.equal(isEqualOrParent(fileURI3, fileURI, true), false, '15'); assert.equal(isEqualOrParent(fileURI5, fileURI5, true), true, '16'); + + let fileURI6 = URI.parse('foo://server:453/foo?q=1'); + let fileURI7 = URI.parse('foo://server:453/foo/bar?q=1'); + assert.equal(isEqualOrParent(fileURI6, fileURI5, true), false, '17'); + assert.equal(isEqualOrParent(fileURI6, fileURI6, true), true, '18'); + assert.equal(isEqualOrParent(fileURI7, fileURI6, true), true, '19'); + assert.equal(isEqualOrParent(fileURI7, fileURI5, true), false, '20'); }); }); diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 495a1ddf636..519c50af729 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -503,4 +503,48 @@ suite('URI', () => { // } // console.profileEnd(); }); + + test('URI#joinPath', function () { + + function assertJoined(base: string, fragment: string, expected: string, checkWithUrl: boolean = true) { + const baseUri = URI.parse(base); + const newUri = URI.joinPath(baseUri, fragment); + const actual = newUri.toString(true); + assert.equal(actual, expected); + + if (checkWithUrl) { + const actualUrl = new URL(fragment, base).href; + assert.equal(actualUrl, expected); + } + } + + assertJoined(('file://server/share/c:/'), '../../bazz', 'file://server/bazz'); + assertJoined(('file://server/share/c:'), '../../bazz', 'file://server/bazz'); + assertJoined(('file:///foo/'), '../../bazz', 'file:///bazz'); + assertJoined(('file:///foo'), '../../bazz', 'file:///bazz'); + assertJoined(('file:///foo'), '../../bazz', 'file:///bazz'); + assertJoined(('file:///c:/foo/'), '../../bazz', 'file:///bazz', false); + assertJoined(('file://ser/foo/'), '../../bazz', 'file://ser/bazz'); + assertJoined(('file://ser/foo'), '../../bazz', 'file://ser/bazz'); + assertJoined(('file:///foo/bar/'), './bazz', 'file:///foo/bar/bazz'); + assertJoined(('file:///foo/bar'), './bazz', 'file:///foo/bar/bazz', false); + assertJoined(('file:///foo/bar'), 'bazz', 'file:///foo/bar/bazz', false); + + // "auto-path" scheme + assertJoined(('file:'), 'bazz', 'file:///bazz'); + assertJoined(('http://domain'), 'bazz', 'http://domain/bazz'); + assertJoined(('https://domain'), 'bazz', 'https://domain/bazz'); + assertJoined(('http:'), 'bazz', 'http:/bazz', false); + assertJoined(('https:'), 'bazz', 'https:/bazz', false); + + // no "auto-path" scheme with and w/o paths + assertJoined(('foo:/'), 'bazz', 'foo:/bazz'); + assertJoined(('foo://bar/'), 'bazz', 'foo://bar/bazz'); + + // no "auto-path" + no path -> error + assert.throws(() => assertJoined(('foo:'), 'bazz', '')); + assert.throws(() => new URL('bazz', 'foo:')); + assert.throws(() => assertJoined(('foo://bar'), 'bazz', '')); + assert.throws(() => new URL('bazz', 'foo://bar')); + }); }); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index f7650c925e3..f8ec9a33d2f 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -52,7 +52,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; -import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, UserDataSyncStoreServiceChannel, UserDataSyncBackupStoreServiceChannel, StorageKeysSyncRegistryChannelClient } from 'vs/platform/userDataSync/common/userDataSyncIpc'; +import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; import { IElectronService } from 'vs/platform/electron/node/electron'; import { LoggerService } from 'vs/platform/log/node/loggerService'; import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog'; @@ -222,14 +222,6 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat const authTokenChannel = new AuthenticationTokenServiceChannel(authTokenService); server.registerChannel('authToken', authTokenChannel); - const userDataSyncStoreService = accessor.get(IUserDataSyncStoreService); - const userDataSyncStoreServiceChannel = new UserDataSyncStoreServiceChannel(userDataSyncStoreService); - server.registerChannel('userDataSyncStoreService', userDataSyncStoreServiceChannel); - - const userDataSyncBackupStoreService = accessor.get(IUserDataSyncBackupStoreService); - const userDataSyncBackupStoreServiceChannel = new UserDataSyncBackupStoreServiceChannel(userDataSyncBackupStoreService); - server.registerChannel('userDataSyncBackupStoreService', userDataSyncBackupStoreServiceChannel); - const userDataSyncService = accessor.get(IUserDataSyncService); const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService); server.registerChannel('userDataSync', userDataSyncChannel); diff --git a/src/vs/editor/browser/controller/textAreaHandler.ts b/src/vs/editor/browser/controller/textAreaHandler.ts index 043bd0eb018..27ab06f3d21 100644 --- a/src/vs/editor/browser/controller/textAreaHandler.ts +++ b/src/vs/editor/browser/controller/textAreaHandler.ts @@ -349,7 +349,7 @@ export class TextAreaHandler extends ViewPart { private _getAriaLabel(options: IComputedEditorOptions): string { const accessibilitySupport = options.get(EditorOption.accessibilitySupport); if (accessibilitySupport === AccessibilitySupport.Disabled) { - return nls.localize('accessibilityOffAriaLabel', "The editor is not accessible at this time. Press Alt+F1 for options."); + return nls.localize('accessibilityOffAriaLabel', "The editor is not accessible at this time. Press {0} for options.", platform.isLinux ? 'Shift+Alt+F1' : 'Alt+F1'); } return options.get(EditorOption.ariaLabel); } diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index e83c3d72cd9..d9ee8f481eb 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -30,6 +30,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { Constants } from 'vs/base/common/uint'; const DIFF_LINES_PADDING = 3; @@ -124,16 +125,6 @@ export class DiffReview extends Disposable { } this._render(); })); - this._register(diffEditor.getOriginalEditor().onDidFocusEditorWidget(() => { - if (this._isVisible) { - this.hide(); - } - })); - this._register(diffEditor.getModifiedEditor().onDidFocusEditorWidget(() => { - if (this._isVisible) { - this.hide(); - } - })); this._register(dom.addStandardDisposableListener(this.domNode.domNode, 'click', (e) => { e.preventDefault(); @@ -209,7 +200,9 @@ export class DiffReview extends Disposable { } index = index % this._diffs.length; - this._diffEditor.setPosition(new Position(this._diffs[index].entries[0].modifiedLineStart, 1)); + const entries = this._diffs[index].entries; + this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1)); + this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: Constants.MAX_SAFE_SMALL_INTEGER, endLineNumber: entries[entries.length - 1].modifiedLineEnd }); this._isVisible = true; this._diffEditor.doLayout(); this._render(); @@ -242,7 +235,9 @@ export class DiffReview extends Disposable { } index = index % this._diffs.length; - this._diffEditor.setPosition(new Position(this._diffs[index].entries[0].modifiedLineStart, 1)); + const entries = this._diffs[index].entries; + this._diffEditor.setPosition(new Position(entries[0].modifiedLineStart, 1)); + this._diffEditor.setSelection({ startColumn: 1, startLineNumber: entries[0].modifiedLineStart, endColumn: Constants.MAX_SAFE_SMALL_INTEGER, endLineNumber: entries[entries.length - 1].modifiedLineEnd }); this._isVisible = true; this._diffEditor.doLayout(); this._render(); @@ -551,6 +546,7 @@ export class DiffReview extends Disposable { let container = document.createElement('div'); container.className = 'diff-review-table'; container.setAttribute('role', 'list'); + container.setAttribute('aria-label', 'Difference review. Use "Stage | Unstage | Revert Selected Ranges" commands'); Configuration.applyFontInfoSlow(container, modifiedOptions.get(EditorOption.fontInfo)); let minOriginalLine = 0; diff --git a/src/vs/editor/common/core/stringBuilder.ts b/src/vs/editor/common/core/stringBuilder.ts index 661fd6642e2..1ae6347c00e 100644 --- a/src/vs/editor/common/core/stringBuilder.ts +++ b/src/vs/editor/common/core/stringBuilder.ts @@ -4,8 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as strings from 'vs/base/common/strings'; +import * as platform from 'vs/base/common/platform'; +import * as buffer from 'vs/base/common/buffer'; -declare const TextDecoder: any; // TODO@TypeScript +declare const TextDecoder: { + prototype: TextDecoder; + new(label?: string): TextDecoder; +}; interface TextDecoder { decode(view: Uint16Array): string; } @@ -18,17 +23,42 @@ export interface IStringBuilder { appendASCIIString(str: string): void; } +let _platformTextDecoder: TextDecoder | null; +function getPlatformTextDecoder(): TextDecoder { + if (!_platformTextDecoder) { + _platformTextDecoder = new TextDecoder(platform.isLittleEndian() ? 'UTF-16LE' : 'UTF-16BE'); + } + return _platformTextDecoder; +} + export let createStringBuilder: (capacity: number) => IStringBuilder; +export let decodeUTF16LE: (source: Uint8Array, offset: number, len: number) => string; if (typeof TextDecoder !== 'undefined') { createStringBuilder = (capacity) => new StringBuilder(capacity); + decodeUTF16LE = standardDecodeUTF16LE; } else { createStringBuilder = (capacity) => new CompatStringBuilder(); + decodeUTF16LE = compatDecodeUTF16LE; +} + +function standardDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string { + const view = new Uint16Array(source.buffer, offset, len); + return getPlatformTextDecoder().decode(view); +} + +function compatDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string { + let result: string[] = []; + let resultLen = 0; + for (let i = 0; i < len; i++) { + const charCode = buffer.readUInt16LE(source, offset); offset += 2; + result[resultLen++] = String.fromCharCode(charCode); + } + return result.join(''); } class StringBuilder implements IStringBuilder { - private readonly _decoder: TextDecoder; private readonly _capacity: number; private readonly _buffer: Uint16Array; @@ -36,7 +66,6 @@ class StringBuilder implements IStringBuilder { private _bufferLength: number; constructor(capacity: number) { - this._decoder = new TextDecoder('UTF-16LE'); this._capacity = capacity | 0; this._buffer = new Uint16Array(this._capacity); @@ -63,7 +92,7 @@ class StringBuilder implements IStringBuilder { } const view = new Uint16Array(this._buffer.buffer, 0, this._bufferLength); - return this._decoder.decode(view); + return getPlatformTextDecoder().decode(view); } private _flushBuffer(): void { diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index a74dc9216df..ff16a9a93cc 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -15,6 +15,7 @@ import { SearchData } from 'vs/editor/common/model/textModelSearch'; import { LanguageId, LanguageIdentifier, FormattingOptions } from 'vs/editor/common/modes'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { MultilineTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore'; +import { TextChange } from 'vs/editor/common/model/textChange'; /** * Vertical Lane in the overview ruler of the editor. @@ -373,21 +374,13 @@ export interface IValidEditOperation { */ range: Range; /** - * The text to replace with. This can be null to emulate a simple delete. + * The text to replace with. This can be empty to emulate a simple delete. */ - text: string | null; + text: string; /** - * This indicates that this operation has "insert" semantics. - * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. + * @internal */ - forceMoveMarkers: boolean; -} - -/** - * @internal - */ -export interface IValidEditOperations { - operations: IValidEditOperation[]; + textChange: TextChange; } /** @@ -1099,9 +1092,11 @@ export interface ITextModel { * Edit the model without adding the edits to the undo stack. * This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way. * @param operations The edit operations. - * @return The inverse edit operations, that, when applied, will bring the model back to the previous state. + * @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state. */ - applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[]; + applyEdits(operations: IIdentifiedSingleEditOperation[]): void; + applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void; + applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[]; /** * Change the end of line sequence without recording in the undo stack. @@ -1112,7 +1107,12 @@ export interface ITextModel { /** * @internal */ - _applyUndoRedoEdits(edits: IValidEditOperations[], eol: EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): IValidEditOperations[]; + _applyUndo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void; + + /** + * @internal + */ + _applyRedo(changes: TextChange[], eol: EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void; /** * Undo edit operations until the first previous stop point created by `pushStackElement`. @@ -1291,7 +1291,7 @@ export interface ITextBuffer { getLineLastNonWhitespaceColumn(lineNumber: number): number; setEOL(newEOL: '\r\n' | '\n'): void; - applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult; + applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult; findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[]; } @@ -1301,7 +1301,7 @@ export interface ITextBuffer { export class ApplyEditsResult { constructor( - public readonly reverseEdits: IValidEditOperation[], + public readonly reverseEdits: IValidEditOperation[] | null, public readonly changes: IInternalModelContentChange[], public readonly trimAutoWhitespaceLineNumbers: number[] | null ) { } diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index c0aee2abe10..622557ca9af 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -6,69 +6,209 @@ import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Selection } from 'vs/editor/common/core/selection'; -import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel, IValidEditOperations } from 'vs/editor/common/model'; +import { EndOfLineSequence, ICursorStateComputer, IIdentifiedSingleEditOperation, IValidEditOperation, ITextModel } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import { IUndoRedoService, IResourceUndoRedoElement, UndoRedoElementType, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo'; import { URI } from 'vs/base/common/uri'; import { getComparisonKey as uriGetComparisonKey } from 'vs/base/common/resources'; +import { TextChange, compressConsecutiveTextChanges } from 'vs/editor/common/model/textChange'; +import * as buffer from 'vs/base/common/buffer'; -export class EditStackElement implements IResourceUndoRedoElement { +class SingleModelEditStackData { - public readonly type = UndoRedoElementType.Resource; - public readonly label: string; - private _isOpen: boolean; - public readonly model: ITextModel; - private readonly _beforeVersionId: number; - private readonly _beforeEOL: EndOfLineSequence; - private readonly _beforeCursorState: Selection[] | null; - private _afterVersionId: number; - private _afterEOL: EndOfLineSequence; - private _afterCursorState: Selection[] | null; - private _edits: IValidEditOperations[]; - - public get resource(): URI { - return this.model.uri; + public static create(model: ITextModel, beforeCursorState: Selection[] | null): SingleModelEditStackData { + const alternativeVersionId = model.getAlternativeVersionId(); + const eol = getModelEOL(model); + return new SingleModelEditStackData( + alternativeVersionId, + alternativeVersionId, + eol, + eol, + beforeCursorState, + beforeCursorState, + [] + ); } - constructor(model: ITextModel, beforeCursorState: Selection[] | null) { - this.label = nls.localize('edit', "Typing"); - this._isOpen = true; - this.model = model; - this._beforeVersionId = this.model.getAlternativeVersionId(); - this._beforeEOL = getModelEOL(this.model); - this._beforeCursorState = beforeCursorState; - this._afterVersionId = this._beforeVersionId; - this._afterEOL = this._beforeEOL; - this._afterCursorState = this._beforeCursorState; - this._edits = []; - } - - public canAppend(model: ITextModel): boolean { - return (this._isOpen && this.model === model); - } + constructor( + public readonly beforeVersionId: number, + public afterVersionId: number, + public readonly beforeEOL: EndOfLineSequence, + public afterEOL: EndOfLineSequence, + public readonly beforeCursorState: Selection[] | null, + public afterCursorState: Selection[] | null, + public changes: TextChange[] + ) { } public append(model: ITextModel, operations: IValidEditOperation[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void { if (operations.length > 0) { - this._edits.push({ operations: operations }); + this.changes = compressConsecutiveTextChanges(this.changes, operations.map(op => op.textChange)); + } + this.afterEOL = afterEOL; + this.afterVersionId = afterVersionId; + this.afterCursorState = afterCursorState; + } + + private static _writeSelectionsSize(selections: Selection[] | null): number { + return 4 + 4 * 4 * (selections ? selections.length : 0); + } + + private static _writeSelections(b: Uint8Array, selections: Selection[] | null, offset: number): number { + buffer.writeUInt32BE(b, (selections ? selections.length : 0), offset); offset += 4; + if (selections) { + for (const selection of selections) { + buffer.writeUInt32BE(b, selection.selectionStartLineNumber, offset); offset += 4; + buffer.writeUInt32BE(b, selection.selectionStartColumn, offset); offset += 4; + buffer.writeUInt32BE(b, selection.positionLineNumber, offset); offset += 4; + buffer.writeUInt32BE(b, selection.positionColumn, offset); offset += 4; + } + } + return offset; + } + + private static _readSelections(b: Uint8Array, offset: number, dest: Selection[]): number { + const count = buffer.readUInt32BE(b, offset); offset += 4; + for (let i = 0; i < count; i++) { + const selectionStartLineNumber = buffer.readUInt32BE(b, offset); offset += 4; + const selectionStartColumn = buffer.readUInt32BE(b, offset); offset += 4; + const positionLineNumber = buffer.readUInt32BE(b, offset); offset += 4; + const positionColumn = buffer.readUInt32BE(b, offset); offset += 4; + dest.push(new Selection(selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn)); + } + return offset; + } + + public serialize(): ArrayBuffer { + let necessarySize = ( + + 4 // beforeVersionId + + 4 // afterVersionId + + 1 // beforeEOL + + 1 // afterEOL + + SingleModelEditStackData._writeSelectionsSize(this.beforeCursorState) + + SingleModelEditStackData._writeSelectionsSize(this.afterCursorState) + + 4 // change count + ); + for (const change of this.changes) { + necessarySize += change.writeSize(); + } + + const b = new Uint8Array(necessarySize); + let offset = 0; + buffer.writeUInt32BE(b, this.beforeVersionId, offset); offset += 4; + buffer.writeUInt32BE(b, this.afterVersionId, offset); offset += 4; + buffer.writeUInt8(b, this.beforeEOL, offset); offset += 1; + buffer.writeUInt8(b, this.afterEOL, offset); offset += 1; + offset = SingleModelEditStackData._writeSelections(b, this.beforeCursorState, offset); + offset = SingleModelEditStackData._writeSelections(b, this.afterCursorState, offset); + buffer.writeUInt32BE(b, this.changes.length, offset); offset += 4; + for (const change of this.changes) { + offset = change.write(b, offset); + } + return b.buffer; + } + + public static deserialize(source: ArrayBuffer): SingleModelEditStackData { + const b = new Uint8Array(source); + let offset = 0; + const beforeVersionId = buffer.readUInt32BE(b, offset); offset += 4; + const afterVersionId = buffer.readUInt32BE(b, offset); offset += 4; + const beforeEOL = buffer.readUInt8(b, offset); offset += 1; + const afterEOL = buffer.readUInt8(b, offset); offset += 1; + const beforeCursorState: Selection[] = []; + offset = SingleModelEditStackData._readSelections(b, offset, beforeCursorState); + const afterCursorState: Selection[] = []; + offset = SingleModelEditStackData._readSelections(b, offset, afterCursorState); + const changeCount = buffer.readUInt32BE(b, offset); offset += 4; + const changes: TextChange[] = []; + for (let i = 0; i < changeCount; i++) { + offset = TextChange.read(b, offset, changes); + } + return new SingleModelEditStackData( + beforeVersionId, + afterVersionId, + beforeEOL, + afterEOL, + beforeCursorState, + afterCursorState, + changes + ); + } +} + +export class SingleModelEditStackElement implements IResourceUndoRedoElement { + + public model: ITextModel | URI; + private _data: SingleModelEditStackData | ArrayBuffer; + + public get type(): UndoRedoElementType.Resource { + return UndoRedoElementType.Resource; + } + + public get resource(): URI { + if (URI.isUri(this.model)) { + return this.model; + } + return this.model.uri; + } + + public get label(): string { + return nls.localize('edit', "Typing"); + } + + constructor(model: ITextModel, beforeCursorState: Selection[] | null) { + this.model = model; + this._data = SingleModelEditStackData.create(model, beforeCursorState); + } + + public setModel(model: ITextModel | URI): void { + this.model = model; + } + + public canAppend(model: ITextModel): boolean { + return (this.model === model && this._data instanceof SingleModelEditStackData); + } + + public append(model: ITextModel, operations: IValidEditOperation[], afterEOL: EndOfLineSequence, afterVersionId: number, afterCursorState: Selection[] | null): void { + if (this._data instanceof SingleModelEditStackData) { + this._data.append(model, operations, afterEOL, afterVersionId, afterCursorState); } - this._afterEOL = afterEOL; - this._afterVersionId = afterVersionId; - this._afterCursorState = afterCursorState; } public close(): void { - this._isOpen = false; + if (this._data instanceof SingleModelEditStackData) { + this._data = this._data.serialize(); + } } public undo(): void { - this._isOpen = false; - this._edits.reverse(); - this._edits = this.model._applyUndoRedoEdits(this._edits, this._beforeEOL, true, false, this._beforeVersionId, this._beforeCursorState); + if (URI.isUri(this.model)) { + // don't have a model + throw new Error(`Invalid SingleModelEditStackElement`); + } + if (this._data instanceof SingleModelEditStackData) { + this._data = this._data.serialize(); + } + const data = SingleModelEditStackData.deserialize(this._data); + this.model._applyUndo(data.changes, data.beforeEOL, data.beforeVersionId, data.beforeCursorState); } public redo(): void { - this._edits.reverse(); - this._edits = this.model._applyUndoRedoEdits(this._edits, this._afterEOL, false, true, this._afterVersionId, this._afterCursorState); + if (URI.isUri(this.model)) { + // don't have a model + throw new Error(`Invalid SingleModelEditStackElement`); + } + if (this._data instanceof SingleModelEditStackData) { + this._data = this._data.serialize(); + } + const data = SingleModelEditStackData.deserialize(this._data); + this.model._applyRedo(data.changes, data.afterEOL, data.afterVersionId, data.afterCursorState); + } + + public heapSize(): number { + if (this._data instanceof SingleModelEditStackData) { + this._data = this._data.serialize(); + } + return this._data.byteLength + 168/*heap overhead*/; } } @@ -78,27 +218,34 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement { public readonly label: string; private _isOpen: boolean; - private readonly _editStackElementsArr: EditStackElement[]; - private readonly _editStackElementsMap: Map; + private readonly _editStackElementsArr: SingleModelEditStackElement[]; + private readonly _editStackElementsMap: Map; public get resources(): readonly URI[] { - return this._editStackElementsArr.map(editStackElement => editStackElement.model.uri); + return this._editStackElementsArr.map(editStackElement => editStackElement.resource); } constructor( label: string, - editStackElements: EditStackElement[] + editStackElements: SingleModelEditStackElement[] ) { this.label = label; this._isOpen = true; this._editStackElementsArr = editStackElements.slice(0); - this._editStackElementsMap = new Map(); + this._editStackElementsMap = new Map(); for (const editStackElement of this._editStackElementsArr) { - const key = uriGetComparisonKey(editStackElement.model.uri); + const key = uriGetComparisonKey(editStackElement.resource); this._editStackElementsMap.set(key, editStackElement); } } + public setModel(model: ITextModel | URI): void { + const key = uriGetComparisonKey(URI.isUri(model) ? model : model.uri); + if (this._editStackElementsMap.has(key)) { + this._editStackElementsMap.get(key)!.setModel(model); + } + } + public canAppend(model: ITextModel): boolean { if (!this._isOpen) { return false; @@ -135,11 +282,22 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement { } } + public heapSize(resource: URI): number { + const key = uriGetComparisonKey(resource); + if (this._editStackElementsMap.has(key)) { + const editStackElement = this._editStackElementsMap.get(key)!; + return editStackElement.heapSize(); + } + return 0; + } + public split(): IResourceUndoRedoElement[] { return this._editStackElementsArr; } } +export type EditStackElement = SingleModelEditStackElement | MultiModelEditStackElement; + function getModelEOL(model: ITextModel): EndOfLineSequence { const eol = model.getEOL(); if (eol === '\n') { @@ -149,11 +307,11 @@ function getModelEOL(model: ITextModel): EndOfLineSequence { } } -function isKnownStackElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null): element is EditStackElement | MultiModelEditStackElement { +function isKnownStackElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null): element is EditStackElement { if (!element) { return false; } - return ((element instanceof EditStackElement) || (element instanceof MultiModelEditStackElement)); + return ((element instanceof SingleModelEditStackElement) || (element instanceof MultiModelEditStackElement)); } export class EditStack { @@ -177,12 +335,12 @@ export class EditStack { this._undoRedoService.removeElements(this._model.uri); } - private _getOrCreateEditStackElement(beforeCursorState: Selection[] | null): EditStackElement | MultiModelEditStackElement { + private _getOrCreateEditStackElement(beforeCursorState: Selection[] | null): EditStackElement { const lastElement = this._undoRedoService.getLastElement(this._model.uri); if (isKnownStackElement(lastElement) && lastElement.canAppend(this._model)) { return lastElement; } - const newElement = new EditStackElement(this._model, beforeCursorState); + const newElement = new SingleModelEditStackElement(this._model, beforeCursorState); this._undoRedoService.pushElement(newElement); return newElement; } @@ -195,7 +353,7 @@ export class EditStack { public pushEditOperation(beforeCursorState: Selection[] | null, editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null { const editStackElement = this._getOrCreateEditStackElement(beforeCursorState); - const inverseEditOperations = this._model.applyEdits(editOperations); + const inverseEditOperations = this._model.applyEdits(editOperations, true); const afterCursorState = EditStack._computeCursorState(cursorStateComputer, inverseEditOperations); editStackElement.append(this._model, inverseEditOperations, getModelEOL(this._model), this._model.getAlternativeVersionId(), afterCursorState); return afterCursorState; diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts index 05d11060137..e8e737a23c3 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase.ts @@ -269,7 +269,7 @@ export class PieceTreeBase { protected _buffers!: StringBuffer[]; // 0 is change buffer, others are readonly original buffer. protected _lineCnt!: number; protected _length!: number; - protected _EOL!: string; + protected _EOL!: '\r\n' | '\n'; protected _EOLLength!: number; protected _EOLNormalized!: boolean; private _lastChangeBufferPos!: BufferCursor; @@ -351,7 +351,7 @@ export class PieceTreeBase { } // #region Buffer API - public getEOL(): string { + public getEOL(): '\r\n' | '\n' { return this._EOL; } diff --git a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts index 0d9c539ff8a..3dd4acda9d6 100644 --- a/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts +++ b/src/vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.ts @@ -9,6 +9,8 @@ import { Range } from 'vs/editor/common/core/range'; import { ApplyEditsResult, EndOfLinePreference, FindMatch, IInternalModelContentChange, ISingleEditOperationIdentifier, ITextBuffer, ITextSnapshot, ValidAnnotatedEditOperation, IValidEditOperation } from 'vs/editor/common/model'; import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeBase'; import { SearchData } from 'vs/editor/common/model/textModelSearch'; +import { countEOL, StringEOL } from 'vs/editor/common/model/tokensStore'; +import { TextChange } from 'vs/editor/common/model/textChange'; export interface IValidatedEditOperation { sortIndex: number; @@ -16,7 +18,10 @@ export interface IValidatedEditOperation { range: Range; rangeOffset: number; rangeLength: number; - lines: string[] | null; + text: string; + eolCount: number; + firstLineLength: number; + lastLineLength: number; forceMoveMarkers: boolean; isAutoWhitespaceEdit: boolean; } @@ -60,7 +65,7 @@ export class PieceTreeTextBuffer implements ITextBuffer { public getBOM(): string { return this._BOM; } - public getEOL(): string { + public getEOL(): '\r\n' | '\n' { return this._pieceTree.getEOL(); } @@ -201,7 +206,7 @@ export class PieceTreeTextBuffer implements ITextBuffer { this._pieceTree.setEOL(newEOL); } - public applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean): ApplyEditsResult { + public applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult { let mightContainRTL = this._mightContainRTL; let mightContainNonBasicASCII = this._mightContainNonBasicASCII; let canReduceOperations = true; @@ -220,13 +225,34 @@ export class PieceTreeTextBuffer implements ITextBuffer { if (!mightContainNonBasicASCII && op.text) { mightContainNonBasicASCII = !strings.isBasicASCII(op.text); } + + let validText = ''; + let eolCount = 0; + let firstLineLength = 0; + let lastLineLength = 0; + if (op.text) { + let strEOL: StringEOL; + [eolCount, firstLineLength, lastLineLength, strEOL] = countEOL(op.text); + + const bufferEOL = this.getEOL(); + const expectedStrEOL = (bufferEOL === '\r\n' ? StringEOL.CRLF : StringEOL.LF); + if (strEOL === StringEOL.Unknown || strEOL === expectedStrEOL) { + validText = op.text; + } else { + validText = op.text.replace(/\r\n|\r|\n/g, bufferEOL); + } + } + operations[i] = { sortIndex: i, identifier: op.identifier || null, range: validatedRange, rangeOffset: this.getOffsetAt(validatedRange.startLineNumber, validatedRange.startColumn), rangeLength: this.getValueLengthInRange(validatedRange), - lines: op.text ? op.text.split(/\r\n|\r|\n/) : null, + text: validText, + eolCount: eolCount, + firstLineLength: firstLineLength, + lastLineLength: lastLineLength, forceMoveMarkers: Boolean(op.forceMoveMarkers), isAutoWhitespaceEdit: op.isAutoWhitespaceEdit || false }; @@ -254,46 +280,56 @@ export class PieceTreeTextBuffer implements ITextBuffer { } // Delta encode operations - let reverseRanges = PieceTreeTextBuffer._getInverseEditRanges(operations); + let reverseRanges = (computeUndoEdits || recordTrimAutoWhitespace ? PieceTreeTextBuffer._getInverseEditRanges(operations) : []); let newTrimAutoWhitespaceCandidates: { lineNumber: number, oldContent: string }[] = []; + if (recordTrimAutoWhitespace) { + for (let i = 0; i < operations.length; i++) { + let op = operations[i]; + let reverseRange = reverseRanges[i]; - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; - - if (recordTrimAutoWhitespace && op.isAutoWhitespaceEdit && op.range.isEmpty()) { - // Record already the future line numbers that might be auto whitespace removal candidates on next edit - for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { - let currentLineContent = ''; - if (lineNumber === reverseRange.startLineNumber) { - currentLineContent = this.getLineContent(op.range.startLineNumber); - if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { - continue; + if (op.isAutoWhitespaceEdit && op.range.isEmpty()) { + // Record already the future line numbers that might be auto whitespace removal candidates on next edit + for (let lineNumber = reverseRange.startLineNumber; lineNumber <= reverseRange.endLineNumber; lineNumber++) { + let currentLineContent = ''; + if (lineNumber === reverseRange.startLineNumber) { + currentLineContent = this.getLineContent(op.range.startLineNumber); + if (strings.firstNonWhitespaceIndex(currentLineContent) !== -1) { + continue; + } } + newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); } - newTrimAutoWhitespaceCandidates.push({ lineNumber: lineNumber, oldContent: currentLineContent }); } } } - let reverseOperations: IReverseSingleEditOperation[] = []; - for (let i = 0; i < operations.length; i++) { - let op = operations[i]; - let reverseRange = reverseRanges[i]; + let reverseOperations: IReverseSingleEditOperation[] | null = null; + if (computeUndoEdits) { - reverseOperations[i] = { - sortIndex: op.sortIndex, - identifier: op.identifier, - range: reverseRange, - text: this.getValueInRange(op.range), - forceMoveMarkers: op.forceMoveMarkers - }; + let reverseRangeDeltaOffset = 0; + reverseOperations = []; + for (let i = 0; i < operations.length; i++) { + const op = operations[i]; + const reverseRange = reverseRanges[i]; + const bufferText = this.getValueInRange(op.range); + const reverseRangeOffset = op.rangeOffset + reverseRangeDeltaOffset; + reverseRangeDeltaOffset += (op.text.length - bufferText.length); + + reverseOperations[i] = { + sortIndex: op.sortIndex, + identifier: op.identifier, + range: reverseRange, + text: bufferText, + textChange: new TextChange(op.rangeOffset, bufferText, reverseRangeOffset, op.text) + }; + } + + // Can only sort reverse operations when the order is not significant + if (!hasTouchingRanges) { + reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex); + } } - // Can only sort reverse operations when the order is not significant - if (!hasTouchingRanges) { - reverseOperations.sort((a, b) => a.sortIndex - b.sortIndex); - } this._mightContainRTL = mightContainRTL; this._mightContainNonBasicASCII = mightContainNonBasicASCII; @@ -350,58 +386,45 @@ export class PieceTreeTextBuffer implements ITextBuffer { } _toSingleEditOperation(operations: IValidatedEditOperation[]): IValidatedEditOperation { - let forceMoveMarkers = false, - firstEditRange = operations[0].range, - lastEditRange = operations[operations.length - 1].range, - entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn), - lastEndLineNumber = firstEditRange.startLineNumber, - lastEndColumn = firstEditRange.startColumn, - result: string[] = []; + let forceMoveMarkers = false; + const firstEditRange = operations[0].range; + const lastEditRange = operations[operations.length - 1].range; + const entireEditRange = new Range(firstEditRange.startLineNumber, firstEditRange.startColumn, lastEditRange.endLineNumber, lastEditRange.endColumn); + let lastEndLineNumber = firstEditRange.startLineNumber; + let lastEndColumn = firstEditRange.startColumn; + const result: string[] = []; for (let i = 0, len = operations.length; i < len; i++) { - let operation = operations[i], - range = operation.range; + const operation = operations[i]; + const range = operation.range; forceMoveMarkers = forceMoveMarkers || operation.forceMoveMarkers; // (1) -- Push old text - for (let lineNumber = lastEndLineNumber; lineNumber < range.startLineNumber; lineNumber++) { - if (lineNumber === lastEndLineNumber) { - result.push(this.getLineContent(lineNumber).substring(lastEndColumn - 1)); - } else { - result.push('\n'); - result.push(this.getLineContent(lineNumber)); - } - } - - if (range.startLineNumber === lastEndLineNumber) { - result.push(this.getLineContent(range.startLineNumber).substring(lastEndColumn - 1, range.startColumn - 1)); - } else { - result.push('\n'); - result.push(this.getLineContent(range.startLineNumber).substring(0, range.startColumn - 1)); - } + result.push(this.getValueInRange(new Range(lastEndLineNumber, lastEndColumn, range.startLineNumber, range.startColumn))); // (2) -- Push new text - if (operation.lines) { - for (let j = 0, lenJ = operation.lines.length; j < lenJ; j++) { - if (j !== 0) { - result.push('\n'); - } - result.push(operation.lines[j]); - } + if (operation.text.length > 0) { + result.push(operation.text); } - lastEndLineNumber = operation.range.endLineNumber; - lastEndColumn = operation.range.endColumn; + lastEndLineNumber = range.endLineNumber; + lastEndColumn = range.endColumn; } + const text = result.join(''); + const [eolCount, firstLineLength, lastLineLength] = countEOL(text); + return { sortIndex: 0, identifier: operations[0].identifier, range: entireEditRange, rangeOffset: this.getOffsetAt(entireEditRange.startLineNumber, entireEditRange.startColumn), rangeLength: this.getValueLengthInRange(entireEditRange, EndOfLinePreference.TextDefined), - lines: result.join('').split('\n'), + text: text, + eolCount: eolCount, + firstLineLength: firstLineLength, + lastLineLength: lastLineLength, forceMoveMarkers: forceMoveMarkers, isAutoWhitespaceEdit: false }; @@ -421,41 +444,26 @@ export class PieceTreeTextBuffer implements ITextBuffer { const endLineNumber = op.range.endLineNumber; const endColumn = op.range.endColumn; - if (startLineNumber === endLineNumber && startColumn === endColumn && (!op.lines || op.lines.length === 0)) { + if (startLineNumber === endLineNumber && startColumn === endColumn && op.text.length === 0) { // no-op continue; } - const deletingLinesCnt = endLineNumber - startLineNumber; - const insertingLinesCnt = (op.lines ? op.lines.length - 1 : 0); - const editingLinesCnt = Math.min(deletingLinesCnt, insertingLinesCnt); - - const text = (op.lines ? op.lines.join(this.getEOL()) : ''); - - if (text) { + if (op.text) { // replacement this._pieceTree.delete(op.rangeOffset, op.rangeLength); - this._pieceTree.insert(op.rangeOffset, text, true); + this._pieceTree.insert(op.rangeOffset, op.text, true); } else { // deletion this._pieceTree.delete(op.rangeOffset, op.rangeLength); } - if (editingLinesCnt < insertingLinesCnt) { - let newLinesContent: string[] = []; - for (let j = editingLinesCnt + 1; j <= insertingLinesCnt; j++) { - newLinesContent.push(op.lines![j]); - } - - newLinesContent[newLinesContent.length - 1] = this.getLineContent(startLineNumber + insertingLinesCnt - 1); - } - const contentChangeRange = new Range(startLineNumber, startColumn, endLineNumber, endColumn); contentChanges.push({ range: contentChangeRange, rangeLength: op.rangeLength, - text: text, + text: op.text, rangeOffset: op.rangeOffset, forceMoveMarkers: op.forceMoveMarkers }); @@ -504,18 +512,16 @@ export class PieceTreeTextBuffer implements ITextBuffer { let resultRange: Range; - if (op.lines && op.lines.length > 0) { + if (op.text.length > 0) { // the operation inserts something - let lineCount = op.lines.length; - let firstLine = op.lines[0]; - let lastLine = op.lines[lineCount - 1]; + const lineCount = op.eolCount + 1; if (lineCount === 1) { // single line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + firstLine.length); + resultRange = new Range(startLineNumber, startColumn, startLineNumber, startColumn + op.firstLineLength); } else { // multi line insert - resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, lastLine.length + 1); + resultRange = new Range(startLineNumber, startColumn, startLineNumber + lineCount - 1, op.lastLineLength + 1); } } else { // There is nothing to insert diff --git a/src/vs/editor/common/model/textChange.ts b/src/vs/editor/common/model/textChange.ts new file mode 100644 index 00000000000..5f4024cfbe6 --- /dev/null +++ b/src/vs/editor/common/model/textChange.ts @@ -0,0 +1,326 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as buffer from 'vs/base/common/buffer'; +import { decodeUTF16LE } from 'vs/editor/common/core/stringBuilder'; + +export class TextChange { + + public get oldLength(): number { + return this.oldText.length; + } + + public get oldEnd(): number { + return this.oldPosition + this.oldText.length; + } + + public get newLength(): number { + return this.newText.length; + } + + public get newEnd(): number { + return this.newPosition + this.newText.length; + } + + constructor( + public readonly oldPosition: number, + public readonly oldText: string, + public readonly newPosition: number, + public readonly newText: string + ) { } + + private static _writeStringSize(str: string): number { + return ( + 4 + 2 * str.length + ); + } + + private static _writeString(b: Uint8Array, str: string, offset: number): number { + const len = str.length; + buffer.writeUInt32BE(b, len, offset); offset += 4; + for (let i = 0; i < len; i++) { + buffer.writeUInt16LE(b, str.charCodeAt(i), offset); offset += 2; + } + return offset; + } + + private static _readString(b: Uint8Array, offset: number): string { + const len = buffer.readUInt32BE(b, offset); offset += 4; + return decodeUTF16LE(b, offset, len); + } + + public writeSize(): number { + return ( + + 4 // oldPosition + + 4 // newPosition + + TextChange._writeStringSize(this.oldText) + + TextChange._writeStringSize(this.newText) + ); + } + + public write(b: Uint8Array, offset: number): number { + buffer.writeUInt32BE(b, this.oldPosition, offset); offset += 4; + buffer.writeUInt32BE(b, this.newPosition, offset); offset += 4; + offset = TextChange._writeString(b, this.oldText, offset); + offset = TextChange._writeString(b, this.newText, offset); + return offset; + } + + public static read(b: Uint8Array, offset: number, dest: TextChange[]): number { + const oldPosition = buffer.readUInt32BE(b, offset); offset += 4; + const newPosition = buffer.readUInt32BE(b, offset); offset += 4; + const oldText = TextChange._readString(b, offset); offset += TextChange._writeStringSize(oldText); + const newText = TextChange._readString(b, offset); offset += TextChange._writeStringSize(newText); + dest.push(new TextChange(oldPosition, oldText, newPosition, newText)); + return offset; + } +} + +export function compressConsecutiveTextChanges(prevEdits: TextChange[] | null, currEdits: TextChange[]): TextChange[] { + if (prevEdits === null || prevEdits.length === 0) { + return currEdits; + } + const compressor = new TextChangeCompressor(prevEdits, currEdits); + return compressor.compress(); +} + +class TextChangeCompressor { + + private _prevEdits: TextChange[]; + private _currEdits: TextChange[]; + + private _result: TextChange[]; + private _resultLen: number; + + private _prevLen: number; + private _prevDeltaOffset: number; + + private _currLen: number; + private _currDeltaOffset: number; + + constructor(prevEdits: TextChange[], currEdits: TextChange[]) { + this._prevEdits = prevEdits; + this._currEdits = currEdits; + + this._result = []; + this._resultLen = 0; + + this._prevLen = this._prevEdits.length; + this._prevDeltaOffset = 0; + + this._currLen = this._currEdits.length; + this._currDeltaOffset = 0; + } + + public compress(): TextChange[] { + let prevIndex = 0; + let currIndex = 0; + + let prevEdit = this._getPrev(prevIndex); + let currEdit = this._getCurr(currIndex); + + while (prevIndex < this._prevLen || currIndex < this._currLen) { + + if (prevEdit === null) { + this._acceptCurr(currEdit!); + currEdit = this._getCurr(++currIndex); + continue; + } + + if (currEdit === null) { + this._acceptPrev(prevEdit); + prevEdit = this._getPrev(++prevIndex); + continue; + } + + if (currEdit.oldEnd <= prevEdit.newPosition) { + this._acceptCurr(currEdit); + currEdit = this._getCurr(++currIndex); + continue; + } + + if (prevEdit.newEnd <= currEdit.oldPosition) { + this._acceptPrev(prevEdit); + prevEdit = this._getPrev(++prevIndex); + continue; + } + + if (currEdit.oldPosition < prevEdit.newPosition) { + const [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newPosition - currEdit.oldPosition); + this._acceptCurr(e1); + currEdit = e2; + continue; + } + + if (prevEdit.newPosition < currEdit.oldPosition) { + const [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldPosition - prevEdit.newPosition); + this._acceptPrev(e1); + prevEdit = e2; + continue; + } + + // At this point, currEdit.oldPosition === prevEdit.newPosition + + let mergePrev: TextChange; + let mergeCurr: TextChange; + + if (currEdit.oldEnd === prevEdit.newEnd) { + mergePrev = prevEdit; + mergeCurr = currEdit; + prevEdit = this._getPrev(++prevIndex); + currEdit = this._getCurr(++currIndex); + } else if (currEdit.oldEnd < prevEdit.newEnd) { + const [e1, e2] = TextChangeCompressor._splitPrev(prevEdit, currEdit.oldLength); + mergePrev = e1; + mergeCurr = currEdit; + prevEdit = e2; + currEdit = this._getCurr(++currIndex); + } else { + const [e1, e2] = TextChangeCompressor._splitCurr(currEdit, prevEdit.newLength); + mergePrev = prevEdit; + mergeCurr = e1; + prevEdit = this._getPrev(++prevIndex); + currEdit = e2; + } + + this._result[this._resultLen++] = new TextChange( + mergePrev.oldPosition, + mergePrev.oldText, + mergeCurr.newPosition, + mergeCurr.newText + ); + this._prevDeltaOffset += mergePrev.newLength - mergePrev.oldLength; + this._currDeltaOffset += mergeCurr.newLength - mergeCurr.oldLength; + } + + const merged = TextChangeCompressor._merge(this._result); + const cleaned = TextChangeCompressor._removeNoOps(merged); + return cleaned; + } + + private _acceptCurr(currEdit: TextChange): void { + this._result[this._resultLen++] = TextChangeCompressor._rebaseCurr(this._prevDeltaOffset, currEdit); + this._currDeltaOffset += currEdit.newLength - currEdit.oldLength; + } + + private _getCurr(currIndex: number): TextChange | null { + return (currIndex < this._currLen ? this._currEdits[currIndex] : null); + } + + private _acceptPrev(prevEdit: TextChange): void { + this._result[this._resultLen++] = TextChangeCompressor._rebasePrev(this._currDeltaOffset, prevEdit); + this._prevDeltaOffset += prevEdit.newLength - prevEdit.oldLength; + } + + private _getPrev(prevIndex: number): TextChange | null { + return (prevIndex < this._prevLen ? this._prevEdits[prevIndex] : null); + } + + private static _rebaseCurr(prevDeltaOffset: number, currEdit: TextChange): TextChange { + return new TextChange( + currEdit.oldPosition - prevDeltaOffset, + currEdit.oldText, + currEdit.newPosition, + currEdit.newText + ); + } + + private static _rebasePrev(currDeltaOffset: number, prevEdit: TextChange): TextChange { + return new TextChange( + prevEdit.oldPosition, + prevEdit.oldText, + prevEdit.newPosition + currDeltaOffset, + prevEdit.newText + ); + } + + private static _splitPrev(edit: TextChange, offset: number): [TextChange, TextChange] { + const preText = edit.newText.substr(0, offset); + const postText = edit.newText.substr(offset); + + return [ + new TextChange( + edit.oldPosition, + edit.oldText, + edit.newPosition, + preText + ), + new TextChange( + edit.oldEnd, + '', + edit.newPosition + offset, + postText + ) + ]; + } + + private static _splitCurr(edit: TextChange, offset: number): [TextChange, TextChange] { + const preText = edit.oldText.substr(0, offset); + const postText = edit.oldText.substr(offset); + + return [ + new TextChange( + edit.oldPosition, + preText, + edit.newPosition, + edit.newText + ), + new TextChange( + edit.oldPosition + offset, + postText, + edit.newEnd, + '' + ) + ]; + } + + private static _merge(edits: TextChange[]): TextChange[] { + if (edits.length === 0) { + return edits; + } + + let result: TextChange[] = [], resultLen = 0; + + let prev = edits[0]; + for (let i = 1; i < edits.length; i++) { + const curr = edits[i]; + + if (prev.oldEnd === curr.oldPosition) { + // Merge into `prev` + prev = new TextChange( + prev.oldPosition, + prev.oldText + curr.oldText, + prev.newPosition, + prev.newText + curr.newText + ); + } else { + result[resultLen++] = prev; + prev = curr; + } + } + result[resultLen++] = prev; + + return result; + } + + private static _removeNoOps(edits: TextChange[]): TextChange[] { + if (edits.length === 0) { + return edits; + } + + let result: TextChange[] = [], resultLen = 0; + + for (let i = 0; i < edits.length; i++) { + const edit = edits[i]; + + if (edit.oldText === edit.newText) { + continue; + } + result[resultLen++] = edit; + } + + return result; + } +} diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 59e61125845..73a171cefee 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -37,6 +37,7 @@ import { Color } from 'vs/base/common/color'; import { Constants } from 'vs/base/common/uint'; import { EditorTheme } from 'vs/editor/common/view/viewContext'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +import { TextChange } from 'vs/editor/common/model/textChange'; function createTextBufferBuilder() { return new PieceTreeTextBufferBuilder(); @@ -367,7 +368,6 @@ export class TextModel extends Disposable implements model.ITextModel { this._onWillDispose.fire(); this._languageRegistryListener.dispose(); this._tokenization.dispose(); - this._undoRedoService.removeElements(this.uri); this._isDisposed = true; super.dispose(); this._isDisposing = false; @@ -711,7 +711,11 @@ export class TextModel extends Disposable implements model.ITextModel { this._alternativeVersionId = this._versionId; } - private _overwriteAlternativeVersionId(newAlternativeVersionId: number): void { + public _overwriteVersionId(versionId: number): void { + this._versionId = versionId; + } + + public _overwriteAlternativeVersionId(newAlternativeVersionId: number): void { this._alternativeVersionId = newAlternativeVersionId; } @@ -1285,19 +1289,39 @@ export class TextModel extends Disposable implements model.ITextModel { return this._commandManager.pushEditOperation(beforeCursorState, editOperations, cursorStateComputer); } - _applyUndoRedoEdits(edits: model.IValidEditOperations[], eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): model.IValidEditOperations[] { + _applyUndo(changes: TextChange[], eol: model.EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void { + const edits = changes.map((change) => { + const rangeStart = this.getPositionAt(change.newPosition); + const rangeEnd = this.getPositionAt(change.newEnd); + return { + range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column), + text: change.oldText + }; + }); + this._applyUndoRedoEdits(edits, eol, true, false, resultingAlternativeVersionId, resultingSelection); + } + + _applyRedo(changes: TextChange[], eol: model.EndOfLineSequence, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void { + const edits = changes.map((change) => { + const rangeStart = this.getPositionAt(change.oldPosition); + const rangeEnd = this.getPositionAt(change.oldEnd); + return { + range: new Range(rangeStart.lineNumber, rangeStart.column, rangeEnd.lineNumber, rangeEnd.column), + text: change.newText + }; + }); + this._applyUndoRedoEdits(edits, eol, false, true, resultingAlternativeVersionId, resultingSelection); + } + + private _applyUndoRedoEdits(edits: model.IIdentifiedSingleEditOperation[], eol: model.EndOfLineSequence, isUndoing: boolean, isRedoing: boolean, resultingAlternativeVersionId: number, resultingSelection: Selection[] | null): void { try { this._onDidChangeDecorations.beginDeferredEmit(); this._eventEmitter.beginDeferredEmit(); this._isUndoing = isUndoing; this._isRedoing = isRedoing; - let reverseEdits: model.IValidEditOperations[] = []; - for (let i = 0, len = edits.length; i < len; i++) { - reverseEdits[i] = { operations: this.applyEdits(edits[i].operations) }; - } + this.applyEdits(edits, false); this.setEOL(eol); this._overwriteAlternativeVersionId(resultingAlternativeVersionId); - return reverseEdits; } finally { this._isUndoing = false; this._isRedoing = false; @@ -1306,21 +1330,25 @@ export class TextModel extends Disposable implements model.ITextModel { } } - public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[]): model.IValidEditOperation[] { + public applyEdits(operations: model.IIdentifiedSingleEditOperation[]): void; + public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: false): void; + public applyEdits(operations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: true): model.IValidEditOperation[]; + public applyEdits(rawOperations: model.IIdentifiedSingleEditOperation[], computeUndoEdits: boolean = false): void | model.IValidEditOperation[] { try { this._onDidChangeDecorations.beginDeferredEmit(); this._eventEmitter.beginDeferredEmit(); - return this._doApplyEdits(this._validateEditOperations(rawOperations)); + const operations = this._validateEditOperations(rawOperations); + return this._doApplyEdits(operations, computeUndoEdits); } finally { this._eventEmitter.endDeferredEmit(); this._onDidChangeDecorations.endDeferredEmit(); } } - private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[]): model.IValidEditOperation[] { + private _doApplyEdits(rawOperations: model.ValidAnnotatedEditOperation[], computeUndoEdits: boolean): void | model.IValidEditOperation[] { const oldLineCount = this._buffer.getLineCount(); - const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace); + const result = this._buffer.applyEdits(rawOperations, this._options.trimAutoWhitespace, computeUndoEdits); const newLineCount = this._buffer.getLineCount(); const contentChanges = result.changes; @@ -1395,7 +1423,7 @@ export class TextModel extends Disposable implements model.ITextModel { ); } - return result.reverseEdits; + return (result.reverseEdits === null ? undefined : result.reverseEdits); } public undo(): void { diff --git a/src/vs/editor/common/model/tokensStore.ts b/src/vs/editor/common/model/tokensStore.ts index 047ca4be628..e61bad4e8a7 100644 --- a/src/vs/editor/common/model/tokensStore.ts +++ b/src/vs/editor/common/model/tokensStore.ts @@ -11,10 +11,18 @@ import { ColorId, FontStyle, LanguageId, MetadataConsts, StandardTokenType, Toke import { writeUInt32BE, readUInt32BE } from 'vs/base/common/buffer'; import { CharCode } from 'vs/base/common/charCode'; -export function countEOL(text: string): [number, number, number] { +export const enum StringEOL { + Unknown = 0, + Invalid = 3, + LF = 1, + CRLF = 2 +} + +export function countEOL(text: string): [number, number, number, StringEOL] { let eolCount = 0; let firstLineLength = 0; let lastLineStart = 0; + let eol: StringEOL = StringEOL.Unknown; for (let i = 0, len = text.length; i < len; i++) { const chr = text.charCodeAt(i); @@ -25,12 +33,16 @@ export function countEOL(text: string): [number, number, number] { eolCount++; if (i + 1 < len && text.charCodeAt(i + 1) === CharCode.LineFeed) { // \r\n... case + eol |= StringEOL.CRLF; i++; // skip \n } else { // \r... case + eol |= StringEOL.Invalid; } lastLineStart = i + 1; } else if (chr === CharCode.LineFeed) { + // \n... case + eol |= StringEOL.LF; if (eolCount === 0) { firstLineLength = i; } @@ -41,7 +53,7 @@ export function countEOL(text: string): [number, number, number] { if (eolCount === 0) { firstLineLength = text.length; } - return [eolCount, firstLineLength, text.length - lastLineStart]; + return [eolCount, firstLineLength, text.length - lastLineStart, eol]; } function getDefaultMetadata(topLevelLanguageId: LanguageId): number { diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index e934726e4f3..44080044e77 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1396,6 +1396,15 @@ export interface AuthenticationSession { accountName: string; } +/** + * @internal + */ +export interface AuthenticationSessionsChangeEvent { + added: string[]; + removed: string[]; + changed: string[]; +} + export interface Command { id: string; title: string; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 0db7b1795d6..4e7e5db2a57 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; @@ -25,7 +26,14 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { SparseEncodedTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; -import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +import { IUndoRedoService, IUndoRedoElement, IPastFutureElements } from 'vs/platform/undoRedo/common/undoRedo'; +import { StringSHA1 } from 'vs/base/common/hash'; +import { SingleModelEditStackElement, MultiModelEditStackElement, EditStackElement } from 'vs/editor/common/model/editStack'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { Schemas } from 'vs/base/common/network'; +import Severity from 'vs/base/common/severity'; + +export const MAINTAIN_UNDO_REDO_STACK = true; export interface IEditorSemanticHighlightingOptions { enabled?: boolean; @@ -35,6 +43,18 @@ function MODEL_ID(resource: URI): string { return resource.toString(); } +function computeModelSha1(model: ITextModel): string { + // compute the sha1 + const shaComputer = new StringSHA1(); + const snapshot = model.createSnapshot(); + let text: string | null; + while ((text = snapshot.read())) { + shaComputer.update(text); + } + return shaComputer.digest(); +} + + class ModelData implements IDisposable { public readonly model: ITextModel; @@ -98,13 +118,42 @@ interface IRawConfig { const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLine.LF : DefaultEndOfLine.CRLF; -export class ModelServiceImpl extends Disposable implements IModelService { - public _serviceBrand: undefined; +interface EditStackPastFutureElements { + past: EditStackElement[]; + future: EditStackElement[]; +} - private readonly _configurationService: IConfigurationService; - private readonly _configurationServiceSubscription: IDisposable; - private readonly _resourcePropertiesService: ITextResourcePropertiesService; - private readonly _undoRedoService: IUndoRedoService; +function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements { + return (isEditStackElements(undoElements.past) && isEditStackElements(undoElements.future)); +} + +function isEditStackElements(elements: IUndoRedoElement[]): elements is EditStackElement[] { + for (const element of elements) { + if (element instanceof SingleModelEditStackElement) { + continue; + } + if (element instanceof MultiModelEditStackElement) { + continue; + } + return false; + } + return true; +} + +class DisposedModelInfo { + constructor( + public readonly uri: URI, + public readonly sha1: string, + public readonly versionId: number, + public readonly alternativeVersionId: number, + ) { } +} + +export class ModelServiceImpl extends Disposable implements IModelService { + + private static _PROMPT_UNDO_REDO_SIZE_LIMIT = 10 * 1024 * 1024; // 10MB + + public _serviceBrand: undefined; private readonly _onModelAdded: Emitter = this._register(new Emitter()); public readonly onModelAdded: Event = this._onModelAdded.event; @@ -115,39 +164,37 @@ export class ModelServiceImpl extends Disposable implements IModelService { private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>()); public readonly onModelModeChanged: Event<{ model: ITextModel; oldModeId: string; }> = this._onModelModeChanged.event; - private _modelCreationOptionsByLanguageAndResource: { - [languageAndResource: string]: ITextModelCreationOptions; - }; + private _modelCreationOptionsByLanguageAndResource: { [languageAndResource: string]: ITextModelCreationOptions; }; /** * All the models known in the system. */ private readonly _models: { [modelId: string]: ModelData; }; + private readonly _disposedModels: Map; constructor( - @IConfigurationService configurationService: IConfigurationService, - @ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService, - @IThemeService themeService: IThemeService, - @ILogService logService: ILogService, - @IUndoRedoService undoRedoService: IUndoRedoService + @IConfigurationService private readonly _configurationService: IConfigurationService, + @ITextResourcePropertiesService private readonly _resourcePropertiesService: ITextResourcePropertiesService, + @IThemeService private readonly _themeService: IThemeService, + @ILogService private readonly _logService: ILogService, + @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, + @IDialogService private readonly _dialogService: IDialogService, ) { super(); - this._configurationService = configurationService; - this._resourcePropertiesService = resourcePropertiesService; - this._undoRedoService = undoRedoService; - this._models = {}; this._modelCreationOptionsByLanguageAndResource = Object.create(null); + this._models = {}; + this._disposedModels = new Map(); - this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions()); + this._register(this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions())); this._updateModelOptions(); - this._register(new SemanticColoringFeature(this, themeService, configurationService, logService)); + this._register(new SemanticColoringFeature(this, this._themeService, this._configurationService, this._logService)); } private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions { let tabSize = EDITOR_MODEL_DEFAULTS.tabSize; if (config.editor && typeof config.editor.tabSize !== 'undefined') { - let parsedTabSize = parseInt(config.editor.tabSize, 10); + const parsedTabSize = parseInt(config.editor.tabSize, 10); if (!isNaN(parsedTabSize)) { tabSize = parsedTabSize; } @@ -158,7 +205,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { let indentSize = tabSize; if (config.editor && typeof config.editor.indentSize !== 'undefined' && config.editor.indentSize !== 'tabSize') { - let parsedIndentSize = parseInt(config.editor.indentSize, 10); + const parsedIndentSize = parseInt(config.editor.indentSize, 10); if (!isNaN(parsedIndentSize)) { indentSize = parsedIndentSize; } @@ -230,14 +277,14 @@ export class ModelServiceImpl extends Disposable implements IModelService { } private _updateModelOptions(): void { - let oldOptionsByLanguageAndResource = this._modelCreationOptionsByLanguageAndResource; + const oldOptionsByLanguageAndResource = this._modelCreationOptionsByLanguageAndResource; this._modelCreationOptionsByLanguageAndResource = Object.create(null); // Update options on all models - let keys = Object.keys(this._models); + const keys = Object.keys(this._models); for (let i = 0, len = keys.length; i < len; i++) { - let modelId = keys[i]; - let modelData = this._models[modelId]; + const modelId = keys[i]; + const modelData = this._models[modelId]; const language = modelData.model.getLanguageIdentifier().language; const uri = modelData.model.uri; const oldOptions = oldOptionsByLanguageAndResource[language + uri]; @@ -277,17 +324,30 @@ export class ModelServiceImpl extends Disposable implements IModelService { } } - public dispose(): void { - this._configurationServiceSubscription.dispose(); - super.dispose(); - } - // --- begin IModelService private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI | undefined, isForSimpleWidget: boolean): ModelData { // create & save the model const options = this.getCreationOptions(languageIdentifier.language, resource, isForSimpleWidget); const model: TextModel = new TextModel(value, options, languageIdentifier, resource, this._undoRedoService); + if (resource && this._disposedModels.has(MODEL_ID(resource))) { + const disposedModelData = this._disposedModels.get(MODEL_ID(resource))!; + this._disposedModels.delete(MODEL_ID(resource)); + const elements = this._undoRedoService.getElements(resource); + if (computeModelSha1(model) === disposedModelData.sha1 && isEditStackPastFutureElements(elements)) { + for (const element of elements.past) { + element.setModel(model); + } + for (const element of elements.future) { + element.setModel(model); + } + this._undoRedoService.setElementsIsValid(resource, true); + model._overwriteVersionId(disposedModelData.versionId); + model._overwriteAlternativeVersionId(disposedModelData.alternativeVersionId); + } else { + this._undoRedoService.removeElements(resource); + } + } const modelId = MODEL_ID(model.uri); if (this._models[modelId]) { @@ -360,7 +420,8 @@ export class ModelServiceImpl extends Disposable implements IModelService { const commonSuffix = this._commonSuffix(model, modelLineCount - commonPrefix, commonPrefix, textBuffer, textBufferLineCount - commonPrefix, commonPrefix); - let oldRange: Range, newRange: Range; + let oldRange: Range; + let newRange: Range; if (commonSuffix > 0) { oldRange = new Range(commonPrefix + 1, 1, modelLineCount - commonSuffix + 1, 1); newRange = new Range(commonPrefix + 1, 1, textBufferLineCount - commonSuffix + 1, 1); @@ -394,7 +455,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { if (!languageSelection) { return; } - let modelData = this._models[MODEL_ID(model.uri)]; + const modelData = this._models[MODEL_ID(model.uri)]; if (!modelData) { return; } @@ -403,19 +464,69 @@ export class ModelServiceImpl extends Disposable implements IModelService { public destroyModel(resource: URI): void { // We need to support that not all models get disposed through this service (i.e. model.dispose() should work!) - let modelData = this._models[MODEL_ID(resource)]; + const modelData = this._models[MODEL_ID(resource)]; if (!modelData) { return; } + const model = modelData.model; + let maintainUndoRedoStack = false; + let heapSize = 0; + if (MAINTAIN_UNDO_REDO_STACK && (resource.scheme === Schemas.file || resource.scheme === Schemas.vscodeRemote)) { + const elements = this._undoRedoService.getElements(resource); + if ((elements.past.length > 0 || elements.future.length > 0) && isEditStackPastFutureElements(elements)) { + maintainUndoRedoStack = true; + for (const element of elements.past) { + heapSize += element.heapSize(resource); + element.setModel(resource); // remove reference from text buffer instance + } + for (const element of elements.future) { + heapSize += element.heapSize(resource); + element.setModel(resource); // remove reference from text buffer instance + } + } else { + maintainUndoRedoStack = false; + } + } + + if (maintainUndoRedoStack) { + // We only invalidate the elements, but they remain in the undo-redo service. + this._undoRedoService.setElementsIsValid(resource, false); + this._disposedModels.set(MODEL_ID(resource), new DisposedModelInfo(resource, computeModelSha1(model), model.getVersionId(), model.getAlternativeVersionId())); + } else { + this._undoRedoService.removeElements(resource); + } + modelData.model.dispose(); + + // After disposing the model, prompt and ask if we should keep the undo-redo stack + if (maintainUndoRedoStack && heapSize > ModelServiceImpl._PROMPT_UNDO_REDO_SIZE_LIMIT) { + const mbSize = (heapSize / 1024 / 1024).toFixed(1); + this._dialogService.show( + Severity.Info, + nls.localize('undoRedoConfirm', "Keep the undo-redo stack for {0} in memory ({1} MB)?", (resource.scheme === Schemas.file ? resource.fsPath : resource.path), mbSize), + [ + nls.localize('nok', "Discard"), + nls.localize('ok', "Keep"), + ], + { + cancelId: 2 + } + ).then((result) => { + const discard = (result.choice === 2 || result.choice === 0); + if (discard) { + this._disposedModels.delete(MODEL_ID(resource)); + this._undoRedoService.removeElements(resource); + } + }); + } } public getModels(): ITextModel[] { - let ret: ITextModel[] = []; + const ret: ITextModel[] = []; - let keys = Object.keys(this._models); + const keys = Object.keys(this._models); for (let i = 0, len = keys.length; i < len; i++) { - let modelId = keys[i]; + const modelId = keys[i]; ret.push(this._models[modelId].model); } @@ -423,8 +534,8 @@ export class ModelServiceImpl extends Disposable implements IModelService { } public getModel(resource: URI): ITextModel | null { - let modelId = MODEL_ID(resource); - let modelData = this._models[modelId]; + const modelId = MODEL_ID(resource); + const modelData = this._models[modelId]; if (!modelData) { return null; } @@ -434,8 +545,8 @@ export class ModelServiceImpl extends Disposable implements IModelService { // --- end IModelService private _onWillDispose(model: ITextModel): void { - let modelId = MODEL_ID(model.uri); - let modelData = this._models[modelId]; + const modelId = MODEL_ID(model.uri); + const modelData = this._models[modelId]; delete this._models[modelId]; modelData.dispose(); diff --git a/src/vs/editor/common/standaloneStrings.ts b/src/vs/editor/common/standaloneStrings.ts index e915d340fb3..88104a63373 100644 --- a/src/vs/editor/common/standaloneStrings.ts +++ b/src/vs/editor/common/standaloneStrings.ts @@ -36,7 +36,7 @@ export namespace InspectTokensNLS { } export namespace GoToLineNLS { - export const gotoLineActionLabel = nls.localize('gotoLineActionLabel', "Go to Line..."); + export const gotoLineActionLabel = nls.localize('gotoLineActionLabel', "Go to Line/Column..."); } export namespace QuickHelpNLS { diff --git a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts index d4756234321..cf9a6f37173 100644 --- a/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/editorNavigationQuickAccess.ts @@ -11,7 +11,7 @@ import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { overviewRulerRangeHighlight } from 'vs/editor/common/view/editorColorRegistry'; import { IQuickPick, IQuickPickItem, IKeyMods } from 'vs/platform/quickinput/common/quickInput'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; import { isDiffEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -47,13 +47,12 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu picker.matchOnLabel = picker.matchOnDescription = picker.matchOnDetail = picker.sortByLabel = false; // Provide based on current active editor - let pickerDisposable = this.doProvide(picker, token); - disposables.add(toDisposable(() => pickerDisposable.dispose())); + const pickerDisposable = disposables.add(new MutableDisposable()); + pickerDisposable.value = this.doProvide(picker, token); // Re-create whenever the active editor changes disposables.add(this.onDidActiveTextEditorControlChange(() => { - pickerDisposable.dispose(); - pickerDisposable = this.doProvide(picker, token); + pickerDisposable.value = this.doProvide(picker, token); })); return disposables; @@ -80,11 +79,11 @@ export abstract class AbstractEditorNavigationQuickAccessProvider implements IQu lastKnownEditorViewState = withNullAsUndefined(editor.saveViewState()); })); - once(token.onCancellationRequested)(() => { - if (lastKnownEditorViewState) { + disposables.add(once(token.onCancellationRequested)(() => { + if (lastKnownEditorViewState && editor === this.activeTextEditorControl) { editor.restoreViewState(lastKnownEditorViewState); } - }); + })); } // Clean up decorations on dispose diff --git a/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts index 555dd019294..23b8d8a144c 100644 --- a/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/gotoLineQuickAccess.ts @@ -6,11 +6,13 @@ import { localize } from 'vs/nls'; import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { DisposableStore, IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { IRange } from 'vs/editor/common/core/range'; import { AbstractEditorNavigationQuickAccessProvider } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; import { IPosition } from 'vs/editor/common/core/position'; +import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { EditorOption, RenderLineNumbersType } from 'vs/editor/common/config/editorOptions'; interface IGotoLineQuickPickItem extends IQuickPickItem, Partial { } @@ -81,6 +83,18 @@ export abstract class AbstractGotoLineQuickAccessProvider extends AbstractEditor updatePickerAndEditor(); disposables.add(picker.onDidChangeValue(() => updatePickerAndEditor())); + // Adjust line number visibility as needed + const codeEditor = getCodeEditor(editor); + if (codeEditor) { + const options = codeEditor.getOptions(); + const lineNumbers = options.get(EditorOption.lineNumbers); + if (lineNumbers.renderType === RenderLineNumbersType.Relative) { + codeEditor.updateOptions({ lineNumbers: 'on' }); + + disposables.add(toDisposable(() => codeEditor.updateOptions({ lineNumbers: 'relative' }))); + } + } + return disposables; } diff --git a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts index 3c718551356..14fd0da987a 100644 --- a/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts +++ b/src/vs/editor/contrib/quickAccess/gotoSymbolQuickAccess.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { IQuickPick, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; -import { DisposableStore, IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { DisposableStore, IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, ScrollType } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { IRange, Range } from 'vs/editor/common/core/range'; @@ -18,11 +18,11 @@ import { trim, format } from 'vs/base/common/strings'; import { fuzzyScore, FuzzyScore, createMatches } from 'vs/base/common/filters'; import { assign } from 'vs/base/common/objects'; -interface IGotoSymbolQuickPickItem extends IQuickPickItem { +export interface IGotoSymbolQuickPickItem extends IQuickPickItem { kind: SymbolKind, index: number, score?: FuzzyScore; - range?: { decoration: IRange, selection: IRange }, + range?: { decoration: IRange, selection: IRange } } export interface IGotoSymbolQuickAccessProviderOptions extends IEditorNavigationQuickAccessOptions { @@ -73,20 +73,44 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit picker.items = [{ label, index: 0, kind: SymbolKind.String }]; picker.ariaLabel = label; - // Listen to changes to the registry and see if eventually + // Wait for changes to the registry and see if eventually // we do get symbols. This can happen if the picker is opened // very early after the model has loaded but before the // language registry is ready. // https://github.com/microsoft/vscode/issues/70607 + (async () => { + const result = await this.waitForLanguageSymbolRegistry(model, disposables); + if (!result || token.isCancellationRequested) { + return; + } + + disposables.add(this.doProvideWithEditorSymbols(editor, model, picker, token)); + })(); + + return disposables; + } + + protected async waitForLanguageSymbolRegistry(model: ITextModel, disposables: DisposableStore): Promise { + if (DocumentSymbolProviderRegistry.has(model)) { + return true; + } + + let symbolProviderRegistryPromiseResolve: (res: boolean) => void; + const symbolProviderRegistryPromise = new Promise(resolve => symbolProviderRegistryPromiseResolve = resolve); + + // Resolve promise when registry knows model const symbolProviderListener = disposables.add(DocumentSymbolProviderRegistry.onDidChange(() => { if (DocumentSymbolProviderRegistry.has(model)) { symbolProviderListener.dispose(); - disposables.add(this.doProvideWithEditorSymbols(editor, model, picker, token)); + symbolProviderRegistryPromiseResolve(true); } })); - return disposables; + // Resolve promise when we get disposed too + disposables.add(toDisposable(() => symbolProviderRegistryPromiseResolve(false))); + + return symbolProviderRegistryPromise; } private doProvideWithEditorSymbols(editor: IEditor, model: ITextModel, picker: IQuickPick, token: CancellationToken): IDisposable { @@ -131,7 +155,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit // Collect symbol picks picker.busy = true; try { - const items = await this.getSymbolPicks(symbolsPromise, picker.value.substr(AbstractGotoSymbolQuickAccessProvider.PREFIX.length).trim(), picksCts.token); + const items = await this.doGetSymbolPicks(symbolsPromise, picker.value.substr(AbstractGotoSymbolQuickAccessProvider.PREFIX.length).trim(), picksCts.token); if (token.isCancellationRequested) { return; } @@ -170,7 +194,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit return disposables; } - private async getSymbolPicks(symbolsPromise: Promise, filter: string, token: CancellationToken): Promise> { + protected async doGetSymbolPicks(symbolsPromise: Promise, filter: string, token: CancellationToken): Promise> { const symbols = await symbolsPromise; if (token.isCancellationRequested) { return []; @@ -343,7 +367,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit return result; } - private async getDocumentSymbols(document: ITextModel, flatten: boolean, token: CancellationToken): Promise { + protected async getDocumentSymbols(document: ITextModel, flatten: boolean, token: CancellationToken): Promise { const model = await OutlineModel.create(document, token); if (token.isCancellationRequested) { return []; diff --git a/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts b/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts index e56cb2bb72f..4c17969b9cd 100644 --- a/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts +++ b/src/vs/editor/contrib/smartSelect/test/smartSelect.test.ts @@ -50,7 +50,8 @@ suite('SmartSelect', () => { setup(() => { const configurationService = new TestConfigurationService(); - modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService(), new NullLogService(), new UndoRedoService(new TestDialogService(), new TestNotificationService())); + const dialogService = new TestDialogService(); + modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService(), new NullLogService(), new UndoRedoService(dialogService, new TestNotificationService()), dialogService); mode = new MockJSMode(); }); diff --git a/src/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.ts b/src/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.ts index ab7735e221c..75d54811065 100644 --- a/src/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.ts +++ b/src/vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess.ts @@ -41,7 +41,7 @@ export class GotoLineAction extends EditorAction { super({ id: 'editor.action.gotoLine', label: GoToLineNLS.gotoLineActionLabel, - alias: 'Go to Line...', + alias: 'Go to Line/Column...', precondition: undefined, kbOpts: { kbExpr: EditorContextKeys.focus, diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index eb014c804d9..4e2e02c6b71 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -156,7 +156,7 @@ export module StaticServices { export const undoRedoService = define(IUndoRedoService, (o) => new UndoRedoService(dialogService.get(o), notificationService.get(o))); - export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o), logService.get(o), undoRedoService.get(o))); + export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o), logService.get(o), undoRedoService.get(o), dialogService.get(o))); export const markerDecorationsService = define(IMarkerDecorationsService, (o) => new MarkerDecorationsService(modelService.get(o), markerService.get(o))); diff --git a/src/vs/editor/test/browser/controller/cursor.test.ts b/src/vs/editor/test/browser/controller/cursor.test.ts index 34902600555..3175d1b0228 100644 --- a/src/vs/editor/test/browser/controller/cursor.test.ts +++ b/src/vs/editor/test/browser/controller/cursor.test.ts @@ -1348,7 +1348,7 @@ suite('Editor Controller - Regression tests', () => { CoreEditingCommands.Undo.runEditorCommand(null, editor, null); assert.equal(model.getLineContent(1), 'Hello world '); - assertCursor(cursor, new Position(1, 13)); + assertCursor(cursor, new Selection(1, 12, 1, 13)); CoreEditingCommands.Undo.runEditorCommand(null, editor, null); assert.equal(model.getLineContent(1), 'Hello world'); diff --git a/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts b/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts index 4ec19305751..ded9745ef09 100644 --- a/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts +++ b/src/vs/editor/test/common/model/benchmark/operations.benchmark.ts @@ -54,7 +54,7 @@ for (let fileSize of fileSizes) { fn: (textBuffer) => { // for line model, this loop doesn't reflect the real situation. for (const edit of edits) { - textBuffer.applyEdits([edit], false); + textBuffer.applyEdits([edit], false, false); } } }); @@ -67,7 +67,7 @@ for (let fileSize of fileSizes) { }, preCycle: (textBuffer) => { for (const edit of edits) { - textBuffer.applyEdits([edit], false); + textBuffer.applyEdits([edit], false, false); } return textBuffer; }, @@ -91,7 +91,7 @@ for (let fileSize of fileSizes) { }, preCycle: (textBuffer) => { for (const edit of edits) { - textBuffer.applyEdits([edit], false); + textBuffer.applyEdits([edit], false, false); } return textBuffer; }, @@ -121,7 +121,7 @@ for (let fileSize of fileSizes) { }, preCycle: (textBuffer) => { for (const edit of edits) { - textBuffer.applyEdits([edit], false); + textBuffer.applyEdits([edit], false, false); } return textBuffer; }, @@ -134,4 +134,4 @@ for (let fileSize of fileSizes) { editsSuite.run(); } -} \ No newline at end of file +} diff --git a/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts b/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts index ab86d7e0a81..aecb8ad46ca 100644 --- a/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts +++ b/src/vs/editor/test/common/model/benchmark/searchNReplace.benchmark.ts @@ -41,10 +41,10 @@ for (let fileSize of fileSizes) { return textBuffer; }, fn: (textBuffer) => { - textBuffer.applyEdits(edits.slice(0, i), false); + textBuffer.applyEdits(edits.slice(0, i), false, false); } }); } replaceSuite.run(); -} \ No newline at end of file +} diff --git a/src/vs/editor/test/common/model/editableTextModel.test.ts b/src/vs/editor/test/common/model/editableTextModel.test.ts index b37a3b9820e..67c8a119e30 100644 --- a/src/vs/editor/test/common/model/editableTextModel.test.ts +++ b/src/vs/editor/test/common/model/editableTextModel.test.ts @@ -1104,7 +1104,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => { { range: new Range(3, 1, 3, 6), text: null, }, { range: new Range(2, 1, 3, 1), text: null, }, { range: new Range(3, 6, 3, 6), text: '\nline2' } - ]); + ], true); model.applyEdits(undoEdits); diff --git a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts index e1e4b5c999e..9531a8bb1af 100644 --- a/src/vs/editor/test/common/model/editableTextModelTestUtils.ts +++ b/src/vs/editor/test/common/model/editableTextModelTestUtils.ts @@ -17,7 +17,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent assertSyncedModels(originalStr, (model, assertMirrorModels) => { // Apply edits & collect inverse edits - let inverseEdits = model.applyEdits(edits); + let inverseEdits = model.applyEdits(edits, true); // Assert edits produced expected result assert.deepEqual(model.getValue(EndOfLinePreference.LF), expectedStr); @@ -25,7 +25,7 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent assertMirrorModels(); // Apply the inverse edits - let inverseInverseEdits = model.applyEdits(inverseEdits); + let inverseInverseEdits = model.applyEdits(inverseEdits, true); // Assert the inverse edits brought back model to original state assert.deepEqual(model.getValue(EndOfLinePreference.LF), originalStr); @@ -36,8 +36,8 @@ export function testApplyEditsWithSyncedModels(original: string[], edits: IIdent identifier: edit.identifier, range: edit.range, text: edit.text, - forceMoveMarkers: edit.forceMoveMarkers, - isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit + forceMoveMarkers: edit.forceMoveMarkers || false, + isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit || false }; }; // Assert the inverse of the inverse edits are the original edits diff --git a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts index 5e18c394433..4c9bd0d183c 100644 --- a/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts +++ b/src/vs/editor/test/common/model/linesTextBuffer/linesTextBuffer.test.ts @@ -18,7 +18,10 @@ suite('PieceTreeTextBuffer._getInverseEdits', () => { range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), rangeOffset: 0, rangeLength: 0, - lines: text, + text: text ? text.join('\n') : '', + eolCount: text ? text.length - 1 : 0, + firstLineLength: text ? text[0].length : 0, + lastLineLength: text ? text[text.length - 1].length : 0, forceMoveMarkers: false, isAutoWhitespaceEdit: false }; @@ -269,7 +272,10 @@ suite('PieceTreeTextBuffer._toSingleEditOperation', () => { range: new Range(startLineNumber, startColumn, endLineNumber, endColumn), rangeOffset: rangeOffset, rangeLength: rangeLength, - lines: text, + text: text ? text.join('\n') : '', + eolCount: text ? text.length - 1 : 0, + firstLineLength: text ? text[0].length : 0, + lastLineLength: text ? text[text.length - 1].length : 0, forceMoveMarkers: false, isAutoWhitespaceEdit: false }; diff --git a/src/vs/editor/test/common/model/model.test.ts b/src/vs/editor/test/common/model/model.test.ts index 77ce4133e46..ed6787bc528 100644 --- a/src/vs/editor/test/common/model/model.test.ts +++ b/src/vs/editor/test/common/model/model.test.ts @@ -330,7 +330,7 @@ suite('Editor Model - Model', () => { let res = thisModel.applyEdits([ { range: new Range(2, 1, 2, 1), text: 'a' }, { range: new Range(1, 1, 1, 1), text: 'b' }, - ]); + ], true); assert.deepEqual(res[0].range, new Range(2, 1, 2, 2)); assert.deepEqual(res[1].range, new Range(1, 1, 1, 2)); diff --git a/src/vs/editor/test/common/model/modelEditOperation.test.ts b/src/vs/editor/test/common/model/modelEditOperation.test.ts index 2fc1337cbe2..058c5d3d56a 100644 --- a/src/vs/editor/test/common/model/modelEditOperation.test.ts +++ b/src/vs/editor/test/common/model/modelEditOperation.test.ts @@ -50,14 +50,14 @@ suite('Editor Model - Model Edit Operation', () => { function assertSingleEditOp(singleEditOp: IIdentifiedSingleEditOperation, editedLines: string[]) { let editOp = [singleEditOp]; - let inverseEditOp = model.applyEdits(editOp); + let inverseEditOp = model.applyEdits(editOp, true); assert.equal(model.getLineCount(), editedLines.length); for (let i = 0; i < editedLines.length; i++) { assert.equal(model.getLineContent(i + 1), editedLines[i]); } - let originalOp = model.applyEdits(inverseEditOp); + let originalOp = model.applyEdits(inverseEditOp, true); assert.equal(model.getLineCount(), 5); assert.equal(model.getLineContent(1), LINE1); @@ -71,8 +71,8 @@ suite('Editor Model - Model Edit Operation', () => { identifier: edit.identifier, range: edit.range, text: edit.text, - forceMoveMarkers: edit.forceMoveMarkers, - isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit + forceMoveMarkers: edit.forceMoveMarkers || false, + isAutoWhitespaceEdit: edit.isAutoWhitespaceEdit || false }; }; assert.deepEqual(originalOp.map(simplifyEdit), editOp.map(simplifyEdit)); diff --git a/src/vs/editor/test/common/model/textChange.test.ts b/src/vs/editor/test/common/model/textChange.test.ts new file mode 100644 index 00000000000..d6d42dfc683 --- /dev/null +++ b/src/vs/editor/test/common/model/textChange.test.ts @@ -0,0 +1,269 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { compressConsecutiveTextChanges, TextChange } from 'vs/editor/common/model/textChange'; + +const GENERATE_TESTS = false; + +interface IGeneratedEdit { + offset: number; + length: number; + text: string; +} + +suite('TextChangeCompressor', () => { + + function getResultingContent(initialContent: string, edits: IGeneratedEdit[]): string { + let content = initialContent; + for (let i = edits.length - 1; i >= 0; i--) { + content = ( + content.substring(0, edits[i].offset) + + edits[i].text + + content.substring(edits[i].offset + edits[i].length) + ); + } + return content; + } + + function getTextChanges(initialContent: string, edits: IGeneratedEdit[]): TextChange[] { + let content = initialContent; + let changes: TextChange[] = new Array(edits.length); + let deltaOffset = 0; + + for (let i = 0; i < edits.length; i++) { + let edit = edits[i]; + + let position = edit.offset + deltaOffset; + let length = edit.length; + let text = edit.text; + + let oldText = content.substr(position, length); + + content = ( + content.substr(0, position) + + text + + content.substr(position + length) + ); + + changes[i] = new TextChange(edit.offset, oldText, position, text); + + deltaOffset += text.length - length; + } + + return changes; + } + + function assertCompression(initialText: string, edit1: IGeneratedEdit[], edit2: IGeneratedEdit[]): void { + + let tmpText = getResultingContent(initialText, edit1); + let chg1 = getTextChanges(initialText, edit1); + + let finalText = getResultingContent(tmpText, edit2); + let chg2 = getTextChanges(tmpText, edit2); + + let compressedTextChanges = compressConsecutiveTextChanges(chg1, chg2); + + // Check that the compression was correct + let compressedDoTextEdits: IGeneratedEdit[] = compressedTextChanges.map((change) => { + return { + offset: change.oldPosition, + length: change.oldLength, + text: change.newText + }; + }); + let actualDoResult = getResultingContent(initialText, compressedDoTextEdits); + assert.equal(actualDoResult, finalText); + + let compressedUndoTextEdits: IGeneratedEdit[] = compressedTextChanges.map((change) => { + return { + offset: change.newPosition, + length: change.newLength, + text: change.oldText + }; + }); + let actualUndoResult = getResultingContent(finalText, compressedUndoTextEdits); + assert.equal(actualUndoResult, initialText); + } + + test('simple 1', () => { + assertCompression( + '', + [{ offset: 0, length: 0, text: 'h' }], + [{ offset: 1, length: 0, text: 'e' }] + ); + }); + + test('simple 2', () => { + assertCompression( + '|', + [{ offset: 0, length: 0, text: 'h' }], + [{ offset: 2, length: 0, text: 'e' }] + ); + }); + + test('complex1', () => { + assertCompression( + 'abcdefghij', + [ + { offset: 0, length: 3, text: 'qh' }, + { offset: 5, length: 0, text: '1' }, + { offset: 8, length: 2, text: 'X' } + ], + [ + { offset: 1, length: 0, text: 'Z' }, + { offset: 3, length: 3, text: 'Y' }, + ] + ); + }); + + test('gen1', () => { + assertCompression( + 'kxm', + [{ offset: 0, length: 1, text: 'tod_neu' }], + [{ offset: 1, length: 2, text: 'sag_e' }] + ); + }); + + test('gen2', () => { + assertCompression( + 'kpb_r_v', + [{ offset: 5, length: 2, text: 'a_jvf_l' }], + [{ offset: 10, length: 2, text: 'w' }] + ); + }); + + test('gen3', () => { + assertCompression( + 'slu_w', + [{ offset: 4, length: 1, text: '_wfw' }], + [{ offset: 3, length: 5, text: '' }] + ); + }); + + test('gen4', () => { + assertCompression( + '_e', + [{ offset: 2, length: 0, text: 'zo_b' }], + [{ offset: 1, length: 3, text: 'tra' }] + ); + }); + + test('gen5', () => { + assertCompression( + 'ssn_', + [{ offset: 0, length: 2, text: 'tat_nwe' }], + [{ offset: 2, length: 6, text: 'jm' }] + ); + }); + + test('gen6', () => { + assertCompression( + 'kl_nru', + [{ offset: 4, length: 1, text: '' }], + [{ offset: 1, length: 4, text: '__ut' }] + ); + }); + + const _a = 'a'.charCodeAt(0); + const _z = 'z'.charCodeAt(0); + + function getRandomInt(min: number, max: number): number { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + function getRandomString(minLength: number, maxLength: number): string { + const length = getRandomInt(minLength, maxLength); + let r = ''; + for (let i = 0; i < length; i++) { + r += String.fromCharCode(getRandomInt(_a, _z)); + } + return r; + } + + function getRandomEOL(): string { + switch (getRandomInt(1, 3)) { + case 1: return '\r'; + case 2: return '\n'; + case 3: return '\r\n'; + } + throw new Error(`not possible`); + } + + function getRandomBuffer(small: boolean): string { + let lineCount = getRandomInt(1, small ? 3 : 10); + let lines: string[] = []; + for (let i = 0; i < lineCount; i++) { + lines.push(getRandomString(0, small ? 3 : 10) + getRandomEOL()); + } + return lines.join(''); + } + + function getRandomEdits(content: string, min: number = 1, max: number = 5): IGeneratedEdit[] { + + let result: IGeneratedEdit[] = []; + let cnt = getRandomInt(min, max); + + let maxOffset = content.length; + + while (cnt > 0 && maxOffset > 0) { + + let offset = getRandomInt(0, maxOffset); + let length = getRandomInt(0, maxOffset - offset); + let text = getRandomBuffer(true); + + result.push({ + offset: offset, + length: length, + text: text + }); + + maxOffset = offset; + cnt--; + } + + result.reverse(); + + return result; + } + + class GeneratedTest { + + private readonly _content: string; + private readonly _edits1: IGeneratedEdit[]; + private readonly _edits2: IGeneratedEdit[]; + + constructor() { + this._content = getRandomBuffer(false).replace(/\n/g, '_'); + this._edits1 = getRandomEdits(this._content, 1, 5).map((e) => { return { offset: e.offset, length: e.length, text: e.text.replace(/\n/g, '_') }; }); + let tmp = getResultingContent(this._content, this._edits1); + this._edits2 = getRandomEdits(tmp, 1, 5).map((e) => { return { offset: e.offset, length: e.length, text: e.text.replace(/\n/g, '_') }; }); + } + + public print(): void { + console.log(`assertCompression(${JSON.stringify(this._content)}, ${JSON.stringify(this._edits1)}, ${JSON.stringify(this._edits2)});`); + } + + public assert(): void { + assertCompression(this._content, this._edits1, this._edits2); + } + } + + if (GENERATE_TESTS) { + let testNumber = 0; + while (true) { + testNumber++; + console.log(`------RUNNING TextChangeCompressor TEST ${testNumber}`); + let test = new GeneratedTest(); + try { + test.assert(); + } catch (err) { + console.log(err); + test.print(); + break; + } + } + } +}); diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index 84ebc8f2e0e..f9a53739bdb 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -9,10 +9,11 @@ import * as platform from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { EditOperation } from 'vs/editor/common/core/editOperation'; import { Range } from 'vs/editor/common/core/range'; +import { Selection } from 'vs/editor/common/core/selection'; import { createStringBuilder } from 'vs/editor/common/core/stringBuilder'; import { DefaultEndOfLine } from 'vs/editor/common/model'; import { createTextBuffer } from 'vs/editor/common/model/textModel'; -import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl'; +import { ModelServiceImpl, MAINTAIN_UNDO_REDO_STACK } from 'vs/editor/common/services/modelServiceImpl'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; @@ -33,7 +34,8 @@ suite('ModelService', () => { configService.setUserConfiguration('files', { 'eol': '\n' }); configService.setUserConfiguration('files', { 'eol': '\r\n' }, URI.file(platform.isWindows ? 'c:\\myroot' : '/myroot')); - modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), new UndoRedoService(new TestDialogService(), new TestNotificationService())); + const dialogService = new TestDialogService(); + modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), new UndoRedoService(dialogService, new TestNotificationService()), dialogService); }); teardown(() => { @@ -307,6 +309,75 @@ suite('ModelService', () => { ]; assertComputeEdits(file1, file2); }); + + if (MAINTAIN_UNDO_REDO_STACK) { + test('maintains undo for same resource and same content', () => { + const resource = URI.parse('file://test.txt'); + + // create a model + const model1 = modelService.createModel('text', null, resource); + // make an edit + model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); + assert.equal(model1.getValue(), 'text1'); + // dispose it + modelService.destroyModel(resource); + + // create a new model with the same content + const model2 = modelService.createModel('text1', null, resource); + // undo + model2.undo(); + assert.equal(model2.getValue(), 'text'); + }); + + test('maintains version id and alternative version id for same resource and same content', () => { + const resource = URI.parse('file://test.txt'); + + // create a model + const model1 = modelService.createModel('text', null, resource); + // make an edit + model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); + assert.equal(model1.getValue(), 'text1'); + const versionId = model1.getVersionId(); + const alternativeVersionId = model1.getAlternativeVersionId(); + // dispose it + modelService.destroyModel(resource); + + // create a new model with the same content + const model2 = modelService.createModel('text1', null, resource); + assert.equal(model2.getVersionId(), versionId); + assert.equal(model2.getAlternativeVersionId(), alternativeVersionId); + }); + } + + test('does not maintain undo for same resource and different content', () => { + const resource = URI.parse('file://test.txt'); + + // create a model + const model1 = modelService.createModel('text', null, resource); + // make an edit + model1.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); + assert.equal(model1.getValue(), 'text1'); + // dispose it + modelService.destroyModel(resource); + + // create a new model with the same content + const model2 = modelService.createModel('text2', null, resource); + // undo + model2.undo(); + assert.equal(model2.getValue(), 'text2'); + }); + + test('setValue should clear undo stack', () => { + const resource = URI.parse('file://test.txt'); + + const model = modelService.createModel('text', null, resource); + model.pushEditOperations(null, [{ range: new Range(1, 5, 1, 5), text: '1' }], () => [new Selection(1, 5, 1, 5)]); + assert.equal(model.getValue(), 'text1'); + + model.setValue('text2'); + model.undo(); + assert.equal(model.getValue(), 'text2'); + }); }); function assertComputeEdits(lines1: string[], lines2: string[]): void { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index fff64d28c4c..b6fd6c37e97 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -179,11 +179,11 @@ declare namespace monaco { /** * Join a Uri path with path fragments and normalizes the resulting path. * - * @param resource The input Uri. + * @param uri The input Uri. * @param pathFragment The path fragment to add to the Uri path. * @returns The resulting Uri. */ - static joinPaths(resource: Uri, ...pathFragment: string[]): Uri; + static joinPath(uri: Uri, ...pathFragment: string[]): Uri; /** * Creates a string representation for this Uri. It's guaranteed that calling * `Uri.parse` with the result of this function creates an Uri which is equal @@ -1552,14 +1552,9 @@ declare namespace monaco.editor { */ range: Range; /** - * The text to replace with. This can be null to emulate a simple delete. + * The text to replace with. This can be empty to emulate a simple delete. */ - text: string | null; - /** - * This indicates that this operation has "insert" semantics. - * i.e. forceMoveMarkers = true => if `range` is collapsed, all markers at the position will be moved. - */ - forceMoveMarkers: boolean; + text: string; } /** @@ -1907,9 +1902,11 @@ declare namespace monaco.editor { * Edit the model without adding the edits to the undo stack. * This can have dire consequences on the undo stack! See @pushEditOperations for the preferred way. * @param operations The edit operations. - * @return The inverse edit operations, that, when applied, will bring the model back to the previous state. + * @return If desired, the inverse edit operations, that, when applied, will bring the model back to the previous state. */ - applyEdits(operations: IIdentifiedSingleEditOperation[]): IValidEditOperation[]; + applyEdits(operations: IIdentifiedSingleEditOperation[]): void; + applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: false): void; + applyEdits(operations: IIdentifiedSingleEditOperation[], computeUndoEdits: true): IValidEditOperation[]; /** * Change the end of line sequence without recording in the undo stack. * This can have dire consequences on the undo stack! See @pushEOL for the preferred way. diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index d99fbcc2ea3..20906116e4c 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -120,6 +120,7 @@ export class MenuId { static readonly TimelineItemContext = new MenuId('TimelineItemContext'); static readonly TimelineTitle = new MenuId('TimelineTitle'); static readonly TimelineTitleContext = new MenuId('TimelineTitleContext'); + static readonly AccountsContext = new MenuId('AccountsContext'); readonly id: number; readonly _debugName: string; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 55e00cc725a..254f08577ad 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -332,7 +332,11 @@ export class ElectronMainService implements IElectronMainService { } async closeWindow(windowId: number | undefined): Promise { - const window = this.windowById(windowId); + this.closeWindowById(windowId, windowId); + } + + async closeWindowById(currentWindowId: number | undefined, targetWindowId?: number | undefined): Promise { + const window = this.windowById(targetWindowId); if (window) { return window.win.close(); } diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/node/electron.ts index 8803fd16b39..2316d70dafc 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/node/electron.ts @@ -74,6 +74,7 @@ export interface IElectronService { relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): Promise; reload(options?: { disableExtensions?: boolean }): Promise; closeWindow(): Promise; + closeWindowById(windowId: number): Promise; quit(): Promise; // Development diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index f6f818485d9..8471255a2d5 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -43,16 +43,14 @@ export const OPTIONS: OptionDescriptions> = { 'goto': { type: 'boolean', cat: 'o', alias: 'g', args: 'file:line[:character]', description: localize('goto', "Open a file at the path on the specified line and character position.") }, 'new-window': { type: 'boolean', cat: 'o', alias: 'n', description: localize('newWindow', "Force to open a new window.") }, 'reuse-window': { type: 'boolean', cat: 'o', alias: 'r', description: localize('reuseWindow', "Force to open a file or folder in an already opened window.") }, + 'folder-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('folderUri', "Opens a window with given folder uri(s)") }, + 'file-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('fileUri', "Opens a window with given file uri(s)") }, 'wait': { type: 'boolean', cat: 'o', alias: 'w', description: localize('wait', "Wait for the files to be closed before returning.") }, 'waitMarkerFilePath': { type: 'string' }, 'locale': { type: 'string', cat: 'o', args: 'locale', description: localize('locale', "The locale to use (e.g. en-US or zh-TW).") }, 'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") }, - 'version': { type: 'boolean', cat: 'o', alias: 'v', description: localize('version', "Print version.") }, - 'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") }, 'telemetry': { type: 'boolean', cat: 'o', description: localize('telemetry', "Shows all telemetry events which VS code collects.") }, - 'folder-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('folderUri', "Opens a window with given folder uri(s)") }, - 'file-uri': { type: 'string[]', cat: 'o', args: 'uri', description: localize('fileUri', "Opens a window with given file uri(s)") }, - 'sync': { type: 'string', cat: 'o', description: localize('turn sync', "Turn sync on or off"), args: ['on', 'off'] }, + 'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") }, 'extensions-dir': { type: 'string', deprecates: 'extensionHomePath', cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") }, 'builtin-extensions-dir': { type: 'string' }, @@ -63,6 +61,7 @@ export const OPTIONS: OptionDescriptions> = { 'uninstall-extension': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") }, 'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") }, + 'version': { type: 'boolean', cat: 't', alias: 'v', description: localize('version', "Print version.") }, 'verbose': { type: 'boolean', cat: 't', description: localize('verbose', "Print verbose output (implies --wait).") }, 'log': { type: 'string', cat: 't', args: 'level', description: localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.") }, 'status': { type: 'boolean', alias: 's', cat: 't', description: localize('status', "Print process usage and diagnostics information.") }, @@ -71,6 +70,7 @@ export const OPTIONS: OptionDescriptions> = { 'prof-startup-prefix': { type: 'string' }, 'disable-extensions': { type: 'boolean', deprecates: 'disableExtensions', cat: 't', description: localize('disableExtensions', "Disable all installed extensions.") }, 'disable-extension': { type: 'string[]', cat: 't', args: 'extension-id', description: localize('disableExtension', "Disable an extension.") }, + 'sync': { type: 'string', cat: 't', description: localize('turn sync', "Turn sync on or off"), args: ['on', 'off'] }, 'inspect-extensions': { type: 'string', deprecates: 'debugPluginHost', args: 'port', cat: 't', description: localize('inspect-extensions', "Allow debugging and profiling of extensions. Check the developer tools for the connection URI.") }, 'inspect-brk-extensions': { type: 'string', deprecates: 'debugBrkPluginHost', args: 'port', cat: 't', description: localize('inspect-brk-extensions', "Allow debugging and profiling of extensions with the extension host being paused after start. Check the developer tools for the connection URI.") }, diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts index 7994ac2b060..cf9492900e9 100644 --- a/src/vs/platform/instantiation/common/instantiationService.ts +++ b/src/vs/platform/instantiation/common/instantiationService.ts @@ -151,7 +151,7 @@ export class InstantiationService implements IInstantiationService { graph.lookupOrInsertNode(item); // a weak but working heuristic for cycle checks - if (cycleCount++ > 200) { + if (cycleCount++ > 1000) { throw new CyclicDependencyError(graph); } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 18c243a56ad..ee048dbe20a 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -532,6 +532,7 @@ export class Menubar { [ minimize, zoom, + __separator__(), switchWindow, ...nativeTabMenuItems, __separator__(), diff --git a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts index 1cebb8652a4..95fe49b6a83 100644 --- a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts @@ -6,7 +6,6 @@ import { localize } from 'vs/nls'; import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { PickerQuickAccessProvider, IPickerQuickAccessItem, IPickerQuickAccessProviderOptions } from 'vs/platform/quickinput/browser/pickerQuickAccess'; -import { distinct } from 'vs/base/common/arrays'; import { CancellationToken } from 'vs/base/common/cancellation'; import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { or, matchesPrefix, matchesWords, matchesContiguousSubString } from 'vs/base/common/filters'; @@ -22,8 +21,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { isFirefox } from 'vs/base/browser/browser'; -import { timeout } from 'vs/base/common/async'; export interface ICommandQuickPick extends IPickerQuickAccessItem { commandId: string; @@ -58,12 +55,17 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc // Ask subclass for all command picks const allCommandPicks = await this.getCommandPicks(disposables, token); + if (token.isCancellationRequested) { + return []; + } + // Filter const filteredCommandPicks: ICommandQuickPick[] = []; for (const commandPick of allCommandPicks) { const labelHighlights = withNullAsUndefined(AbstractCommandsQuickAccessProvider.WORD_FILTER(filter, commandPick.label)); const aliasHighlights = commandPick.commandAlias ? withNullAsUndefined(AbstractCommandsQuickAccessProvider.WORD_FILTER(filter, commandPick.commandAlias)) : undefined; + // Add if matching in label or alias if (labelHighlights || aliasHighlights) { commandPick.highlights = { label: labelHighlights, @@ -72,14 +74,16 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc filteredCommandPicks.push(commandPick); } - } - // Remove duplicates - const distinctCommandPicks = distinct(filteredCommandPicks, pick => `${pick.label}${pick.commandId}`); + // Also add if we have a 100% command ID match + else if (filter === commandPick.commandId) { + filteredCommandPicks.push(commandPick); + } + } // Add description to commands that have duplicate labels const mapLabelToCommand = new Map(); - for (const commandPick of distinctCommandPicks) { + for (const commandPick of filteredCommandPicks) { const existingCommandForLabel = mapLabelToCommand.get(commandPick.label); if (existingCommandForLabel) { commandPick.description = commandPick.commandId; @@ -90,7 +94,7 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc } // Sort by MRU order and fallback to name otherwise - distinctCommandPicks.sort((commandPickA, commandPickB) => { + filteredCommandPicks.sort((commandPickA, commandPickB) => { const commandACounter = this.commandsHistory.peek(commandPickA.commandId); const commandBCounter = this.commandsHistory.peek(commandPickB.commandId); @@ -113,8 +117,8 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc const commandPicks: Array = []; let addSeparator = false; - for (let i = 0; i < distinctCommandPicks.length; i++) { - const commandPick = distinctCommandPicks[i]; + for (let i = 0; i < filteredCommandPicks.length; i++) { + const commandPick = filteredCommandPicks[i]; const keybinding = this.keybindingService.lookupKeybinding(commandPick.commandId); const ariaLabel = keybinding ? localize('commandPickAriaLabelWithKeybinding', "{0}, {1}, commands picker", commandPick.label, keybinding.getAriaLabel()) : @@ -143,13 +147,6 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc // Add to history this.commandsHistory.push(commandPick.commandId); - if (!isFirefox) { - // Use a timeout to give the quick open widget a chance to close itself first - // Firefox: since the browser is quite picky for certain commands, we do not - // use a timeout (https://github.com/microsoft/vscode/issues/83288) - await timeout(50); - } - // Telementry this.telemetryService.publicLog2('workbenchActionExecuted', { id: commandPick.commandId, @@ -191,7 +188,7 @@ interface ICommandsQuickAccessConfiguration { }; } -class CommandsHistory extends Disposable { +export class CommandsHistory extends Disposable { static readonly DEFAULT_COMMANDS_HISTORY_LENGTH = 50; diff --git a/src/vs/platform/quickinput/browser/helpQuickAccess.ts b/src/vs/platform/quickinput/browser/helpQuickAccess.ts index 22e0879e475..32a64e912bf 100644 --- a/src/vs/platform/quickinput/browser/helpQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/helpQuickAccess.ts @@ -66,6 +66,10 @@ export class HelpQuickAccessProvider implements IQuickAccessProvider { const editorProviders: IHelpQuickAccessPickItem[] = []; for (const provider of this.registry.getQuickAccessProviders().sort((providerA, providerB) => providerA.prefix.localeCompare(providerB.prefix))) { + if (provider.prefix === HelpQuickAccessProvider.PREFIX) { + continue; // exclude help which is already active + } + for (const helpEntry of provider.helpEntries) { const prefix = helpEntry.prefix || provider.prefix; const label = prefix || '\u2026' /* ... */; diff --git a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts index 83798e7505f..297f71654b6 100644 --- a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts @@ -7,7 +7,7 @@ import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickI import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent } from 'vs/base/parts/quickinput/common/quickInput'; import { IQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess'; -import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { timeout } from 'vs/base/common/async'; export enum TriggerAction { @@ -25,7 +25,12 @@ export enum TriggerAction { /** * Update the results of the picker. */ - REFRESH_PICKER + REFRESH_PICKER, + + /** + * Remove the item from the picker. + */ + REMOVE_ITEM } export interface IPickerQuickAccessItem extends IQuickPickItem { @@ -85,7 +90,9 @@ export abstract class PickerQuickAccessProvider { + const picksDisposables = picksDisposable.value = new DisposableStore(); // Cancel any previous ask for picks and busy picksCts?.dispose(true); @@ -96,7 +103,7 @@ export abstract class PickerQuickAccessProvider(Extensions.Quickaccess); private readonly mapProviderToDescriptor = new Map(); - private lastActivePicker: IQuickPick | undefined = undefined; + private readonly lastAcceptedPickerValues = new Map(); + + private visibleQuickAccess: { + picker: IQuickPick, + descriptor: IQuickAccessProviderDescriptor | undefined, + value: string + } | undefined = undefined; constructor( @IQuickInputService private readonly quickInputService: IQuickInputService, @@ -25,33 +39,127 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon super(); } - show(value = '', options?: IQuickAccessOptions): void { - const disposables = new DisposableStore(); - - // Hide any previous picker if any - this.lastActivePicker?.hide(); + show(value = '', options?: IInternalQuickAccessOptions): void { // Find provider for the value to show const [provider, descriptor] = this.getOrInstantiateProvider(value); + // Return early if quick access is already showing on that same prefix + const visibleQuickAccess = this.visibleQuickAccess; + const visibleDescriptor = visibleQuickAccess?.descriptor; + if (visibleQuickAccess && descriptor && visibleDescriptor === descriptor) { + + // Apply value only if it is more specific than the prefix + // from the provider and we are not instructed to preserve + if (value !== descriptor.prefix && !options?.preserveFilterValue) { + visibleQuickAccess.picker.value = value; + } + + // Always adjust selection + this.adjustValueSelection(visibleQuickAccess.picker, descriptor, options); + + return; + } + + // Rewrite the filter value based on certain rules unless disabled + if (descriptor && !options?.preserveFilterValue) { + let newValue: string | undefined = undefined; + + // If we have a visible provider with a value, take it's filter value but + // rewrite to new provider prefix in case they differ + if (visibleQuickAccess && visibleDescriptor && visibleDescriptor !== descriptor) { + const newValueCandidateWithoutPrefix = visibleQuickAccess.value.substr(visibleDescriptor.prefix.length); + if (newValueCandidateWithoutPrefix) { + newValue = `${descriptor.prefix}${newValueCandidateWithoutPrefix}`; + } + } + + // Otherwise, take a default value as instructed + if (!newValue) { + const defaultFilterValue = provider?.defaultFilterValue; + if (defaultFilterValue === DefaultQuickAccessFilterValue.LAST) { + newValue = this.lastAcceptedPickerValues.get(descriptor); + } else if (typeof defaultFilterValue === 'string') { + newValue = `${descriptor.prefix}${defaultFilterValue}`; + } + } + + if (typeof newValue === 'string') { + value = newValue; + } + } + // Create a picker for the provider to use with the initial value // and adjust the filtering to exclude the prefix from filtering + const disposables = new DisposableStore(); const picker = disposables.add(this.quickInputService.createQuickPick()); - picker.placeholder = descriptor?.placeholder; picker.value = value; + this.adjustValueSelection(picker, descriptor, options); + picker.placeholder = descriptor?.placeholder; picker.quickNavigate = options?.quickNavigateConfiguration; - picker.valueSelection = options?.inputSelection ? [options.inputSelection.start, options.inputSelection.end] : [value.length, value.length]; + picker.hideInput = !!picker.quickNavigate && !visibleQuickAccess; // only hide input if there was no picker opened already + picker.itemActivation = options?.itemActivation || (options?.quickNavigateConfiguration ? ItemActivation.SECOND : ItemActivation.FIRST); picker.contextKey = descriptor?.contextKey; picker.filterValue = (value: string) => value.substring(descriptor ? descriptor.prefix.length : 0); - // Remember as last active picker and clean up once picker get's disposed - this.lastActivePicker = picker; + // Register listeners + const cancellationToken = this.registerPickerListeners(picker, provider, descriptor, value, disposables); + + // Ask provider to fill the picker as needed if we have one + if (provider) { + disposables.add(provider.provide(picker, cancellationToken)); + } + + // Finally, show the picker. This is important because a provider + // may not call this and then our disposables would leak that rely + // on the onDidHide event. + picker.show(); + } + + private adjustValueSelection(picker: IQuickPick, descriptor?: IQuickAccessProviderDescriptor, options?: IInternalQuickAccessOptions): void { + let valueSelection: [number, number]; + + // Preserve: just always put the cursor at the end + if (options?.preserveFilterValue) { + valueSelection = [picker.value.length, picker.value.length]; + } + + // Otherwise: select the value up until the prefix + else { + valueSelection = [descriptor?.prefix.length ?? 0, picker.value.length]; + } + + picker.valueSelection = valueSelection; + } + + private registerPickerListeners(picker: IQuickPick, provider: IQuickAccessProvider | undefined, descriptor: IQuickAccessProviderDescriptor | undefined, value: string, disposables: DisposableStore): CancellationToken { + + // Remember as last visible picker and clean up once picker get's disposed + const visibleQuickAccess = this.visibleQuickAccess = { picker, descriptor, value }; disposables.add(toDisposable(() => { - if (picker === this.lastActivePicker) { - this.lastActivePicker = undefined; + if (visibleQuickAccess === this.visibleQuickAccess) { + this.visibleQuickAccess = undefined; } })); + // Whenever the value changes, check if the provider has + // changed and if so - re-create the picker from the beginning + disposables.add(picker.onDidChangeValue(value => { + const [providerForValue] = this.getOrInstantiateProvider(value); + if (providerForValue !== provider) { + this.show(value, { preserveFilterValue: true } /* do not rewrite value from user typing! */); + } else { + visibleQuickAccess.value = value; // remember the value in our visible one + } + })); + + // Remember picker input for future use when accepting + if (descriptor) { + disposables.add(picker.onDidAccept(() => { + this.lastAcceptedPickerValues.set(descriptor, picker.value); + })); + } + // Create a cancellation token source that is valid as long as the // picker has not been closed without picking an item const cts = disposables.add(new CancellationTokenSource()); @@ -64,24 +172,7 @@ export class QuickAccessController extends Disposable implements IQuickAccessCon disposables.dispose(); }); - // Whenever the value changes, check if the provider has - // changed and if so - re-create the picker from the beginning - disposables.add(picker.onDidChangeValue(value => { - const [providerForValue] = this.getOrInstantiateProvider(value); - if (providerForValue !== provider) { - this.show(value); - } - })); - - // Ask provider to fill the picker as needed if we have one - if (provider) { - disposables.add(provider.provide(picker, cts.token)); - } - - // Finally, show the picker. This is important because a provider - // may not call this and then our disposables would leak that rely - // on the onDidHide event. - picker.show(); + return cts.token; } private getOrInstantiateProvider(value: string): [IQuickAccessProvider | undefined, IQuickAccessProviderDescriptor | undefined] { diff --git a/src/vs/platform/quickinput/browser/quickInput.ts b/src/vs/platform/quickinput/browser/quickInput.ts index 1e3a7b5ec0f..a5bf99e792f 100644 --- a/src/vs/platform/quickinput/browser/quickInput.ts +++ b/src/vs/platform/quickinput/browser/quickInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IQuickInputService, IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInputButton, IInputBox, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService, IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInputButton, IInputBox, QuickPickInput, IKeyMods } from 'vs/platform/quickinput/common/quickInput'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; @@ -154,8 +154,8 @@ export class QuickInputService extends Themable implements IQuickInputService { this.controller.navigate(next, quickNavigate); } - accept() { - return this.controller.accept(); + accept(keyMods?: IKeyMods) { + return this.controller.accept(keyMods); } back() { diff --git a/src/vs/platform/quickinput/common/quickAccess.ts b/src/vs/platform/quickinput/common/quickAccess.ts index bdac015721d..11832d89b2a 100644 --- a/src/vs/platform/quickinput/common/quickAccess.ts +++ b/src/vs/platform/quickinput/common/quickAccess.ts @@ -9,18 +9,20 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { first, coalesce } from 'vs/base/common/arrays'; import { startsWith } from 'vs/base/common/strings'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { ItemActivation } from 'vs/base/parts/quickinput/common/quickInput'; export interface IQuickAccessOptions { - /** - * Allows to control the part of text in the input field that should be selected. - */ - inputSelection?: { start: number; end: number; }; - /** * Allows to enable quick navigate support in quick input. */ quickNavigateConfiguration?: IQuickNavigateConfiguration; + + /** + * Allows to configure a different item activation strategy. + * By default the first item in the list will get activated. + */ + itemActivation?: ItemActivation } export interface IQuickAccessController { @@ -31,8 +33,32 @@ export interface IQuickAccessController { show(value?: string, options?: IQuickAccessOptions): void; } +export enum DefaultQuickAccessFilterValue { + + /** + * Keep the value as it is given to quick access. + */ + PRESERVE = 0, + + /** + * Use the value that was used last time something was accepted from the picker. + */ + LAST = 1 +} + export interface IQuickAccessProvider { + /** + * Allows to set a default filter value when the provider opens. This can be: + * - `undefined` to not specify any default value + * - `DefaultFilterValues.PRESERVE` to use the value that was last typed + * - `string` for the actual value to use + * + * Note: the default filter will only be used if quick access was opened with + * the exact prefix of the provider. Otherwise the filter value is preserved. + */ + readonly defaultFilterValue?: string | DefaultQuickAccessFilterValue; + /** * Called whenever a prefix was typed into quick pick that matches the provider. * diff --git a/src/vs/platform/quickinput/common/quickInput.ts b/src/vs/platform/quickinput/common/quickInput.ts index fdbded969de..03a03e5fa42 100644 --- a/src/vs/platform/quickinput/common/quickInput.ts +++ b/src/vs/platform/quickinput/common/quickInput.ts @@ -6,7 +6,7 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInputButton, IInputBox, QuickPickInput } from 'vs/base/parts/quickinput/common/quickInput'; +import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInputButton, IInputBox, QuickPickInput, IKeyMods } from 'vs/base/parts/quickinput/common/quickInput'; import { IQuickAccessController } from 'vs/platform/quickinput/common/quickAccess'; export * from 'vs/base/parts/quickinput/common/quickInput'; @@ -84,8 +84,11 @@ export interface IQuickInputService { /** * Accept the selected item. + * + * @param keyMods allows to override the state of key + * modifiers that should be present when invoking. */ - accept(): Promise; + accept(keyMods?: IKeyMods): Promise; /** * Cancels quick input and closes it. diff --git a/src/vs/platform/undoRedo/common/undoRedo.ts b/src/vs/platform/undoRedo/common/undoRedo.ts index b8fef5dd2f6..935e3ffcb22 100644 --- a/src/vs/platform/undoRedo/common/undoRedo.ts +++ b/src/vs/platform/undoRedo/common/undoRedo.ts @@ -30,6 +30,13 @@ export interface IWorkspaceUndoRedoElement { split(): IResourceUndoRedoElement[]; } +export type IUndoRedoElement = IResourceUndoRedoElement | IWorkspaceUndoRedoElement; + +export interface IPastFutureElements { + past: IUndoRedoElement[]; + future: IUndoRedoElement[]; +} + export interface IUndoRedoService { _serviceBrand: undefined; @@ -37,12 +44,18 @@ export interface IUndoRedoService { * Add a new element to the `undo` stack. * This will destroy the `redo` stack. */ - pushElement(element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement): void; + pushElement(element: IUndoRedoElement): void; /** * Get the last pushed element. If the last pushed element has been undone, returns null. */ - getLastElement(resource: URI): IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null; + getLastElement(resource: URI): IUndoRedoElement | null; + + getElements(resource: URI): IPastFutureElements; + + hasElements(resource: URI): boolean; + + setElementsIsValid(resource: URI, isValid: boolean): void; /** * Remove elements that target `resource`. diff --git a/src/vs/platform/undoRedo/common/undoRedoService.ts b/src/vs/platform/undoRedo/common/undoRedoService.ts index 8715d0d3198..65c9382526e 100644 --- a/src/vs/platform/undoRedo/common/undoRedoService.ts +++ b/src/vs/platform/undoRedo/common/undoRedoService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { IUndoRedoService, IResourceUndoRedoElement, IWorkspaceUndoRedoElement, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo'; +import { IUndoRedoService, IResourceUndoRedoElement, IWorkspaceUndoRedoElement, UndoRedoElementType, IUndoRedoElement, IPastFutureElements } from 'vs/platform/undoRedo/common/undoRedo'; import { URI } from 'vs/base/common/uri'; import { getComparisonKey as uriGetComparisonKey } from 'vs/base/common/resources'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -23,6 +23,7 @@ class ResourceStackElement { public readonly strResource: string; public readonly resources: URI[]; public readonly strResources: string[]; + public isValid: boolean; constructor(actual: IResourceUndoRedoElement) { this.actual = actual; @@ -31,6 +32,11 @@ class ResourceStackElement { this.strResource = uriGetComparisonKey(this.resource); this.resources = [this.resource]; this.strResources = [this.strResource]; + this.isValid = true; + } + + public setValid(isValid: boolean): void { + this.isValid = isValid; } } @@ -39,22 +45,57 @@ const enum RemovedResourceReason { NoParallelUniverses = 1 } +class ResourceReasonPair { + constructor( + public readonly resource: URI, + public readonly reason: RemovedResourceReason + ) { } +} + class RemovedResources { - public readonly set: Set = new Set(); - public readonly reason: [URI[], URI[]] = [[], []]; + private readonly elements = new Map(); + + private _getPath(resource: URI): string { + return resource.scheme === Schemas.file ? resource.fsPath : resource.path; + } public createMessage(): string { - let messages: string[] = []; - if (this.reason[RemovedResourceReason.ExternalRemoval].length > 0) { - const paths = this.reason[RemovedResourceReason.ExternalRemoval].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path); - messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", paths.join(', '))); + const externalRemoval: string[] = []; + const noParallelUniverses: string[] = []; + for (const [, element] of this.elements) { + const dest = ( + element.reason === RemovedResourceReason.ExternalRemoval + ? externalRemoval + : noParallelUniverses + ); + dest.push(this._getPath(element.resource)); } - if (this.reason[RemovedResourceReason.NoParallelUniverses].length > 0) { - const paths = this.reason[RemovedResourceReason.NoParallelUniverses].map(uri => uri.scheme === Schemas.file ? uri.fsPath : uri.path); - messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", paths.join(', '))); + + let messages: string[] = []; + if (externalRemoval.length > 0) { + messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", externalRemoval.join(', '))); + } + if (noParallelUniverses.length > 0) { + messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", noParallelUniverses.join(', '))); } return messages.join('\n'); } + + public get size(): number { + return this.elements.size; + } + + public has(strResource: string): boolean { + return this.elements.has(strResource); + } + + public set(strResource: string, value: ResourceReasonPair): void { + this.elements.set(strResource, value); + } + + public delete(strResource: string): boolean { + return this.elements.delete(strResource); + } } class WorkspaceStackElement { @@ -65,6 +106,7 @@ class WorkspaceStackElement { public readonly resources: URI[]; public readonly strResources: string[]; public removedResources: RemovedResources | null; + public invalidatedResources: RemovedResources | null; constructor(actual: IWorkspaceUndoRedoElement) { this.actual = actual; @@ -72,18 +114,37 @@ class WorkspaceStackElement { this.resources = actual.resources.slice(0); this.strResources = this.resources.map(resource => uriGetComparisonKey(resource)); this.removedResources = null; + this.invalidatedResources = null; } public removeResource(resource: URI, strResource: string, reason: RemovedResourceReason): void { if (!this.removedResources) { this.removedResources = new RemovedResources(); } - if (!this.removedResources.set.has(strResource)) { - this.removedResources.set.add(strResource); - this.removedResources.reason[reason].push(resource); + if (!this.removedResources.has(strResource)) { + this.removedResources.set(strResource, new ResourceReasonPair(resource, reason)); + } + } + + public setValid(resource: URI, strResource: string, isValid: boolean): void { + if (isValid) { + if (this.invalidatedResources) { + this.invalidatedResources.delete(strResource); + if (this.invalidatedResources.size === 0) { + this.invalidatedResources = null; + } + } + } else { + if (!this.invalidatedResources) { + this.invalidatedResources = new RemovedResources(); + } + if (!this.invalidatedResources.has(strResource)) { + this.invalidatedResources.set(strResource, new ResourceReasonPair(resource, RemovedResourceReason.ExternalRemoval)); + } } } } + type StackElement = ResourceStackElement | WorkspaceStackElement; class ResourceEditStack { @@ -110,7 +171,7 @@ export class UndoRedoService implements IUndoRedoService { this._editStacks = new Map(); } - public pushElement(_element: IResourceUndoRedoElement | IWorkspaceUndoRedoElement): void { + public pushElement(_element: IUndoRedoElement): void { const element: StackElement = (_element.type === UndoRedoElementType.Resource ? new ResourceStackElement(_element) : new WorkspaceStackElement(_element)); for (let i = 0, len = element.resources.length; i < len; i++) { const resource = element.resources[i]; @@ -131,11 +192,18 @@ export class UndoRedoService implements IUndoRedoService { } } editStack.future = []; + if (editStack.past.length > 0) { + const lastElement = editStack.past[editStack.past.length - 1]; + if (lastElement.type === UndoRedoElementType.Resource && !lastElement.isValid) { + // clear undo stack + editStack.past = []; + } + } editStack.past.push(element); } } - public getLastElement(resource: URI): IResourceUndoRedoElement | IWorkspaceUndoRedoElement | null { + public getLastElement(resource: URI): IUndoRedoElement | null { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; @@ -150,7 +218,7 @@ export class UndoRedoService implements IUndoRedoService { return null; } - private _splitPastWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set | null): void { + private _splitPastWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: RemovedResources | null): void { const individualArr = toRemove.actual.split(); const individualMap = new Map(); for (const _element of individualArr) { @@ -178,7 +246,7 @@ export class UndoRedoService implements IUndoRedoService { } } - private _splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: Set | null): void { + private _splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, ignoreResources: RemovedResources | null): void { const individualArr = toRemove.actual.split(); const individualMap = new Map(); for (const _element of individualArr) { @@ -224,6 +292,56 @@ export class UndoRedoService implements IUndoRedoService { } } + public setElementsIsValid(resource: URI, isValid: boolean): void { + const strResource = uriGetComparisonKey(resource); + if (this._editStacks.has(strResource)) { + const editStack = this._editStacks.get(strResource)!; + for (const element of editStack.past) { + if (element.type === UndoRedoElementType.Workspace) { + element.setValid(resource, strResource, isValid); + } else { + element.setValid(isValid); + } + } + for (const element of editStack.future) { + if (element.type === UndoRedoElementType.Workspace) { + element.setValid(resource, strResource, isValid); + } else { + element.setValid(isValid); + } + } + } + } + + // resource + + public hasElements(resource: URI): boolean { + const strResource = uriGetComparisonKey(resource); + if (this._editStacks.has(strResource)) { + const editStack = this._editStacks.get(strResource)!; + return (editStack.past.length > 0 || editStack.future.length > 0); + } + return false; + } + + public getElements(resource: URI): IPastFutureElements { + const past: IUndoRedoElement[] = []; + const future: IUndoRedoElement[] = []; + + const strResource = uriGetComparisonKey(resource); + if (this._editStacks.has(strResource)) { + const editStack = this._editStacks.get(strResource)!; + for (const element of editStack.past) { + past.push(element.actual); + } + for (const element of editStack.future) { + future.push(element.actual); + } + } + + return { past, future }; + } + public canUndo(resource: URI): boolean { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { @@ -257,11 +375,17 @@ export class UndoRedoService implements IUndoRedoService { private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise | void { if (element.removedResources) { - this._splitPastWorkspaceElement(element, element.removedResources.set); + this._splitPastWorkspaceElement(element, element.removedResources); const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage()); this._notificationService.info(message); return this.undo(resource); } + if (element.invalidatedResources) { + this._splitPastWorkspaceElement(element, element.invalidatedResources); + const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage()); + this._notificationService.info(message); + return this.undo(resource); + } // this must be the last past element in all the impacted resources! let affectedEditStacks: ResourceEditStack[] = []; @@ -313,6 +437,12 @@ export class UndoRedoService implements IUndoRedoService { } private _resourceUndo(editStack: ResourceEditStack, element: ResourceStackElement): Promise | void { + if (!element.isValid) { + // invalid element => immediately flush edit stack! + editStack.past = []; + editStack.future = []; + return; + } editStack.past.pop(); editStack.future.push(element); return this._safeInvoke(element, () => element.actual.undo()); @@ -348,11 +478,17 @@ export class UndoRedoService implements IUndoRedoService { private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise | void { if (element.removedResources) { - this._splitFutureWorkspaceElement(element, element.removedResources.set); + this._splitFutureWorkspaceElement(element, element.removedResources); const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage()); this._notificationService.info(message); return this.redo(resource); } + if (element.invalidatedResources) { + this._splitFutureWorkspaceElement(element, element.invalidatedResources); + const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage()); + this._notificationService.info(message); + return this.redo(resource); + } // this must be the last future element in all the impacted resources! let affectedEditStacks: ResourceEditStack[] = []; @@ -383,6 +519,12 @@ export class UndoRedoService implements IUndoRedoService { } private _resourceRedo(editStack: ResourceEditStack, element: ResourceStackElement): Promise | void { + if (!element.isValid) { + // invalid element => immediately flush edit stack! + editStack.past = []; + editStack.future = []; + return; + } editStack.future.pop(); editStack.past.push(element); return this._safeInvoke(element, () => element.actual.redo()); diff --git a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts index f00644b7772..8ecbd09d7ac 100644 --- a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts +++ b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts @@ -7,9 +7,9 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { IFileService, IFileContent, FileChangesEvent, FileOperationResult, FileOperationError } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { URI } from 'vs/base/common/uri'; -import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, ISyncResourceHandle, USER_DATA_SYNC_SCHEME } from 'vs/platform/userDataSync/common/userDataSync'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { joinPath, dirname, isEqual } from 'vs/base/common/resources'; +import { joinPath, dirname, isEqual, basename } from 'vs/base/common/resources'; import { CancelablePromise } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -173,20 +173,36 @@ export abstract class AbstractSynchroniser extends Disposable { return !!lastSyncData; } - async getConflictContent(conflictResource: URI): Promise { + async getRemoteSyncResourceHandles(): Promise { + const handles = await this.userDataSyncStoreService.getAllRefs(this.resource); + return handles.map(({ created, ref }) => ({ created, uri: this.toRemoteBackupResource(ref) })); + } + + async getLocalSyncResourceHandles(): Promise { + const handles = await this.userDataSyncBackupStoreService.getAllRefs(this.resource); + return handles.map(({ created, ref }) => ({ created, uri: this.toLocalBackupResource(ref) })); + } + + private toRemoteBackupResource(ref: string): URI { + return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote-backup', path: `/${this.resource}/${ref}` }); + } + + private toLocalBackupResource(ref: string): URI { + return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local-backup', path: `/${this.resource}/${ref}` }); + } + + async resolveContent(uri: URI): Promise { + const ref = basename(uri); + if (isEqual(uri, this.toRemoteBackupResource(ref))) { + const { content } = await this.getUserData(ref); + return content; + } + if (isEqual(uri, this.toLocalBackupResource(ref))) { + return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref); + } return null; } - async getRemoteContent(ref?: string): Promise { - const refOrLastSyncUserData: string | IRemoteUserData | null = ref || await this.getLastSyncUserData(); - const { content } = await this.getUserData(refOrLastSyncUserData); - return content; - } - - async getLocalBackupContent(ref?: string): Promise { - return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref); - } - async resetLocal(): Promise { try { await this.fileService.del(this.lastSyncResource); @@ -265,9 +281,10 @@ export abstract class AbstractSynchroniser extends Disposable { return this.userDataSyncBackupStoreService.backup(this.resource, JSON.stringify(syncData)); } + abstract stop(): Promise; + protected abstract readonly version: number; protected abstract performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise; - abstract stop(): Promise; } export interface IFileSyncPreviewResult { @@ -310,7 +327,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser { this.setStatus(SyncStatus.Idle); } - async getConflictContent(conflictResource: URI): Promise { + protected async getConflictContent(conflictResource: URI): Promise { if (isEqual(this.remotePreviewResource, conflictResource) || isEqual(this.localPreviewResource, conflictResource)) { if (this.syncPreviewResultPromise) { const result = await this.syncPreviewResultPromise; diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index 01ad8d03ab0..70b478c1828 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { Event } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -16,6 +16,9 @@ import { isNonEmptyArray } from 'vs/base/common/arrays'; import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { URI } from 'vs/base/common/uri'; +import { joinPath, dirname, basename } from 'vs/base/common/resources'; +import { format } from 'vs/base/common/jsonFormatter'; +import { applyEdits } from 'vs/base/common/jsonEdit'; interface ISyncPreviewResult { readonly localExtensions: ISyncExtension[]; @@ -120,28 +123,24 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse async stop(): Promise { } - async getRemoteContent(ref?: string, fragment?: string): Promise { - const content = await super.getRemoteContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; + async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + return [{ resource: joinPath(uri, 'extensions.json') }]; } - async getLocalBackupContent(ref?: string, fragment?: string): Promise { - let content = await super.getLocalBackupContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); + async resolveContent(uri: URI): Promise { + let content = await super.resolveContent(uri); + if (content) { + return content; } - return content; - } - - private getFragment(content: string, fragment: string): string | null { - const syncData = this.parseSyncData(content); - if (syncData) { - switch (fragment) { - case 'extensions': - return syncData.content; + content = await super.resolveContent(dirname(uri)); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + switch (basename(uri)) { + case 'extensions.json': + const edits = format(syncData.content, undefined, {}); + return applyEdits(syncData.content, edits); + } } } return null; diff --git a/src/vs/platform/userDataSync/common/globalStateSync.ts b/src/vs/platform/userDataSync/common/globalStateSync.ts index f1d8a26a6a3..0546c73e87e 100644 --- a/src/vs/platform/userDataSync/common/globalStateSync.ts +++ b/src/vs/platform/userDataSync/common/globalStateSync.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, IStorageValue } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { VSBuffer } from 'vs/base/common/buffer'; import { Event } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { dirname } from 'vs/base/common/resources'; +import { dirname, joinPath, basename } from 'vs/base/common/resources'; import { IFileService } from 'vs/platform/files/common/files'; import { IStringDictionary } from 'vs/base/common/collections'; import { edit } from 'vs/platform/userDataSync/common/content'; @@ -17,8 +17,8 @@ import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { URI } from 'vs/base/common/uri'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { format } from 'vs/base/common/jsonFormatter'; +import { applyEdits } from 'vs/base/common/jsonEdit'; const argvStoragePrefx = 'globalState.argv.'; const argvProperties: string[] = ['locale']; @@ -112,28 +112,24 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs async stop(): Promise { } - async getRemoteContent(ref?: string, fragment?: string): Promise { - let content = await super.getRemoteContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; + async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + return [{ resource: joinPath(uri, 'globalState.json') }]; } - async getLocalBackupContent(ref?: string, fragment?: string): Promise { - let content = await super.getLocalBackupContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); + async resolveContent(uri: URI): Promise { + let content = await super.resolveContent(uri); + if (content) { + return content; } - return content; - } - - private getFragment(content: string, fragment: string): string | null { - const syncData = this.parseSyncData(content); - if (syncData) { - switch (fragment) { - case 'globalState': - return syncData.content; + content = await super.resolveContent(dirname(uri)); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + switch (basename(uri)) { + case 'globalState.json': + const edits = format(syncData.content, undefined, {}); + return applyEdits(syncData.content, edits); + } } } return null; diff --git a/src/vs/platform/userDataSync/common/keybindingsSync.ts b/src/vs/platform/userDataSync/common/keybindingsSync.ts index 0aa4c71114e..0ea9b58ccdd 100644 --- a/src/vs/platform/userDataSync/common/keybindingsSync.ts +++ b/src/vs/platform/userDataSync/common/keybindingsSync.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; -import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME } from 'vs/platform/userDataSync/common/userDataSync'; +import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge'; import { VSBuffer } from 'vs/base/common/buffer'; import { parse } from 'vs/base/common/json'; @@ -19,7 +19,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays'; import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { URI } from 'vs/base/common/uri'; -import { joinPath, isEqual } from 'vs/base/common/resources'; +import { joinPath, isEqual, dirname, basename } from 'vs/base/common/resources'; interface ISyncContent { mac?: string; @@ -160,38 +160,36 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem return false; } - async getConflictContent(conflictResource: URI): Promise { - const content = await super.getConflictContent(conflictResource); - return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null; + async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + return [{ resource: joinPath(uri, 'keybindings.json'), comparableResource: this.file }]; } - async getRemoteContent(ref?: string, fragment?: string): Promise { - const content = await super.getRemoteContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); + async resolveContent(uri: URI): Promise { + if (isEqual(this.remotePreviewResource, uri)) { + return this.getConflictContent(uri); } - return content; - } - - async getLocalBackupContent(ref?: string, fragment?: string): Promise { - let content = await super.getLocalBackupContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); + let content = await super.resolveContent(uri); + if (content) { + return content; } - return content; - } - - private getFragment(content: string, fragment: string): string | null { - const syncData = this.parseSyncData(content); - if (syncData) { - switch (fragment) { - case 'keybindings': - return this.getKeybindingsContentFromSyncContent(syncData.content); + content = await super.resolveContent(dirname(uri)); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + switch (basename(uri)) { + case 'keybindings.json': + return this.getKeybindingsContentFromSyncContent(syncData.content); + } } } return null; } + protected async getConflictContent(conflictResource: URI): Promise { + const content = await super.getConflictContent(conflictResource); + return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null; + } + protected async performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise { try { const result = await this.getPreview(remoteUserData, lastSyncUserData); diff --git a/src/vs/platform/userDataSync/common/settingsSync.ts b/src/vs/platform/userDataSync/common/settingsSync.ts index 234496f2f4b..9b4d848b5a6 100644 --- a/src/vs/platform/userDataSync/common/settingsSync.ts +++ b/src/vs/platform/userDataSync/common/settingsSync.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; -import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, CONFIGURATION_SYNC_STORE_KEY, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME } from 'vs/platform/userDataSync/common/userDataSync'; +import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, CONFIGURATION_SYNC_STORE_KEY, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { VSBuffer } from 'vs/base/common/buffer'; import { parse } from 'vs/base/common/json'; import { localize } from 'vs/nls'; @@ -20,7 +20,7 @@ import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { URI } from 'vs/base/common/uri'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { joinPath, isEqual } from 'vs/base/common/resources'; +import { joinPath, isEqual, dirname, basename } from 'vs/base/common/resources'; export interface ISettingsSyncContent { settings: string; @@ -173,7 +173,35 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser { return false; } - async getConflictContent(conflictResource: URI): Promise { + async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + return [{ resource: joinPath(uri, 'settings.json'), comparableResource: this.file }]; + } + + async resolveContent(uri: URI): Promise { + if (isEqual(this.remotePreviewResource, uri)) { + return this.getConflictContent(uri); + } + let content = await super.resolveContent(uri); + if (content) { + return content; + } + content = await super.resolveContent(dirname(uri)); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + const settingsSyncContent = this.parseSettingsSyncContent(syncData.content); + if (settingsSyncContent) { + switch (basename(uri)) { + case 'settings.json': + return settingsSyncContent.settings; + } + } + } + } + return null; + } + + protected async getConflictContent(conflictResource: URI): Promise { let content = await super.getConflictContent(conflictResource); if (content !== null) { const settingsSyncContent = this.parseSettingsSyncContent(content); @@ -188,36 +216,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser { return content; } - async getRemoteContent(ref?: string, fragment?: string): Promise { - let content = await super.getRemoteContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; - } - - async getLocalBackupContent(ref?: string, fragment?: string): Promise { - let content = await super.getLocalBackupContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; - } - - private getFragment(content: string, fragment: string): string | null { - const syncData = this.parseSyncData(content); - if (syncData) { - const settingsSyncContent = this.parseSettingsSyncContent(syncData.content); - if (settingsSyncContent) { - switch (fragment) { - case 'settings': - return settingsSyncContent.settings; - } - } - } - return null; - } - async acceptConflict(conflict: URI, content: string): Promise { if (this.status === SyncStatus.HasConflicts && (isEqual(this.localPreviewResource, conflict) || isEqual(this.remotePreviewResource, conflict)) diff --git a/src/vs/platform/userDataSync/common/snippetsSync.ts b/src/vs/platform/userDataSync/common/snippetsSync.ts index f9d70f18abc..e12cef7ce1f 100644 --- a/src/vs/platform/userDataSync/common/snippetsSync.ts +++ b/src/vs/platform/userDataSync/common/snippetsSync.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, UserDataSyncError, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, UserDataSyncError, UserDataSyncErrorCode, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService, FileChangesEvent, IFileStat, IFileContent, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -11,7 +11,7 @@ import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/us import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStringDictionary } from 'vs/base/common/collections'; import { URI } from 'vs/base/common/uri'; -import { joinPath, extname, relativePath, isEqualOrParent, isEqual, basename } from 'vs/base/common/resources'; +import { joinPath, extname, relativePath, isEqualOrParent, isEqual, basename, dirname } from 'vs/base/common/resources'; import { VSBuffer } from 'vs/base/common/buffer'; import { merge } from 'vs/platform/userDataSync/common/snippetsMerge'; import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; @@ -148,8 +148,46 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD this.setStatus(SyncStatus.Idle); } - async getConflictContent(conflictResource: URI): Promise { - if (isEqualOrParent(conflictResource.with({ scheme: this.syncFolder.scheme }), this.snippetsPreviewFolder) && this.syncPreviewResultPromise) { + async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + let content = await super.resolveContent(uri); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + const snippets = this.parseSnippets(syncData); + const result = []; + for (const snippet of Object.keys(snippets)) { + const resource = joinPath(uri, snippet); + const comparableResource = joinPath(this.snippetsFolder, snippet); + const exists = await this.fileService.exists(comparableResource); + result.push({ resource, comparableResource: exists ? comparableResource : undefined }); + } + return result; + } + } + return []; + } + + async resolveContent(uri: URI): Promise { + if (isEqualOrParent(uri.with({ scheme: this.syncFolder.scheme }), this.snippetsPreviewFolder)) { + return this.getConflictContent(uri); + } + let content = await super.resolveContent(uri); + if (content) { + return content; + } + content = await super.resolveContent(dirname(uri)); + if (content) { + const syncData = this.parseSyncData(content); + if (syncData) { + const snippets = this.parseSnippets(syncData); + return snippets[basename(uri)] || null; + } + } + return null; + } + + protected async getConflictContent(conflictResource: URI): Promise { + if (this.syncPreviewResultPromise) { const result = await this.syncPreviewResultPromise; const key = relativePath(this.snippetsPreviewFolder, conflictResource.with({ scheme: this.snippetsPreviewFolder.scheme }))!; if (conflictResource.scheme === this.snippetsPreviewFolder.scheme) { @@ -162,37 +200,6 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD return null; } - async getRemoteContent(ref?: string, fragment?: string): Promise { - const content = await super.getRemoteContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; - } - - async getLocalBackupContent(ref?: string, fragment?: string): Promise { - let content = await super.getLocalBackupContent(ref); - if (content !== null && fragment) { - return this.getFragment(content, fragment); - } - return content; - } - - private getFragment(content: string, fragment: string): string | null { - const syncData = this.parseSyncData(content); - return syncData ? this.getFragmentFromSyncData(syncData, fragment) : null; - } - - private getFragmentFromSyncData(syncData: ISyncData, fragment: string): string | null { - switch (fragment) { - case 'snippets': - return syncData.content; - default: - const remoteSnippets = this.parseSnippets(syncData); - return remoteSnippets[fragment] || null; - } - } - async acceptConflict(conflictResource: URI, content: string): Promise { const conflict = this.conflicts.filter(({ local, remote }) => isEqual(local, conflictResource) || isEqual(remote, conflictResource))[0]; if (this.status === SyncStatus.HasConflicts && conflict) { diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index d60ad78872e..53134ef71f7 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IStringDictionary } from 'vs/base/common/collections'; import { FormattingOptions } from 'vs/base/common/jsonFormatter'; import { URI } from 'vs/base/common/uri'; -import { joinPath, dirname, basename, isEqualOrParent } from 'vs/base/common/resources'; +import { joinPath, isEqualOrParent } from 'vs/base/common/resources'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IProductService } from 'vs/platform/product/common/productService'; import { distinct } from 'vs/base/common/arrays'; @@ -125,7 +125,7 @@ export interface IUserDataSyncStore { } export function getUserDataSyncStore(productService: IProductService, configurationService: IConfigurationService): IUserDataSyncStore | undefined { - const value = productService[CONFIGURATION_SYNC_STORE_KEY] || configurationService.getValue<{ url: string, authenticationProviderId: string }>(CONFIGURATION_SYNC_STORE_KEY); + const value = configurationService.getValue<{ url: string, authenticationProviderId: string }>(CONFIGURATION_SYNC_STORE_KEY) || productService[CONFIGURATION_SYNC_STORE_KEY]; if (value && value.url && value.authenticationProviderId) { return { url: joinPath(URI.parse(value.url), 'v1'), @@ -247,6 +247,11 @@ export const enum SyncStatus { HasConflicts = 'hasConflicts', } +export interface ISyncResourceHandle { + created: number; + uri: URI; +} + export type Conflict = { remote: URI, local: URI }; export interface IUserDataSynchroniser { @@ -267,11 +272,12 @@ export interface IUserDataSynchroniser { hasLocalData(): Promise; resetLocal(): Promise; - getConflictContent(conflictResource: URI): Promise; + resolveContent(resource: URI): Promise; acceptConflict(conflictResource: URI, content: string): Promise; - getRemoteContent(ref?: string, fragment?: string): Promise; - getLocalBackupContent(ref?: string, fragment?: string): Promise; + getRemoteSyncResourceHandles(): Promise; + getLocalSyncResourceHandles(): Promise; + getAssociatedResources(syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]>; } //#endregion @@ -319,6 +325,10 @@ export interface IUserDataSyncService { isFirstTimeSyncWithMerge(): Promise; resolveContent(resource: URI): Promise; acceptConflict(conflictResource: URI, content: string): Promise; + + getLocalSyncResourceHandles(resource: SyncResource): Promise; + getRemoteSyncResourceHandles(resource: SyncResource): Promise; + getAssociatedResources(resource: SyncResource, syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]>; } export const IUserDataAutoSyncService = createDecorator('IUserDataAutoSyncService'); @@ -351,25 +361,6 @@ export const USER_DATA_SYNC_SCHEME = 'vscode-userdata-sync'; export const CONTEXT_SYNC_STATE = new RawContextKey('syncStatus', SyncStatus.Uninitialized); export const CONTEXT_SYNC_ENABLEMENT = new RawContextKey('syncEnabled', false); -export function toRemoteBackupSyncResource(resource: SyncResource, ref?: string): URI { - return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote-backup', path: `/${resource}/${ref ? ref : 'latest'}` }); -} -export function toLocalBackupSyncResource(resource: SyncResource, ref?: string): URI { - return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local-backup', path: `/${resource}/${ref ? ref : 'latest'}` }); -} -export function resolveBackupSyncResource(resource: URI): { remote: boolean, resource: SyncResource, path: string } | null { - if (resource.scheme === USER_DATA_SYNC_SCHEME - && resource.authority === 'remote-backup' || resource.authority === 'local-backup') { - const resourceKey: SyncResource = basename(dirname(resource)) as SyncResource; - const path = resource.path.substring(resourceKey.length + 1); - if (resourceKey && path) { - const remote = resource.authority === 'remote-backup'; - return { remote, resource: resourceKey, path }; - } - } - return null; -} - export const PREVIEW_DIR_NAME = 'preview'; export function getSyncResourceFromLocalPreview(localPreview: URI, environmentService: IEnvironmentService): SyncResource | undefined { if (localPreview.scheme === USER_DATA_SYNC_SCHEME) { diff --git a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts index 744e9c904a5..53d2983ad09 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { Event, Emitter } from 'vs/base/common/event'; -import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncService, IUserDataSyncStoreService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync'; +import { Event } from 'vs/base/common/event'; +import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync'; import { URI } from 'vs/base/common/uri'; import { IStringDictionary } from 'vs/base/common/collections'; import { FormattingOptions } from 'vs/base/common/jsonFormatter'; @@ -30,14 +30,17 @@ export class UserDataSyncChannel implements IServerChannel { call(context: any, command: string, args?: any): Promise { switch (command) { case '_getInitialData': return Promise.resolve([this.service.status, this.service.conflicts, this.service.lastSyncTime]); - case 'sync': return this.service.sync(); - case 'acceptConflict': return this.service.acceptConflict(URI.revive(args[0]), args[1]); case 'pull': return this.service.pull(); + case 'sync': return this.service.sync(); case 'stop': this.service.stop(); return Promise.resolve(); case 'reset': return this.service.reset(); case 'resetLocal': return this.service.resetLocal(); - case 'resolveContent': return this.service.resolveContent(URI.revive(args[0])); case 'isFirstTimeSyncWithMerge': return this.service.isFirstTimeSyncWithMerge(); + case 'acceptConflict': return this.service.acceptConflict(URI.revive(args[0]), args[1]); + case 'resolveContent': return this.service.resolveContent(URI.revive(args[0])); + case 'getLocalSyncResourceHandles': return this.service.getLocalSyncResourceHandles(args[0]); + case 'getRemoteSyncResourceHandles': return this.service.getRemoteSyncResourceHandles(args[0]); + case 'getAssociatedResources': return this.service.getAssociatedResources(args[0], { created: args[1].created, uri: URI.revive(args[1].uri) }); } throw new Error('Invalid call'); } @@ -101,41 +104,6 @@ export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService { } -export class UserDataSyncStoreServiceChannel implements IServerChannel { - - constructor(private readonly service: IUserDataSyncStoreService) { } - - listen(_: unknown, event: string): Event { - throw new Error(`Event not found: ${event}`); - } - - call(context: any, command: string, args?: any): Promise { - switch (command) { - case 'getAllRefs': return this.service.getAllRefs(args[0]); - case 'resolveContent': return this.service.resolveContent(args[0], args[1]); - case 'delete': return this.service.delete(args[0]); - } - throw new Error('Invalid call'); - } -} - -export class UserDataSyncBackupStoreServiceChannel implements IServerChannel { - - constructor(private readonly service: IUserDataSyncBackupStoreService) { } - - listen(_: unknown, event: string): Event { - throw new Error(`Event not found: ${event}`); - } - - call(context: any, command: string, args?: any): Promise { - switch (command) { - case 'getAllRefs': return this.service.getAllRefs(args[0]); - case 'resolveContent': return this.service.resolveContent(args[0], args[1]); - } - throw new Error('Invalid call'); - } -} - export class StorageKeysSyncRegistryChannel implements IServerChannel { constructor(private readonly service: IStorageKeysSyncRegistryService) { } diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts index 92a79046411..d601761a271 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode, UserDataSyncError, resolveBackupSyncResource, SyncResourceConflicts } from 'vs/platform/userDataSync/common/userDataSync'; +import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode, UserDataSyncError, SyncResourceConflicts, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Emitter, Event } from 'vs/base/common/event'; @@ -188,25 +188,27 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ } async resolveContent(resource: URI): Promise { - const result = resolveBackupSyncResource(resource); - if (result) { - const synchronizer = this.synchronisers.filter(s => s.resource === result.resource)[0]; - if (synchronizer) { - const ref = result.path !== 'latest' ? result.path : undefined; - return result.remote ? synchronizer.getRemoteContent(ref, resource.fragment) : synchronizer.getLocalBackupContent(ref, resource.fragment); - } - } - - for (const synchronizer of this.synchronisers) { - const content = await synchronizer.getConflictContent(resource); - if (content !== null) { + for (const synchroniser of this.synchronisers) { + const content = await synchroniser.resolveContent(resource); + if (content) { return content; } } - return null; } + getRemoteSyncResourceHandles(resource: SyncResource): Promise { + return this.getSynchroniser(resource).getRemoteSyncResourceHandles(); + } + + getLocalSyncResourceHandles(resource: SyncResource): Promise { + return this.getSynchroniser(resource).getLocalSyncResourceHandles(); + } + + getAssociatedResources(resource: SyncResource, syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + return this.getSynchroniser(resource).getAssociatedResources(syncResourceHandle); + } + async isFirstTimeSyncWithMerge(): Promise { await this.checkEnablement(); if (!await this.userDataSyncStoreService.manifest()) { diff --git a/src/vs/platform/userDataSync/test/common/synchronizer.test.ts b/src/vs/platform/userDataSync/test/common/synchronizer.test.ts index 006947f829c..9b9ffb82e55 100644 --- a/src/vs/platform/userDataSync/test/common/synchronizer.test.ts +++ b/src/vs/platform/userDataSync/test/common/synchronizer.test.ts @@ -68,7 +68,7 @@ suite('TestSynchronizer', () => { teardown(() => disposableStore.clear()); test('status is syncing', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); const actual: SyncStatus[] = []; disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status))); @@ -85,7 +85,7 @@ suite('TestSynchronizer', () => { }); test('status is set correctly when sync is finished', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); testObject.syncBarrier.open(); const actual: SyncStatus[] = []; @@ -97,7 +97,7 @@ suite('TestSynchronizer', () => { }); test('status is set correctly when sync has conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); testObject.syncResult = { status: SyncStatus.HasConflicts }; testObject.syncBarrier.open(); @@ -110,7 +110,7 @@ suite('TestSynchronizer', () => { }); test('status is set correctly when sync has errors', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); testObject.syncResult = { error: true }; testObject.syncBarrier.open(); @@ -127,7 +127,7 @@ suite('TestSynchronizer', () => { }); test('sync should not run if syncing already', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); const promise = Event.toPromise(testObject.onDoSyncCall.event); testObject.sync(); @@ -144,7 +144,7 @@ suite('TestSynchronizer', () => { }); test('sync should not run if disabled', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); client.instantiationService.get(IUserDataSyncEnablementService).setResourceEnablement(testObject.resource, false); const actual: SyncStatus[] = []; @@ -157,7 +157,7 @@ suite('TestSynchronizer', () => { }); test('sync should not run if there are conflicts', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); testObject.syncResult = { status: SyncStatus.HasConflicts }; testObject.syncBarrier.open(); await testObject.sync(); @@ -171,7 +171,7 @@ suite('TestSynchronizer', () => { }); test('request latest data on precondition failure', async () => { - const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings, 'settings'); + const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings); // Sync once testObject.syncBarrier.open(); await testObject.sync(); diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 54caa9768fb..6074ae5204c 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -40,6 +40,26 @@ declare module 'vscode' { readonly removed: string[]; } + /** + * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed. + */ + export interface AuthenticationSessionsChangeEvent { + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added. + */ + readonly added: string[]; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed. + */ + readonly removed: string[]; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed. + */ + readonly changed: string[]; + } + export interface AuthenticationProvider { /** * Used as an identifier for extensions trying to work with a particular @@ -53,7 +73,7 @@ declare module 'vscode' { * An [event](#Event) which fires when the array of sessions has changed, or data * within a session has changed. */ - readonly onDidChangeSessions: Event; + readonly onDidChangeSessions: Event; /** * Returns an array of current sessions. @@ -99,7 +119,7 @@ declare module 'vscode' { * within a session has changed for a provider. Fires with the ids of the providers * that have had session data change. */ - export const onDidChangeSessions: Event; + export const onDidChangeSessions: Event<{ [providerId: string]: AuthenticationSessionsChangeEvent }>; } //#endregion @@ -1269,17 +1289,11 @@ declare module 'vscode' { //#region Custom editors: https://github.com/microsoft/vscode/issues/77131 - // TODO: - // - Think about where a rename would live. - // - Think about handling go to line? (add other editor options? reveal?) - // - Should we expose edits? - // - More properties from `TextDocument`? - /** * Defines the editing capability of a custom webview editor. This allows the webview editor to hook into standard * editor events such as `undo` or `save`. * - * @param EditType Type of edits. + * @param EditType Type of edits used for the documents this delegate handles. */ interface CustomEditorEditingDelegate { /** @@ -1290,7 +1304,7 @@ declare module 'vscode' { * * @return Thenable signaling that the save has completed. */ - save(document: CustomDocument, cancellation: CancellationToken): Thenable; + save(document: CustomDocument, cancellation: CancellationToken): Thenable; /** * Save the existing resource at a new path. @@ -1300,7 +1314,7 @@ declare module 'vscode' { * * @return Thenable signaling that the save has completed. */ - saveAs(document: CustomDocument, targetResource: Uri): Thenable; + saveAs(document: CustomDocument, targetResource: Uri): Thenable; /** * Event triggered by extensions to signal to VS Code that an edit has occurred. @@ -1317,7 +1331,7 @@ declare module 'vscode' { * * @return Thenable signaling that the change has completed. */ - applyEdits(document: CustomDocument, edits: readonly EditType[]): Thenable; + applyEdits(document: CustomDocument, edits: readonly EditType[]): Thenable; /** * Undo a set of edits. @@ -1329,7 +1343,7 @@ declare module 'vscode' { * * @return Thenable signaling that the change has completed. */ - undoEdits(document: CustomDocument, edits: readonly EditType[]): Thenable; + undoEdits(document: CustomDocument, edits: readonly EditType[]): Thenable; /** * Revert the file to its last saved state. @@ -1339,7 +1353,7 @@ declare module 'vscode' { * * @return Thenable signaling that the change has completed. */ - revert(document: CustomDocument, edits: CustomDocumentRevert): Thenable; + revert(document: CustomDocument, edits: CustomDocumentRevert): Thenable; /** * Back up the resource in its current state. @@ -1360,22 +1374,25 @@ declare module 'vscode' { * in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather * than cancelling it to ensure that VS Code has some valid backup. */ - backup(document: CustomDocument, cancellation: CancellationToken): Thenable; + backup(document: CustomDocument, cancellation: CancellationToken): Thenable; } /** - * Event triggered by extensions to signal to VS Code that an edit has occurred on a CustomDocument``. + * Event triggered by extensions to signal to VS Code that an edit has occurred on a `CustomDocument`. + * + * @param EditType Type of edits used for the document. */ interface CustomDocumentEditEvent { /** * Document the edit is for. */ - readonly document: CustomDocument; + readonly document: CustomDocument; /** * Object that describes the edit. * - * Edit objects are passed back to your extension in `undoEdits`, `applyEdits`, and `revert`. + * Edit objects are passed back to your extension in `CustomEditorEditingDelegate.undoEdits`, + * `CustomEditorEditingDelegate.applyEdits`, and `CustomEditorEditingDelegate.revert`. */ readonly edit: EditType; @@ -1403,13 +1420,19 @@ declare module 'vscode' { /** * Represents a custom document used by a `CustomEditorProvider`. * - * Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a - * `CustomDocument` is managed by VS Code. When no more references remain to a given `CustomDocument`, - * then it is disposed of. + * All custom documents must subclass `CustomDocument`. Custom documents are only used within a given + * `CustomEditorProvider`. The lifecycle of a `CustomDocument` is managed by VS Code. When no more references + * remain to a `CustomDocument`, it is disposed of. * - * @param UserDataType Type of custom object that extensions can store on the document. + * @param EditType Type of edits used in this document. */ - interface CustomDocument { + class CustomDocument { + /** + * @param viewType The associated uri for this document. + * @param uri The associated viewType for this document. + */ + constructor(viewType: string, uri: Uri); + /** * The associated viewType for this document. */ @@ -1426,12 +1449,17 @@ declare module 'vscode' { readonly onDidDispose: Event; /** - * Custom data that an extension can store on the document. + * List of edits from document open to the document's current state. */ - userData?: UserDataType; + readonly appliedEdits: ReadonlyArray; - // TODO: Should we expose edits here? - // This could be helpful for tracking the life cycle of edits + /** + * List of edits from document open to the document's last saved point. + * + * The save point will be behind `appliedEdits` if the user saves and then continues editing, + * or in front of the last entry in `appliedEdits` if the user saves and then hits undo. + */ + readonly savedEdits: ReadonlyArray; } /** @@ -1443,7 +1471,8 @@ declare module 'vscode' { * You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text * based documents, use [`WebviewTextEditorProvider`](#WebviewTextEditorProvider) instead. */ - export interface CustomEditorProvider { + export interface CustomEditorProvider { + /** * Resolve the model for a given resource. * @@ -1452,18 +1481,18 @@ declare module 'vscode' { * If all editors for a given resource are closed, the `CustomDocument` is disposed of. Opening an editor at * this point will trigger another call to `resolveCustomDocument`. * - * @param document Document to resolve. + * @param uri Uri of the document to open. * @param token A cancellation token that indicates the result is no longer needed. * - * @return The capabilities of the resolved document. + * @return The custom document. */ - resolveCustomDocument(document: CustomDocument, token: CancellationToken): Thenable; // TODO: rename to open? + openCustomDocument(uri: Uri, token: CancellationToken): Thenable>; /** * Resolve a webview editor for a given resource. * - * This is called when a user first opens a resource for a `CustomTextEditorProvider`, or if they reopen an - * existing editor using this `CustomTextEditorProvider`. + * This is called when a user first opens a resource for a `CustomEditorProvider`, or if they reopen an + * existing editor using this `CustomEditorProvider`. * * To resolve a webview editor, the provider must fill in its initial html content and hook up all * the event listeners it is interested it. The provider can also hold onto the `WebviewPanel` to use later, @@ -1475,14 +1504,14 @@ declare module 'vscode' { * * @return Thenable indicating that the webview editor has been resolved. */ - resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable; + resolveCustomEditor(document: CustomDocument, webviewPanel: WebviewPanel, token: CancellationToken): Thenable; /** * Defines the editing capability of a custom webview document. * * When not provided, the document is considered readonly. */ - readonly editingDelegate?: CustomEditorEditingDelegate; + readonly editingDelegate?: CustomEditorEditingDelegate; } /** @@ -1496,6 +1525,7 @@ declare module 'vscode' { * For binary files or more specialized use cases, see [CustomEditorProvider](#CustomEditorProvider). */ export interface CustomTextEditorProvider { + /** * Resolve a webview editor for a given text resource. * @@ -1529,8 +1559,6 @@ declare module 'vscode' { * @return Thenable indicating that the webview editor has been moved. */ moveCustomTextEditor?(newDocument: TextDocument, existingWebviewPanel: WebviewPanel, token: CancellationToken): Thenable; - - // TODO: handlesMove?: boolean; } namespace window { @@ -1540,14 +1568,16 @@ declare module 'vscode' { * @param viewType Type of the webview editor provider. This should match the `viewType` from the * `package.json` contributions. * @param provider Provider that resolves editors. - * @param webviewOptions Content settings for the webview panels that the provider is given. + * @param options Options for the provider * * @return Disposable that unregisters the provider. */ export function registerCustomEditorProvider( viewType: string, provider: CustomEditorProvider | CustomTextEditorProvider, - webviewOptions?: WebviewPanelOptions, // TODO: move this onto provider? + options?: { + readonly webviewOptions?: WebviewPanelOptions; + } ): Disposable; } @@ -1636,7 +1666,16 @@ declare module 'vscode' { export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; export interface NotebookCellMetadata { + /** + * Controls if the content of a cell is editable or not. + */ editable: boolean; + + /** + * Controls if the cell is executable. + * This metadata is ignored for markdown cell. + */ + runnable: boolean; } export interface NotebookCell { @@ -1650,7 +1689,23 @@ declare module 'vscode' { } export interface NotebookDocumentMetadata { + /** + * Controls if users can add or delete cells + * Default to true + */ editable: boolean; + + /** + * Default value for [cell editable metadata](#NotebookCellMetadata.editable). + * Default to true. + */ + cellEditable: boolean; + + /** + * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). + * Default to true. + */ + cellRunnable: boolean; } export interface NotebookDocument { @@ -1682,7 +1737,7 @@ declare module 'vscode' { /** * Create a notebook cell. The cell is not inserted into current document when created. Extensions should insert the cell into the document by [TextDocument.cells](#TextDocument.cells) */ - createCell(content: string, language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata): NotebookCell; + createCell(content: string, language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): NotebookCell; } export interface NotebookProvider { @@ -1874,14 +1929,10 @@ declare module 'vscode' { export interface Timeline { readonly paging?: { /** - * A provider-defined cursor specifing the starting point of timeline items which are after the ones returned. + * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. + * Use `undefined` to signal that there are no more items to be returned. */ - readonly cursor?: string - - /** - * A flag which indicates whether there are more items that weren't returned. - */ - readonly more?: boolean; + readonly cursor: string | undefined; } /** @@ -1892,7 +1943,7 @@ declare module 'vscode' { export interface TimelineOptions { /** - * A provider-defined cursor specifing the starting point of the timeline items that should be returned. + * A provider-defined cursor specifying the starting point of the timeline items that should be returned. */ cursor?: string; @@ -2049,7 +2100,7 @@ declare module 'vscode' { * @param pathFragments * @returns A new uri */ - export function joinPaths(base: Uri, ...pathFragments: string[]): Uri; + export function joinPath(base: Uri, ...pathFragments: string[]): Uri; } //#endregion diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 15af9ba8bc6..29460ca8c92 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import * as modes from 'vs/editor/common/modes'; import * as nls from 'vs/nls'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; @@ -12,13 +12,141 @@ import { ExtHostAuthenticationShape, ExtHostContext, IExtHostContext, MainContex import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import Severity from 'vs/base/common/severity'; +import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; + +interface AuthDependent { + providerId: string; + label: string; + scopes: string[]; + scopeDescriptions?: string; +} + +const BUILT_IN_AUTH_DEPENDENTS: AuthDependent[] = [ + { + providerId: 'microsoft', + label: 'Settings sync', + scopes: ['https://management.core.windows.net/.default', 'offline_access'], + scopeDescriptions: 'Read user email' + } +]; + +export class MainThreadAuthenticationProvider extends Disposable { + private _sessionMenuItems = new Map(); + private _sessionIds: string[] = []; -export class MainThreadAuthenticationProvider { constructor( private readonly _proxy: ExtHostAuthenticationShape, public readonly id: string, - public readonly displayName: string - ) { } + public readonly displayName: string, + public readonly dependents: AuthDependent[] + ) { + super(); + + if (!dependents.length) { + return; + } + + this.registerCommandsAndContextMenuItems(); + } + + private setPermissionsForAccount(quickInputService: IQuickInputService, doLogin?: boolean) { + const quickPick = quickInputService.createQuickPick(); + quickPick.canSelectMany = true; + const items = this.dependents.map(dependent => { + return { + label: dependent.label, + description: dependent.scopeDescriptions, + picked: true, + scopes: dependent.scopes + }; + }); + + quickPick.items = items; + // TODO read from storage and filter is not doLogin + quickPick.selectedItems = items; + quickPick.title = nls.localize('signInTo', "Sign in to {0}", this.displayName); + quickPick.placeholder = nls.localize('accountPermissions', "Choose what features and extensions to authorize to use this account"); + + quickPick.onDidAccept(() => { + const scopes = quickPick.selectedItems.reduce((previous, current) => previous.concat((current as any).scopes), []); + if (scopes.length && doLogin) { + this.login(scopes); + } + + quickPick.dispose(); + }); + + quickPick.onDidHide(() => { + quickPick.dispose(); + }); + + quickPick.show(); + } + + private registerCommandsAndContextMenuItems(): void { + this._register(CommandsRegistry.registerCommand({ + id: `signIn${this.id}`, + handler: (accessor, args) => { + this.setPermissionsForAccount(accessor.get(IQuickInputService), true); + }, + })); + + this._register(MenuRegistry.appendMenuItem(MenuId.AccountsContext, { + group: '2_providers', + command: { + id: `signIn${this.id}`, + title: nls.localize('addAccount', "Sign in to {0}", this.displayName) + }, + order: 3 + })); + + this._proxy.$getSessions(this.id).then(sessions => { + sessions.forEach(session => this.registerSession(session)); + }); + } + + private registerSession(session: modes.AuthenticationSession) { + this._sessionIds.push(session.id); + const menuItem = MenuRegistry.appendMenuItem(MenuId.AccountsContext, { + group: '1_accounts', + command: { + id: `configureSessions${session.id}`, + title: session.accountName + }, + order: 3 + }); + + const manageCommand = CommandsRegistry.registerCommand({ + id: `configureSessions${session.id}`, + handler: (accessor, args) => { + const quickInputService = accessor.get(IQuickInputService); + + const quickPick = quickInputService.createQuickPick(); + const items = [{ label: 'Sign Out' }]; + + quickPick.items = items; + + quickPick.onDidAccept(e => { + const selected = quickPick.selectedItems[0]; + if (selected.label === 'Sign Out') { + this.logout(session.id); + } + + quickPick.dispose(); + }); + + quickPick.onDidHide(_ => { + quickPick.dispose(); + }); + + quickPick.show(); + }, + }); + + this._sessionMenuItems.set(session.id, [menuItem, manageCommand]); + } async getSessions(): Promise> { return (await this._proxy.$getSessions(this.id)).map(session => { @@ -30,6 +158,24 @@ export class MainThreadAuthenticationProvider { }); } + async updateSessionItems(): Promise { + const currentSessions = await this._proxy.$getSessions(this.id); + const removedSessionIds = this._sessionIds.filter(id => !currentSessions.some(session => session.id === id)); + const addedSessions = currentSessions.filter(session => !this._sessionIds.some(id => id === session.id)); + + removedSessionIds.forEach(id => { + const disposeables = this._sessionMenuItems.get(id); + if (disposeables) { + disposeables.forEach(disposeable => disposeable.dispose()); + this._sessionMenuItems.delete(id); + } + }); + + addedSessions.forEach(session => this.registerSession(session)); + + this._sessionIds = currentSessions.map(session => session.id); + } + login(scopes: string[]): Promise { return this._proxy.$login(this.id, scopes).then(session => { return { @@ -40,8 +186,14 @@ export class MainThreadAuthenticationProvider { }); } - logout(accountId: string): Promise { - return this._proxy.$logout(this.id, accountId); + logout(sessionId: string): Promise { + return this._proxy.$logout(this.id, sessionId); + } + + dispose(): void { + super.dispose(); + this._sessionMenuItems.forEach(item => item.forEach(d => d.dispose())); + this._sessionMenuItems.clear(); } } @@ -59,8 +211,10 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostAuthentication); } - $registerAuthenticationProvider(id: string, displayName: string): void { - const provider = new MainThreadAuthenticationProvider(this._proxy, id, displayName); + async $registerAuthenticationProvider(id: string, displayName: string): Promise { + const dependentBuiltIns = BUILT_IN_AUTH_DEPENDENTS.filter(dependency => dependency.providerId === id); + + const provider = new MainThreadAuthenticationProvider(this._proxy, id, displayName, dependentBuiltIns); this.authenticationService.registerAuthenticationProvider(id, provider); } @@ -68,8 +222,8 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu this.authenticationService.unregisterAuthenticationProvider(id); } - $onDidChangeSessions(id: string): void { - this.authenticationService.sessionsUpdate(id); + $onDidChangeSessions(id: string, event: modes.AuthenticationSessionsChangeEvent): void { + this.authenticationService.sessionsUpdate(id, event); } async $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise { diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 8c2b12f2c9c..bbdaae1b8b5 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx import { Disposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/browser/notebookService'; -import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellsSplice, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -127,7 +127,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo } } - async $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise { + async $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise { let controller = this._notebookProviders.get(viewType); if (controller) { @@ -135,6 +135,14 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo } } + async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise { + let controller = this._notebookProviders.get(viewType); + + if (controller) { + controller.updateNotebookCellMetadata(resource, handle, metadata); + } + } + async resolveNotebook(viewType: string, uri: URI): Promise { let handle = await this._proxy.$resolveNotebook(viewType, uri); return handle; @@ -228,25 +236,25 @@ export class MainThreadNotebookController implements IMainNotebookController { document?.textModel.updateLanguages(languages); } - updateNotebookMetadata(resource: UriComponents, metadata: NotebookDocumentMetadata | undefined) { + updateNotebookMetadata(resource: UriComponents, metadata: NotebookDocumentMetadata) { let document = this._mapping.get(URI.from(resource).toString()); document?.textModel.updateNotebookMetadata(metadata); } + updateNotebookCellMetadata(resource: UriComponents, handle: number, metadata: NotebookCellMetadata) { + let document = this._mapping.get(URI.from(resource).toString()); + document?.textModel.updateNotebookCellMetadata(handle, metadata); + } + updateNotebookRenderers(resource: UriComponents, renderers: number[]): void { let document = this._mapping.get(URI.from(resource).toString()); document?.textModel.updateRenderers(renderers); } - updateNotebookActiveCell(uri: URI, cellHandle: number): void { - let mainthreadNotebook = this._mapping.get(URI.from(uri).toString()); - mainthreadNotebook?.textModel.updateActiveCell(cellHandle); - } - async createRawCell(uri: URI, index: number, language: string, type: CellKind): Promise { let cell = await this._proxy.$createEmptyCell(this._viewType, uri, index, language, type); if (cell) { - let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs); + let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs, cell.metadata); return mainCell; } @@ -263,12 +271,8 @@ export class MainThreadNotebookController implements IMainNotebookController { return false; } - async executeNotebookActiveCell(uri: URI): Promise { - let mainthreadNotebook = this._mapping.get(URI.from(uri).toString()); - - if (mainthreadNotebook && mainthreadNotebook.textModel.activeCell) { - return this._proxy.$executeNotebook(this._viewType, uri, mainthreadNotebook.textModel.activeCell.handle); - } + async executeNotebookCell(uri: URI, handle: number): Promise { + return this._proxy.$executeNotebook(this._viewType, uri, handle); } async destoryNotebookDocument(notebook: INotebookTextModel): Promise { diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index 1947655d902..7eb55b81fda 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -11,6 +11,7 @@ import { Disposable, DisposableStore, dispose, IDisposable, IReference } from 'v import { Schemas } from 'vs/base/common/network'; import { basename } from 'vs/base/common/path'; import { isWeb } from 'vs/base/common/platform'; +import { isEqual } from 'vs/base/common/resources'; import { escape } from 'vs/base/common/strings'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as modes from 'vs/editor/common/modes'; @@ -28,6 +29,7 @@ import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } fr import { IEditorInput, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; +import { CustomDocumentBackupData } from 'vs/workbench/contrib/customEditor/browser/customEditorInputFactory'; import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { CustomTextEditorModel } from 'vs/workbench/contrib/customEditor/common/customTextEditorModel'; import { WebviewExtensionDescription, WebviewIcons } from 'vs/workbench/contrib/webview/browser/webview'; @@ -70,6 +72,10 @@ class WebviewInputStore { public get size(): number { return this._handlesToInputs.size; } + + [Symbol.iterator](): Iterator { + return this._handlesToInputs.values(); + } } class WebviewViewTypeTransformer { @@ -374,7 +380,10 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma const model = modelType === ModelType.Text ? CustomTextEditorModel.create(this._instantiationService, viewType, resource) - : MainThreadCustomEditorModel.create(this._instantiationService, this._proxy, viewType, resource, cancellation); + : MainThreadCustomEditorModel.create(this._instantiationService, this._proxy, viewType, resource, () => { + return Array.from(this._webviewInputs) + .filter(editor => editor instanceof CustomEditorInput && isEqual(editor.resource, resource)) as CustomEditorInput[]; + }, cancellation); return this._customEditorService.models.add(resource, viewType, model); } @@ -548,7 +557,6 @@ namespace HotExitState { export type State = typeof Allowed | typeof NotAllowed | Pending; } -const customDocumentFileScheme = 'custom'; class MainThreadCustomEditorModel extends Disposable implements ICustomEditorModel, IWorkingCopy { @@ -562,17 +570,19 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod proxy: extHostProtocol.ExtHostWebviewsShape, viewType: string, resource: URI, + getEditors: () => CustomEditorInput[], cancellation: CancellationToken, ) { const { editable } = await proxy.$createWebviewCustomEditorDocument(resource, viewType, cancellation); - return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, editable); + return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, editable, getEditors); } constructor( private readonly _proxy: extHostProtocol.ExtHostWebviewsShape, private readonly _viewType: string, - private readonly _realResource: URI, + private readonly _editorResource: URI, private readonly _editable: boolean, + private readonly _getEditors: () => CustomEditorInput[], @IWorkingCopyService workingCopyService: IWorkingCopyService, @ILabelService private readonly _labelService: ILabelService, @IFileService private readonly _fileService: IFileService, @@ -587,9 +597,9 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod dispose() { if (this._editable) { - this._undoService.removeElements(this._realResource); + this._undoService.removeElements(this._editorResource); } - this._proxy.$disposeWebviewCustomEditorDocument(this._realResource, this._viewType); + this._proxy.$disposeWebviewCustomEditorDocument(this._editorResource, this._viewType); super.dispose(); } @@ -598,15 +608,15 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod public get resource() { // Make sure each custom editor has a unique resource for backup and edits return URI.from({ - scheme: customDocumentFileScheme, + scheme: Schemas.vscodeCustomEditor, authority: this._viewType, - path: this._realResource.path, - query: JSON.stringify(this._realResource.toJSON()) + path: this._editorResource.path, + query: JSON.stringify(this._editorResource.toJSON()), }); } public get name() { - return basename(this._labelService.getUriLabel(this._realResource)); + return basename(this._labelService.getUriLabel(this._editorResource)); } public get capabilities(): WorkingCopyCapabilities { @@ -645,7 +655,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod this._undoService.pushElement({ type: UndoRedoElementType.Resource, - resource: this._realResource, + resource: this._editorResource, label: label ?? localize('defaultEditLabel', "Edit"), undo: () => this.undo(), redo: () => this.redo(), @@ -663,11 +673,18 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod } const undoneEdit = this._edits[this._currentEditIndex]; - await this._proxy.$undo(this._realResource, this.viewType, undoneEdit); - this.change(() => { --this._currentEditIndex; }); + await this._proxy.$undo(this._editorResource, this.viewType, undoneEdit, this.getEditState()); + } + + private getEditState(): extHostProtocol.CustomDocumentEditState { + return { + allEdits: this._edits, + currentIndex: this._currentEditIndex, + saveIndex: this._savePoint, + }; } private async redo(): Promise { @@ -681,10 +698,10 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod } const redoneEdit = this._edits[this._currentEditIndex + 1]; - await this._proxy.$redo(this._realResource, this.viewType, redoneEdit); this.change(() => { ++this._currentEditIndex; }); + await this._proxy.$redo(this._editorResource, this.viewType, redoneEdit, this.getEditState()); } private spliceEdits(editToInsert?: number) { @@ -696,7 +713,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod : this._edits.splice(start, toRemove); if (removedEdits.length) { - this._proxy.$disposeEdits(this._realResource, this._viewType, removedEdits); + this._proxy.$disposeEdits(this._editorResource, this._viewType, removedEdits); } } @@ -728,7 +745,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod editsToRedo = this._edits.slice(this._currentEditIndex, this._savePoint); } - this._proxy.$revert(this._realResource, this.viewType, { undoneEdits: editsToUndo, redoneEdits: editsToRedo }); + this._proxy.$revert(this._editorResource, this.viewType, { undoneEdits: editsToUndo, redoneEdits: editsToRedo }, this.getEditState()); this.change(() => { this._currentEditIndex = this._savePoint; this.spliceEdits(); @@ -739,7 +756,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod if (!this._editable) { return false; } - await createCancelablePromise(token => this._proxy.$onSave(this._realResource, this.viewType, token)); + await createCancelablePromise(token => this._proxy.$onSave(this._editorResource, this.viewType, token)); this.change(() => { this._savePoint = this._currentEditIndex; }); @@ -748,7 +765,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod public async saveAs(resource: URI, targetResource: URI, _options?: ISaveOptions): Promise { if (this._editable) { - await this._proxy.$onSaveAs(this._realResource, this.viewType, targetResource); + await this._proxy.$onSaveAs(this._editorResource, this.viewType, targetResource); this.change(() => { this._savePoint = this._currentEditIndex; }); @@ -761,9 +778,25 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod } public async backup(): Promise { - const backupData: IWorkingCopyBackup = { + const editors = this._getEditors(); + if (!editors.length) { + throw new Error('No editors found for resource, cannot back up'); + } + const primaryEditor = editors[0]; + + const backupData: IWorkingCopyBackup = { meta: { viewType: this.viewType, + editorResource: this._editorResource, + extension: primaryEditor.extension ? { + id: primaryEditor.extension.id.value, + location: primaryEditor.extension.location, + } : undefined, + webview: { + id: primaryEditor.id, + options: primaryEditor.webview.options, + state: primaryEditor.webview.state, + } } }; @@ -777,7 +810,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod const pendingState = new HotExitState.Pending( createCancelablePromise(token => - this._proxy.$backup(this._realResource.toJSON(), this.viewType, token))); + this._proxy.$backup(this._editorResource.toJSON(), this.viewType, token))); this._hotExitState = pendingState; try { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index f9c38f65db6..aef8a4aa053 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -199,7 +199,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I login(providerId: string, scopes: string[]): Thenable { return extHostAuthentication.login(extension, providerId, scopes); }, - get onDidChangeSessions(): Event { + get onDidChangeSessions(): Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> { return extHostAuthentication.onDidChangeSessions; }, }; @@ -546,9 +546,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } })); }, withProgress(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable) { - if (typeof options.location === 'object') { - checkProposedApiEnabled(extension); - } return extHostProgress.withProgress(extension, options, task); }, createOutputChannel(name: string): vscode.OutputChannel { @@ -583,9 +580,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => { return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer); }, - registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: vscode.WebviewPanelOptions) => { + registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: { webviewOptions?: vscode.WebviewPanelOptions }) => { checkProposedApiEnabled(extension); - return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options); + return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options?.webviewOptions); }, registerDecorationProvider(provider: vscode.DecorationProvider) { checkProposedApiEnabled(extension); @@ -1026,12 +1023,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I CallHierarchyItem: extHostTypes.CallHierarchyItem, DebugConsoleMode: extHostTypes.DebugConsoleMode, Decoration: extHostTypes.Decoration, - WebviewContentState: extHostTypes.WebviewContentState, UIKind: UIKind, ColorThemeKind: extHostTypes.ColorThemeKind, TimelineItem: extHostTypes.TimelineItem, CellKind: extHostTypes.CellKind, - CellOutputKind: extHostTypes.CellOutputKind + CellOutputKind: extHostTypes.CellOutputKind, + CustomDocument: extHostTypes.CustomDocument, }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 8c12660c19b..a6e41261c6c 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -156,7 +156,7 @@ export interface MainThreadCommentsShape extends IDisposable { export interface MainThreadAuthenticationShape extends IDisposable { $registerAuthenticationProvider(id: string, displayName: string): void; $unregisterAuthenticationProvider(id: string): void; - $onDidChangeSessions(id: string): void; + $onDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void; $getSessionsPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise; $loginPrompt(providerId: string, providerName: string, extensionId: string, extensionName: string): Promise; } @@ -622,6 +622,12 @@ export interface WebviewPanelViewStateData { }; } +export interface CustomDocumentEditState { + readonly allEdits: readonly number[]; + readonly currentIndex: number; + readonly saveIndex: number; +} + export interface ExtHostWebviewsShape { $onMessage(handle: WebviewPanelHandle, message: any): void; $onMissingCsp(handle: WebviewPanelHandle, extensionId: string): void; @@ -634,9 +640,9 @@ export interface ExtHostWebviewsShape { $createWebviewCustomEditorDocument(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise<{ editable: boolean }>; $disposeWebviewCustomEditorDocument(resource: UriComponents, viewType: string): Promise; - $undo(resource: UriComponents, viewType: string, editId: number): Promise; - $redo(resource: UriComponents, viewType: string, editId: number): Promise; - $revert(resource: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }): Promise; + $undo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise; + $redo(resource: UriComponents, viewType: string, editId: number, state: CustomDocumentEditState): Promise; + $revert(resource: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: CustomDocumentEditState): Promise; $disposeEdits(resourceComponents: UriComponents, viewType: string, editIds: number[]): void; $onSave(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; @@ -687,7 +693,8 @@ export interface MainThreadNotebookShape extends IDisposable { $unregisterNotebookRenderer(handle: number): Promise; $createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise; $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise; - $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata | undefined): Promise; + $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise; + $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata | undefined): Promise; $spliceNotebookCells(viewType: string, resource: UriComponents, splices: NotebookCellsSplice[], renderers: number[]): Promise; $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise; $postMessage(handle: number, value: any): Promise; diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index e57c6e13961..3584908894a 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -17,8 +17,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { private _onDidChangeAuthenticationProviders = new Emitter(); readonly onDidChangeAuthenticationProviders: Event = this._onDidChangeAuthenticationProviders.event; - private _onDidChangeSessions = new Emitter(); - readonly onDidChangeSessions: Event = this._onDidChangeSessions.event; + private _onDidChangeSessions = new Emitter<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }>(); + readonly onDidChangeSessions: Event<{ [providerId: string]: vscode.AuthenticationSessionsChangeEvent }> = this._onDidChangeSessions.event; constructor(mainContext: IMainContext) { this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication); @@ -85,9 +85,9 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._authenticationProviders.set(provider.id, provider); - const listener = provider.onDidChangeSessions(_ => { - this._proxy.$onDidChangeSessions(provider.id); - this._onDidChangeSessions.fire([provider.id]); + const listener = provider.onDidChangeSessions(e => { + this._proxy.$onDidChangeSessions(provider.id, e); + this._onDidChangeSessions.fire({ [provider.id]: e }); }); this._proxy.$registerAuthenticationProvider(provider.id, provider.displayName); diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index b160a6d3394..3a60ef04051 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -16,6 +16,12 @@ import { INotebookDisplayOrder, ITransformedDisplayOutputDto, IOrderedMimeType, import { ISplice } from 'vs/base/common/sequence'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; +const notebookDocumentMetadataDefaults: vscode.NotebookDocumentMetadata = { + editable: true, + cellEditable: true, + cellRunnable: true +}; + export class ExtHostCell implements vscode.NotebookCell { public source: string[]; @@ -27,13 +33,16 @@ export class ExtHostCell implements vscode.NotebookCell { private _outputMapping = new Set(); constructor( + private viewType: string, + private documentUri: URI, readonly handle: number, readonly uri: URI, private _content: string, public cellKind: CellKind, public language: string, outputs: any[], - public metadata: vscode.NotebookCellMetadata | undefined, + private _metadata: vscode.NotebookCellMetadata | undefined, + private _proxy: MainThreadNotebookShape ) { this.source = this._content.split(/\r|\n|\r\n/g); this._outputs = outputs; @@ -62,6 +71,20 @@ export class ExtHostCell implements vscode.NotebookCell { this._onDidChangeOutputs.fire(diffs); } + get metadata() { + return this._metadata; + } + + set metadata(newMetadata: vscode.NotebookCellMetadata | undefined) { + const newMetadataWithDefaults: vscode.NotebookCellMetadata | undefined = newMetadata ? { + editable: newMetadata.editable, + runnable: newMetadata.runnable + } : undefined; + + this._metadata = newMetadataWithDefaults; + this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, newMetadataWithDefaults); + } + getContent(): string { if (this._textDocument && this._initalVersion !== this._textDocument?.version) { return this._textDocument.getText(); @@ -131,14 +154,14 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages); } - private _metadata: vscode.NotebookDocumentMetadata | undefined = undefined; + private _metadata: vscode.NotebookDocumentMetadata | undefined = notebookDocumentMetadataDefaults; get metadata() { return this._metadata; } set metadata(newMetadata: vscode.NotebookDocumentMetadata | undefined) { - this._metadata = newMetadata; + this._metadata = newMetadata || notebookDocumentMetadataDefaults; this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata); } @@ -201,6 +224,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo language: cell.language, cellKind: cell.cellKind, outputs: outputs, + metadata: cell.metadata, isDirty: false }; }); @@ -346,7 +370,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook onDidReceiveMessage: vscode.Event = this._onDidReceiveMessage.event; constructor( - viewType: string, + private readonly viewType: string, readonly id: string, public uri: URI, private _proxy: MainThreadNotebookShape, @@ -381,7 +405,7 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook createCell(content: string, language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): vscode.NotebookCell { const handle = ExtHostNotebookEditor._cellhandlePool++; const uri = CellUri.generate(this.document.uri, handle); - const cell = new ExtHostCell(handle, uri, content, type, language, outputs, metadata); + const cell = new ExtHostCell(this.viewType, this.uri, handle, uri, content, type, language, outputs, metadata, this._proxy); return cell; } @@ -579,7 +603,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN let editor = this._editors.get(URI.revive(uri).toString()); let document = this._documents.get(URI.revive(uri).toString()); - let rawCell = editor?.editor.createCell('', language, type, [], undefined) as ExtHostCell; + let rawCell = editor?.editor.createCell('', language, type, [], { editable: true, runnable: true }) as ExtHostCell; document?.insertCell(index, rawCell!); let allDocuments = this._documentsAndEditors.allDocuments(); diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 8f93ace6539..7ce3ecf2590 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4,16 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { coalesce, equals } from 'vs/base/common/arrays'; +import { escapeCodicons } from 'vs/base/common/codicons'; import { illegalArgument } from 'vs/base/common/errors'; +import { Emitter } from 'vs/base/common/event'; import { IRelativePattern } from 'vs/base/common/glob'; import { isMarkdownString } from 'vs/base/common/htmlContent'; import { startsWith } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; -import type * as vscode from 'vscode'; import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files'; import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver'; -import { escapeCodicons } from 'vs/base/common/codicons'; +import type * as vscode from 'vscode'; +import { Cache } from './cache'; +import { assertIsDefined } from 'vs/base/common/types'; function es5ClassCompat(target: Function): any { ///@ts-ignore @@ -2538,13 +2541,6 @@ export class Decoration { bubble?: boolean; } -export enum WebviewContentState { - Readonly = 1, - Unchanged = 2, - Dirty = 3, -} - - //#region Theming @es5ClassCompat @@ -2584,3 +2580,84 @@ export class TimelineItem implements vscode.TimelineItem { } //#endregion Timeline + +//#region Custom Editors + +interface EditState { + readonly allEdits: readonly number[]; + readonly currentIndex: number; + readonly saveIndex: number; +} + +export class CustomDocument implements vscode.CustomDocument { + + + readonly #edits = new Cache('edits'); + + #editState: EditState; + + readonly #viewType: string; + readonly #uri: vscode.Uri; + + constructor(viewType: string, uri: vscode.Uri) { + this.#viewType = viewType; + this.#uri = uri; + this.#editState = { + allEdits: [], + currentIndex: 0, + saveIndex: 0 + }; + } + + //#region Public API + + public get viewType(): string { return this.#viewType; } + + public get uri(): vscode.Uri { return this.#uri; } + + #onDidDispose = new Emitter(); + public readonly onDidDispose = this.#onDidDispose.event; + + get appliedEdits() { + return this.#editState.allEdits.slice(0, this.#editState.currentIndex + 1) + .map(id => this._getEdit(id)); + } + + get savedEdits() { + return this.#editState.allEdits.slice(0, this.#editState.saveIndex + 1) + .map(id => this._getEdit(id)); + } + + //#endregion + + /** @internal */ _dispose(): void { + this.#onDidDispose.fire(); + this.#onDidDispose.dispose(); + } + + /** @internal */ _updateEditState(state: EditState) { + this.#editState = state; + } + + /** @internal*/ _getEdit(editId: number): EditType { + return assertIsDefined(this.#edits.get(editId, 0)); + } + + /** @internal*/ _disposeEdits(editIds: number[]) { + for (const editId of editIds) { + this.#edits.delete(editId); + } + } + + /** @internal*/ _addEdit(edit: EditType): number { + const id = this.#edits.add([edit]); + this.#editState = { + allEdits: [...this.#editState.allEdits.slice(0, this.#editState.currentIndex), id], + currentIndex: this.#editState.currentIndex + 1, + saveIndex: this.#editState.saveIndex, + }; + return id; + } +} + +// #endregion diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 83c595b3f89..e42c3b0ef80 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -18,9 +18,8 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor'; import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview'; import type * as vscode from 'vscode'; -import { Cache } from './cache'; -import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewExtensionDescription, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol'; -import { Disposable as VSCodeDisposable } from './extHostTypes'; +import * as extHostProtocol from './extHost.protocol'; +import * as extHostTypes from './extHostTypes'; type IconPath = URI | { light: URI, dark: URI }; @@ -33,8 +32,8 @@ export class ExtHostWebview implements vscode.Webview { public readonly onDidReceiveMessage: Event = this._onMessageEmitter.event; constructor( - private readonly _handle: WebviewPanelHandle, - private readonly _proxy: MainThreadWebviewsShape, + private readonly _handle: extHostProtocol.WebviewPanelHandle, + private readonly _proxy: extHostProtocol.MainThreadWebviewsShape, private _options: vscode.WebviewOptions, private readonly _initData: WebviewInitData, private readonly _workspace: IExtHostWorkspace | undefined, @@ -99,8 +98,8 @@ export class ExtHostWebview implements vscode.Webview { export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPanel { - private readonly _handle: WebviewPanelHandle; - private readonly _proxy: MainThreadWebviewsShape; + private readonly _handle: extHostProtocol.WebviewPanelHandle; + private readonly _proxy: extHostProtocol.MainThreadWebviewsShape; private readonly _viewType: string; private _title: string; private _iconPath?: IconPath; @@ -121,8 +120,8 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa public readonly onDidChangeViewState = this.#onDidChangeViewState.event; constructor( - handle: WebviewPanelHandle, - proxy: MainThreadWebviewsShape, + handle: extHostProtocol.WebviewPanelHandle, + proxy: extHostProtocol.MainThreadWebviewsShape, viewType: string, title: string, viewColumn: vscode.ViewColumn | undefined, @@ -246,114 +245,14 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa } } -class CustomDocument extends Disposable implements vscode.CustomDocument { - - public static create( - viewType: string, - uri: vscode.Uri, - editingDelegate: vscode.CustomEditorEditingDelegate | undefined - ) { - return Object.seal(new CustomDocument(viewType, uri, editingDelegate)); - } - - // Explicitly initialize all properties as we seal the object after creation! - - readonly #_edits = new Cache('edits'); - - readonly #viewType: string; - readonly #uri: vscode.Uri; - readonly #editingDelegate: vscode.CustomEditorEditingDelegate | undefined; - - private constructor( - viewType: string, - uri: vscode.Uri, - editingDelegate: vscode.CustomEditorEditingDelegate | undefined, - ) { - super(); - this.#viewType = viewType; - this.#uri = uri; - this.#editingDelegate = editingDelegate; - } - - dispose() { - this.#onDidDispose.fire(); - super.dispose(); - } - - //#region Public API - - public get viewType(): string { return this.#viewType; } - - public get uri(): vscode.Uri { return this.#uri; } - - #onDidDispose = this._register(new Emitter()); - public readonly onDidDispose = this.#onDidDispose.event; - - public userData: unknown = undefined; - - //#endregion - - //#region Internal - - /** @internal*/ async _revert(changes: { undoneEdits: number[], redoneEdits: number[] }) { - const editing = this.getEditingDelegate(); - const undoneEdits = changes.undoneEdits.map(id => this.#_edits.get(id, 0)); - const appliedEdits = changes.redoneEdits.map(id => this.#_edits.get(id, 0)); - return editing.revert(this, { undoneEdits, appliedEdits }); - } - - /** @internal*/ _undo(editId: number) { - const editing = this.getEditingDelegate(); - const edit = this.#_edits.get(editId, 0); - return editing.undoEdits(this, [edit]); - } - - /** @internal*/ _redo(editId: number) { - const editing = this.getEditingDelegate(); - const edit = this.#_edits.get(editId, 0); - return editing.applyEdits(this, [edit]); - } - - /** @internal*/ _save(cancellation: CancellationToken) { - return this.getEditingDelegate().save(this, cancellation); - } - - /** @internal*/ _saveAs(target: vscode.Uri) { - return this.getEditingDelegate().saveAs(this, target); - } - - /** @internal*/ _backup(cancellation: CancellationToken) { - return this.getEditingDelegate().backup(this, cancellation); - } - - /** @internal*/ _disposeEdits(editIds: number[]) { - for (const editId of editIds) { - this.#_edits.delete(editId); - } - } - - /** @internal*/ _pushEdit(edit: unknown): number { - return this.#_edits.add([edit]); - } - - //#endregion - - private getEditingDelegate(): vscode.CustomEditorEditingDelegate { - if (!this.#editingDelegate) { - throw new Error('Document is not editable'); - } - return this.#editingDelegate; - } -} - class WebviewDocumentStore { - private readonly _documents = new Map(); + private readonly _documents = new Map(); - public get(viewType: string, resource: vscode.Uri): CustomDocument | undefined { + public get(viewType: string, resource: vscode.Uri): extHostTypes.CustomDocument | undefined { return this._documents.get(this.key(viewType, resource)); } - public add(document: CustomDocument) { + public add(document: extHostTypes.CustomDocument) { const key = this.key(document.viewType, document.uri); if (this._documents.has(key)) { throw new Error(`Document already exists for viewType:${document.viewType} resource:${document.uri}`); @@ -361,7 +260,7 @@ class WebviewDocumentStore { this._documents.set(key, document); } - public delete(document: CustomDocument) { + public delete(document: extHostTypes.CustomDocument) { const key = this.key(document.viewType, document.uri); this._documents.delete(key); } @@ -406,18 +305,18 @@ class EditorProviderStore { throw new Error(`Provider for viewType:${viewType} already registered`); } this._providers.set(viewType, { type, extension, provider } as ProviderEntry); - return new VSCodeDisposable(() => this._providers.delete(viewType)); + return new extHostTypes.Disposable(() => this._providers.delete(viewType)); } } -export class ExtHostWebviews implements ExtHostWebviewsShape { +export class ExtHostWebviews implements extHostProtocol.ExtHostWebviewsShape { - private static newHandle(): WebviewPanelHandle { + private static newHandle(): extHostProtocol.WebviewPanelHandle { return generateUuid(); } - private readonly _proxy: MainThreadWebviewsShape; - private readonly _webviewPanels = new Map(); + private readonly _proxy: extHostProtocol.MainThreadWebviewsShape; + private readonly _webviewPanels = new Map(); private readonly _serializers = new Map { + return new extHostTypes.Disposable(() => { this._serializers.delete(viewType); this._proxy.$unregisterSerializer(viewType); }); @@ -497,21 +396,21 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { if (provider.editingDelegate) { disposables.add(provider.editingDelegate.onDidEdit(e => { const document = e.document; - const editId = (document as CustomDocument)._pushEdit(e.edit); + const editId = (document as extHostTypes.CustomDocument)._addEdit(e.edit); this._proxy.$onDidEdit(document.uri, document.viewType, editId, e.label); })); } } - return VSCodeDisposable.from( + return extHostTypes.Disposable.from( disposables, - new VSCodeDisposable(() => { + new extHostTypes.Disposable(() => { this._proxy.$unregisterEditorProvider(viewType); })); } public $onMessage( - handle: WebviewPanelHandle, + handle: extHostProtocol.WebviewPanelHandle, message: any ): void { const panel = this.getWebviewPanel(handle); @@ -521,13 +420,13 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } public $onMissingCsp( - _handle: WebviewPanelHandle, + _handle: extHostProtocol.WebviewPanelHandle, extensionId: string ): void { this._logService.warn(`${extensionId} created a webview without a content security policy: https://aka.ms/vscode-webview-missing-csp`); } - public $onDidChangeWebviewPanelViewStates(newStates: WebviewPanelViewStateData): void { + public $onDidChangeWebviewPanelViewStates(newStates: extHostProtocol.WebviewPanelViewStateData): void { const handles = Object.keys(newStates); // Notify webviews of state changes in the following order: // - Non-visible @@ -560,7 +459,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } } - async $onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise { + async $onDidDisposeWebviewPanel(handle: extHostProtocol.WebviewPanelHandle): Promise { const panel = this.getWebviewPanel(handle); if (panel) { panel.dispose(); @@ -569,7 +468,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } async $deserializeWebviewPanel( - webviewHandle: WebviewPanelHandle, + webviewHandle: extHostProtocol.WebviewPanelHandle, viewType: string, title: string, state: any, @@ -599,9 +498,8 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } const revivedResource = URI.revive(resource); - const document = CustomDocument.create(viewType, revivedResource, entry.provider.editingDelegate); - await entry.provider.resolveCustomDocument(document, cancellation); - this._documents.add(document); + const document = await entry.provider.openCustomDocument(revivedResource, cancellation); + this._documents.add(document as extHostTypes.CustomDocument); return { editable: !!entry.provider.editingDelegate, }; @@ -620,12 +518,12 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { const revivedResource = URI.revive(resource); const document = this.getCustomDocument(viewType, revivedResource); this._documents.delete(document); - document.dispose(); + document._dispose(); } async $resolveWebviewEditor( resource: UriComponents, - handle: WebviewPanelHandle, + handle: extHostProtocol.WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, @@ -686,50 +584,73 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { await (entry.provider as vscode.CustomTextEditorProvider).moveCustomTextEditor!(document, webview, CancellationToken.None); } - async $undo(resourceComponents: UriComponents, viewType: string, editId: number): Promise { + async $undo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._undo(editId); + document._updateEditState(state); + return delegate.undoEdits(document, [document._getEdit(editId)]); } - async $redo(resourceComponents: UriComponents, viewType: string, editId: number): Promise { + async $redo(resourceComponents: UriComponents, viewType: string, editId: number, state: extHostProtocol.CustomDocumentEditState): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._redo(editId); + document._updateEditState(state); + return delegate.applyEdits(document, [document._getEdit(editId)]); } - async $revert(resourceComponents: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }): Promise { + async $revert(resourceComponents: UriComponents, viewType: string, changes: { undoneEdits: number[], redoneEdits: number[] }, state: extHostProtocol.CustomDocumentEditState): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._revert(changes); + const undoneEdits = changes.undoneEdits.map(id => document._getEdit(id)); + const appliedEdits = changes.redoneEdits.map(id => document._getEdit(id)); + document._updateEditState(state); + return delegate.revert(document, { undoneEdits, appliedEdits }); } async $onSave(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._save(cancellation); + return delegate.save(document, cancellation); } async $onSaveAs(resourceComponents: UriComponents, viewType: string, targetResource: UriComponents): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._saveAs(URI.revive(targetResource)); + return delegate.saveAs(document, URI.revive(targetResource)); } async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise { + const delegate = this.getEditingDelegate(viewType); const document = this.getCustomDocument(viewType, resourceComponents); - return document._backup(cancellation); + return delegate.backup(document, cancellation); } - private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined { + private getWebviewPanel(handle: extHostProtocol.WebviewPanelHandle): ExtHostWebviewEditor | undefined { return this._webviewPanels.get(handle); } - private getCustomDocument(viewType: string, resource: UriComponents): CustomDocument { + private getCustomDocument(viewType: string, resource: UriComponents): extHostTypes.CustomDocument { const document = this._documents.get(viewType, URI.revive(resource)); if (!document) { throw new Error('No webview editor custom document found'); } return document; } + + private getEditingDelegate(viewType: string): vscode.CustomEditorEditingDelegate { + const entry = this._editorProviders.get(viewType); + if (!entry) { + throw new Error(`No provider found for '${viewType}'`); + } + const delegate = (entry.provider as vscode.CustomEditorProvider).editingDelegate; + if (!delegate) { + throw new Error(`Provider for ${viewType}' does not support editing`); + } + return delegate; + } } -function toExtensionData(extension: IExtensionDescription): WebviewExtensionDescription { +function toExtensionData(extension: IExtensionDescription): extHostProtocol.WebviewExtensionDescription { return { id: extension.identifier, location: extension.extensionLocation }; } diff --git a/src/vs/workbench/browser/actions/developerActions.ts b/src/vs/workbench/browser/actions/developerActions.ts index 6469fe2dbc2..3e66fae8bf1 100644 --- a/src/vs/workbench/browser/actions/developerActions.ts +++ b/src/vs/workbench/browser/actions/developerActions.ts @@ -41,7 +41,7 @@ class InspectContextKeysAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { const disposables = new DisposableStore(); const stylesheet = createStyleSheet(); @@ -85,8 +85,6 @@ class InspectContextKeysAction extends Action { dispose(disposables); }, null, disposables); - - return Promise.resolve(); } } diff --git a/src/vs/workbench/browser/actions/helpActions.ts b/src/vs/workbench/browser/actions/helpActions.ts index 2ecc5026fc8..283d00258ea 100644 --- a/src/vs/workbench/browser/actions/helpActions.ts +++ b/src/vs/workbench/browser/actions/helpActions.ts @@ -31,13 +31,11 @@ class KeybindingsReferenceAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { const url = isLinux ? this.productService.keyboardShortcutsUrlLinux : isMacintosh ? this.productService.keyboardShortcutsUrlMac : this.productService.keyboardShortcutsUrlWin; if (url) { this.openerService.open(URI.parse(url)); } - - return Promise.resolve(); } } @@ -56,12 +54,10 @@ class OpenDocumentationUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.documentationUrl) { this.openerService.open(URI.parse(this.productService.documentationUrl)); } - - return Promise.resolve(); } } @@ -80,12 +76,10 @@ class OpenIntroductoryVideosUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.introductoryVideosUrl) { this.openerService.open(URI.parse(this.productService.introductoryVideosUrl)); } - - return Promise.resolve(); } } @@ -104,12 +98,10 @@ class OpenTipsAndTricksUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.tipsAndTricksUrl) { this.openerService.open(URI.parse(this.productService.tipsAndTricksUrl)); } - - return Promise.resolve(); } } @@ -151,12 +143,10 @@ class OpenTwitterUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.twitterUrl) { this.openerService.open(URI.parse(this.productService.twitterUrl)); } - - return Promise.resolve(); } } @@ -175,12 +165,10 @@ class OpenRequestFeatureUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.requestFeatureUrl) { this.openerService.open(URI.parse(this.productService.requestFeatureUrl)); } - - return Promise.resolve(); } } @@ -199,7 +187,7 @@ class OpenLicenseUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.licenseUrl) { if (language) { const queryArgChar = this.productService.licenseUrl.indexOf('?') > 0 ? '&' : '?'; @@ -208,8 +196,6 @@ class OpenLicenseUrlAction extends Action { this.openerService.open(URI.parse(this.productService.licenseUrl)); } } - - return Promise.resolve(); } } @@ -228,7 +214,7 @@ class OpenPrivacyStatementUrlAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.productService.privacyStatementUrl) { if (language) { const queryArgChar = this.productService.privacyStatementUrl.indexOf('?') > 0 ? '&' : '?'; @@ -237,8 +223,6 @@ class OpenPrivacyStatementUrlAction extends Action { this.openerService.open(URI.parse(this.productService.privacyStatementUrl)); } } - - return Promise.resolve(); } } diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 3f1403df47d..c7a4b51b9f8 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -645,9 +645,8 @@ export class IncreaseViewSizeAction extends BaseResizeViewAction { super(id, label, layoutService); } - run(): Promise { + async run(): Promise { this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT); - return Promise.resolve(true); } } @@ -665,9 +664,8 @@ export class DecreaseViewSizeAction extends BaseResizeViewAction { super(id, label, layoutService); } - run(): Promise { + async run(): Promise { this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT); - return Promise.resolve(true); } } diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index 725374a03c4..f63d927d18e 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -36,7 +36,7 @@ export const inRecentFilesPickerContextKey = 'inRecentFilesPicker'; abstract class BaseOpenRecentAction extends Action { - private removeFromRecentlyOpened: IQuickInputButton = { + private readonly removeFromRecentlyOpened: IQuickInputButton = { iconClass: 'codicon-close', tooltip: nls.localize('remove', "Remove from Recently Opened") }; @@ -124,7 +124,7 @@ abstract class BaseOpenRecentAction extends Action { const pick = await this.quickInputService.pick(picks, { contextKey: inRecentFilesPickerContextKey, activeItem: [...workspacePicks, ...filePicks][autoFocusSecondEntry ? 1 : 0], - placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to open in new window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to open in new window)"), + placeHolder: isMacintosh ? nls.localize('openRecentPlaceHolderMac', "Select to open (hold Cmd-key to force new window or Alt-key for same window)") : nls.localize('openRecentPlaceHolder', "Select to open (hold Ctrl-key to force new window or Alt-key for same window)"), matchOnDescription: true, onKeyMods: mods => keyMods = mods, quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined, @@ -135,7 +135,7 @@ abstract class BaseOpenRecentAction extends Action { }); if (pick) { - return this.hostService.openWindow([pick.openable], { forceNewWindow: keyMods?.ctrlCmd }); + return this.hostService.openWindow([pick.openable], { forceNewWindow: keyMods?.ctrlCmd, forceReuseWindow: keyMods?.alt }); } } } diff --git a/src/vs/workbench/browser/actions/workspaceActions.ts b/src/vs/workbench/browser/actions/workspaceActions.ts index 6607abc7716..1b2d9636354 100644 --- a/src/vs/workbench/browser/actions/workspaceActions.ts +++ b/src/vs/workbench/browser/actions/workspaceActions.ts @@ -112,11 +112,10 @@ export class CloseWorkspaceAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close.")); - - return Promise.resolve(undefined); + return; } return this.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: this.environmentService.configuration.remoteAuthority }); diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 4119fac3bb2..e3b036b02f3 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -645,15 +645,19 @@ export class CompositeDragAndDropObserver extends Disposable { } return this._register(disposableStore); } - registerDraggable(element: HTMLElement, type: ViewType, id: string, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable { + + registerDraggable(element: HTMLElement, draggedItemProvider: () => { type: ViewType, id: string }, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable { element.draggable = true; const disposableStore = new DisposableStore(); disposableStore.add(addDisposableListener(element, EventType.DRAG_START, e => { + const { id, type } = draggedItemProvider(); this.writeDragData(id, type); this._onDragStart.fire({ eventData: e, dragAndDropData: this.readDragData(type)! }); })); disposableStore.add(new DragAndDropObserver(element, { onDragEnd: e => { + const { id, type } = draggedItemProvider(); + const data = this.readDragData(type); if (data && data.getData().id === id) { this.transferData.clearData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype); @@ -666,6 +670,7 @@ export class CompositeDragAndDropObserver extends Disposable { this._onDragEnd.fire({ eventData: e, dragAndDropData: data! }); }, onDragEnter: e => { + if (callbacks.onDragEnter) { const data = this.readDragData('composite') || this.readDragData('view'); if (!data) { diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 2f4829e9b51..426e1929d30 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -364,8 +364,8 @@ class ResourceLabelWidget extends IconLabel { } setResource(label: IResourceLabelProps, options: IResourceLabelOptions = Object.create(null)): void { - const resource = toResource(this.label); - const isMasterDetail = this.label?.resource && !URI.isUri(this.label.resource); + const resource = toResource(label); + const isMasterDetail = label?.resource && !URI.isUri(label.resource); if (!isMasterDetail && resource?.scheme === Schemas.untitled) { // Untitled labels are very dynamic because they may change diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 3fa67173cc3..43f89e056d8 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -424,11 +424,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi if (!this.state.fullscreen && !this.state.maximized && (activeBorder || inactiveBorder)) { windowBorder = true; - // If one color is missing, just fallback to the other one - const borderColor = this.state.hasFocus - ? activeBorder ?? inactiveBorder - : inactiveBorder ?? activeBorder; - this.container.style.setProperty('--window-border-color', borderColor ? borderColor.toString() : 'transparent'); + // If the inactive color is missing, fallback to the active one + const borderColor = this.state.hasFocus ? activeBorder : inactiveBorder ?? activeBorder; + this.container.style.setProperty('--window-border-color', borderColor?.toString() ?? 'transparent'); } if (windowBorder === this.state.windowBorder) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index 9762e6df864..ffc31afca7e 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -134,6 +134,61 @@ export class ToggleViewletAction extends Action { } } +export class AccountsActionViewItem extends ActivityActionViewItem { + constructor( + action: ActivityAction, + colors: (theme: IColorTheme) => ICompositeBarColors, + @IThemeService themeService: IThemeService, + @IContextMenuService protected contextMenuService: IContextMenuService, + @IMenuService protected menuService: IMenuService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + ) { + super(action, { draggable: false, colors, icon: true }, themeService); + } + + render(container: HTMLElement): void { + super.render(container); + + // Context menus are triggered on mouse down so that an item can be picked + // and executed with releasing the mouse over it + + this._register(DOM.addDisposableListener(this.container, DOM.EventType.MOUSE_DOWN, (e: MouseEvent) => { + DOM.EventHelper.stop(e, true); + this.showContextMenu(); + })); + + this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_UP, (e: KeyboardEvent) => { + let event = new StandardKeyboardEvent(e); + if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { + DOM.EventHelper.stop(e, true); + this.showContextMenu(); + } + })); + + this._register(DOM.addDisposableListener(this.container, TouchEventType.Tap, (e: GestureEvent) => { + DOM.EventHelper.stop(e, true); + this.showContextMenu(); + })); + } + + private showContextMenu(): void { + const accountsActions: IAction[] = []; + const accountsMenu = this.menuService.createMenu(MenuId.AccountsContext, this.contextKeyService); + const actionsDisposable = createAndFillInActionBarActions(accountsMenu, undefined, { primary: [], secondary: accountsActions }); + + const containerPosition = DOM.getDomNodePagePosition(this.container); + const location = { x: containerPosition.left + containerPosition.width / 2, y: containerPosition.top }; + this.contextMenuService.showContextMenu({ + getAnchor: () => location, + getActions: () => accountsActions, + onHide: () => { + accountsMenu.dispose(); + dispose(actionsDisposable); + } + }); + } +} + export class GlobalActivityActionViewItem extends ActivityActionViewItem { constructor( @@ -231,7 +286,7 @@ class SwitchSideBarViewAction extends Action { const activeViewlet = this.viewletService.getActiveViewlet(); if (!activeViewlet) { - return Promise.resolve(); + return; } let targetViewletId: string | undefined; for (let i = 0; i < pinnedViewletIds.length; i++) { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index bdea370e482..6077c659b04 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -9,7 +9,7 @@ import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/acti import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity'; import { Registry } from 'vs/platform/registry/common/platform'; import { Part } from 'vs/workbench/browser/part'; -import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; +import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction, AccountsActionViewItem } from 'vs/workbench/browser/parts/activitybar/activitybarActions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity'; import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService'; @@ -354,7 +354,17 @@ export class ActivitybarPart extends Part implements IActivityBarService { private createGlobalActivityActionBar(container: HTMLElement): void { this.globalActivityActionBar = this._register(new ActionBar(container, { - actionViewItemProvider: action => this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)), + actionViewItemProvider: action => { + if (action.id === 'workbench.actions.manage') { + return this.instantiationService.createInstance(GlobalActivityActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); + } + + if (action.id === 'workbench.actions.accounts') { + return this.instantiationService.createInstance(AccountsActionViewItem, action as ActivityAction, (theme: IColorTheme) => this.getActivitybarItemColors(theme)); + } + + throw new Error(`No view item for action '${action.id}'`); + }, orientation: ActionsOrientation.VERTICAL, ariaLabel: nls.localize('manage', "Manage"), animated: false @@ -366,6 +376,13 @@ export class ActivitybarPart extends Part implements IActivityBarService { cssClass: 'codicon-settings-gear' }); + const profileAction = new ActivityAction({ + id: 'workbench.actions.accounts', + name: nls.localize('accounts', "Accounts"), + cssClass: 'codicon-account' + }); + + this.globalActivityActionBar.push(profileAction); this.globalActivityActionBar.push(this.globalActivityAction); } diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css index cfce06de02b..4859ec83fed 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css @@ -9,8 +9,8 @@ margin-bottom: 4px; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before, -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after { +.monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::before, +.monaco-workbench .activitybar > .content .composite-bar > .monaco-action-bar .action-item::after { position: absolute; content: ''; width: 48px; @@ -23,25 +23,32 @@ transition-delay: 100ms; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::before { +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::before { margin-top: -3px; margin-bottom: 1px; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item::after { +/* Override top element since it would be cut off */ +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item:first-of-type::before { + margin-top: 0px; + margin-bottom: 0px; +} + +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item::after { margin-top: 1px; margin-bottom: -3px; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before, -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::after, -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::before, -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after { +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::before, +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::after, +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::before, +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::after { transition-delay: 0s; } -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.top::before, -.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.bottom::after { +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.top::before, +.monaco-workbench .activitybar > .content > .composite-bar > .monaco-action-bar .action-item.bottom::after, +.monaco-workbench .activitybar > .content.dragged-over > .composite-bar > .monaco-action-bar .action-item:last-of-type::after { opacity: 1; } diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index badf730c7cd..07f58c1f5bf 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -12,12 +12,12 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions'; -import { Dimension, $, addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom'; +import { Dimension, $, addDisposableListener, EventType, EventHelper, toggleClass, isAncestor } from 'vs/base/browser/dom'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Widget } from 'vs/base/browser/ui/widget'; import { isUndefinedOrNull } from 'vs/base/common/types'; -import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { Emitter } from 'vs/base/common/event'; import { Registry } from 'vs/platform/registry/common/platform'; import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views'; @@ -187,7 +187,6 @@ export class CompositeBar extends Widget implements ICompositeBar { constructor( items: ICompositeBarItem[], private options: ICompositeBarOptions, - @IThemeService private readonly themeService: IThemeService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextMenuService private readonly contextMenuService: IContextMenuService ) { @@ -215,8 +214,6 @@ export class CompositeBar extends Widget implements ICompositeBar { create(parent: HTMLElement): HTMLElement { const actionBarDiv = parent.appendChild($('.composite-bar')); - const excessDiv = parent.appendChild($('.composite-bar-excess')); - this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, { actionViewItemProvider: (action: IAction) => { if (action instanceof CompositeOverflowActivityAction) { @@ -242,23 +239,26 @@ export class CompositeBar extends Widget implements ICompositeBar { this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e))); // Register a drop target on the whole bar to prevent forbidden feedback - this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, {})); + this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(parent, { + onDragOver: (e: IDraggedCompositeData) => { + // don't add feedback if this is over the composite bar actions + if (e.eventData.target && isAncestor(e.eventData.target as HTMLElement, actionBarDiv)) { + toggleClass(parent, 'dragged-over', false); + return; + } - // Allow to drop at the end to move composites to the end - this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(excessDiv, { - onDragEnter: (e: IDraggedCompositeData) => { const pinnedItems = this.getPinnedComposites(); - const validDropTarget = this.options.dndHandler.onDragEnter(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData); - this.updateFromDragging(excessDiv, validDropTarget); + const validDropTarget = this.options.dndHandler.onDragOver(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData); + toggleClass(parent, 'dragged-over', validDropTarget); }, onDragLeave: (e: IDraggedCompositeData) => { - this.updateFromDragging(excessDiv, false); + toggleClass(parent, 'dragged-over', false); }, onDrop: (e: IDraggedCompositeData) => { const pinnedItems = this.getPinnedComposites(); this.options.dndHandler.drop(e.dragAndDropData, pinnedItems[pinnedItems.length - 1].id, e.eventData, false); - this.updateFromDragging(excessDiv, false); + toggleClass(parent, 'dragged-over', false); } })); @@ -364,13 +364,6 @@ export class CompositeBar extends Widget implements ICompositeBar { } } - private updateFromDragging(element: HTMLElement, isDragging: boolean): void { - const theme = this.themeService.getColorTheme(); - const dragBackground = this.options.colors(theme).dragAndDropBackground; - - element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : ''; - } - private resetActiveComposite(compositeId: string) { const defaultCompositeId = this.options.getDefaultCompositeId(); diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 53c6766a71a..2175d4d636f 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -518,7 +518,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { let insertDropBefore: boolean | undefined = undefined; // Allow to drag - this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, 'composite', this.activity.id, { + this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.container, () => { return { type: 'composite', id: this.activity.id }; }, { onDragOver: e => { const isValidMove = e.dragAndDropData.getData().id !== this.activity.id && this.dndHandler.onDragOver(e.dragAndDropData, this.activity.id, e.eventData); insertDropBefore = this.updateFromDragging(container, isValidMove, e.eventData); @@ -533,6 +533,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { }, onDrop: e => { + dom.EventHelper.stop(e.eventData, true); this.dndHandler.drop(e.dragAndDropData, this.activity.id, e.eventData, !!insertDropBefore); insertDropBefore = this.updateFromDragging(container, false, e.eventData); }, @@ -554,9 +555,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { // Activate on drag over to reveal targets [this.badge, this.label].forEach(b => this._register(new DelayedDragHandler(b, () => { - if (!(this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) || - this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) && - !this.getAction().checked) { + if (!this.getAction().checked) { this.getAction().run(); } }))); diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index bc2a05ab0cf..acc13a95897 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -36,7 +36,9 @@ import { SplitEditorUpAction, SplitEditorDownAction, MoveEditorToLeftGroupAction, MoveEditorToRightGroupAction, MoveEditorToAboveGroupAction, MoveEditorToBelowGroupAction, CloseAllEditorGroupsAction, JoinAllGroupsAction, FocusLeftGroup, FocusAboveGroup, FocusRightGroup, FocusBelowGroup, EditorLayoutSingleAction, EditorLayoutTwoColumnsAction, EditorLayoutThreeColumnsAction, EditorLayoutTwoByTwoGridAction, EditorLayoutTwoRowsAction, EditorLayoutThreeRowsAction, EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoRowsRightAction, NewEditorGroupLeftAction, NewEditorGroupRightAction, - NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction, QuickOpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickOpenNextRecentlyUsedEditorAction as QuickOpenLeastRecentlyUsedEditorAction, QuickOpenLeastRecentlyUsedEditorInGroupAction + NewEditorGroupAboveAction, NewEditorGroupBelowAction, SplitEditorOrthogonalAction, CloseEditorInAllGroupsAction, NavigateToLastEditLocationAction, ToggleGroupSizesAction, ShowAllEditorsByMostRecentlyUsedAction, + QuickOpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction, QuickOpenNextRecentlyUsedEditorAction as QuickOpenLeastRecentlyUsedEditorAction, + QuickOpenLeastRecentlyUsedEditorInGroupAction } from 'vs/workbench/browser/parts/editor/editorActions'; import * as editorCommands from 'vs/workbench/browser/parts/editor/editorCommands'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 26859c4ce0f..1de80271f82 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -24,6 +24,7 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { values } from 'vs/base/common/map'; +import { ItemActivation } from 'vs/platform/quickinput/common/quickInput'; export class ExecuteCommandAction extends Action { @@ -1261,6 +1262,7 @@ export class BaseQuickOpenEditorAction extends Action { id: string, label: string, private prefix: string, + private itemActivation: ItemActivation | undefined, @IQuickOpenService private readonly quickOpenService: IQuickOpenService, @IKeybindingService private readonly keybindingService: IKeybindingService ) { @@ -1270,7 +1272,10 @@ export class BaseQuickOpenEditorAction extends Action { async run(): Promise { const keybindings = this.keybindingService.lookupKeybindings(this.id); - this.quickOpenService.show(this.prefix, { quickNavigateConfiguration: { keybindings } }); + this.quickOpenService.show(this.prefix, { + quickNavigateConfiguration: { keybindings }, + autoFocus: this.itemActivation === ItemActivation.LAST ? { autoFocusLastEntry: true } : undefined + }); } } @@ -1285,7 +1290,7 @@ export class QuickOpenPreviousRecentlyUsedEditorAction extends BaseQuickOpenEdit @IQuickOpenService quickOpenService: IQuickOpenService, @IKeybindingService keybindingService: IKeybindingService ) { - super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService); + super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService); } } @@ -1300,7 +1305,7 @@ export class QuickOpenNextRecentlyUsedEditorAction extends BaseQuickOpenEditorAc @IQuickOpenService quickOpenService: IQuickOpenService, @IKeybindingService keybindingService: IKeybindingService ) { - super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService); + super(id, label, NAVIGATE_ALL_EDITORS_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService); } } @@ -1315,7 +1320,7 @@ export class QuickOpenPreviousRecentlyUsedEditorInGroupAction extends BaseQuickO @IQuickOpenService quickOpenService: IQuickOpenService, @IKeybindingService keybindingService: IKeybindingService ) { - super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService); + super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, undefined, quickOpenService, keybindingService); } } @@ -1330,7 +1335,7 @@ export class QuickOpenLeastRecentlyUsedEditorInGroupAction extends BaseQuickOpen @IQuickOpenService quickOpenService: IQuickOpenService, @IKeybindingService keybindingService: IKeybindingService ) { - super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, quickOpenService, keybindingService); + super(id, label, NAVIGATE_IN_ACTIVE_GROUP_BY_MOST_RECENTLY_USED_PREFIX, ItemActivation.LAST, quickOpenService, keybindingService); } } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 1c64617fd75..04465bd1528 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -292,11 +292,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { localize('closeGroupAction', "Close"), 'codicon-close', true, - () => { - this.accessor.removeGroup(this); - - return Promise.resolve(true); - })); + async () => this.accessor.removeGroup(this))); const keybinding = this.keybindingService.lookupKeybinding(removeGroupAction.id); containerToolbar.push(removeGroupAction, { icon: true, label: false, keybinding: keybinding ? keybinding.getLabel() : undefined }); @@ -807,7 +803,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Guard against invalid inputs if (!editor) { - return Promise.resolve(null); + return null; } // Editor opening event allows for prevention @@ -822,13 +818,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return withUndefinedAsNull(await this.doOpenEditor(editor, options)); } - private doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise { + private async doOpenEditor(editor: EditorInput, options?: EditorOptions): Promise { // Guard against invalid inputs. Disposed inputs // should never open because they emit no events // e.g. to indicate dirty changes. if (editor.isDisposed()) { - return Promise.resolve(undefined); + return; } // Determine options diff --git a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts index 7d30370b0d3..1b9413cc803 100644 --- a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts +++ b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/editorquickaccess'; import { localize } from 'vs/nls'; -import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickPickSeparator, quickPickItemScorerAccessor, IQuickPickItemWithResource, IQuickPick } from 'vs/platform/quickinput/common/quickInput'; import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/browser/pickerQuickAccess'; import { IEditorGroupsService, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorsOrder, IEditorIdentifier, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; @@ -13,12 +13,31 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; -import { prepareQuery, scoreItem, compareItemsByScore } from 'vs/base/common/fuzzyScorer'; +import { prepareQuery, scoreItem, compareItemsByScore, ScorerCache } from 'vs/base/common/fuzzyScorer'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { IDisposable } from 'vs/base/common/lifecycle'; interface IEditorQuickPickItem extends IQuickPickItemWithResource, IEditorIdentifier, IPickerQuickAccessItem { } export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessProvider { + private readonly pickState = new class { + + scorerCache: ScorerCache = Object.create(null); + isQuickNavigating: boolean | undefined = undefined; + + reset(isQuickNavigating: boolean): void { + + // Caches + if (!isQuickNavigating) { + this.scorerCache = Object.create(null); + } + + // Other + this.isQuickNavigating = isQuickNavigating; + } + }; + constructor( prefix: string, @IEditorGroupsService protected readonly editorGroupService: IEditorGroupsService, @@ -29,9 +48,17 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro super(prefix, { canAcceptInBackground: true }); } + provide(picker: IQuickPick, token: CancellationToken): IDisposable { + + // Reset the pick state for this run + this.pickState.reset(!!picker.quickNavigate); + + // Start picker + return super.provide(picker, token); + } + protected getPicks(filter: string): Array { const query = prepareQuery(filter); - const scorerCache = Object.create(null); // Filtering const filteredEditorEntries = this.doGetEditorPickItems().filter(entry => { @@ -40,7 +67,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro } // Score on label and description - const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, scorerCache); + const itemScore = scoreItem(entry, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); if (!itemScore.score) { return false; } @@ -59,7 +86,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro return groups.indexOf(entryA.groupId) - groups.indexOf(entryB.groupId); // older groups first } - return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, scorerCache); + return compareItemsByScore(entryA, entryB, query, true, quickPickItemScorerAccessor, this.pickState.scorerCache); }); } @@ -99,17 +126,30 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro description: editor.getDescription(), iconClasses: getIconClasses(this.modelService, this.modeService, resource), italic: !this.editorGroupService.getGroup(groupId)?.isPinned(editor), - buttons: [ - { - iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close', - tooltip: localize('closeEditor', "Close Editor"), - alwaysVisible: isDirty + buttons: (() => { + if (this.pickState.isQuickNavigating) { + return undefined; // no actions when quick navigating } - ], - trigger: async () => { - await this.editorGroupService.getGroup(groupId)?.closeEditor(editor, { preserveFocus: true }); - return TriggerAction.REFRESH_PICKER; + return [ + { + iconClass: isDirty ? 'dirty-editor codicon-circle-filled' : 'codicon-close', + tooltip: localize('closeEditor', "Close Editor"), + alwaysVisible: isDirty + } + ]; + })(), + trigger: async () => { + const group = this.editorGroupService.getGroup(groupId); + if (group) { + await group.closeEditor(editor, { preserveFocus: true }); + + if (!group.isOpened(editor)) { + return TriggerAction.REMOVE_ITEM; + } + } + + return TriggerAction.NO_ACTION; }, accept: (keyMods, event) => this.editorGroupService.getGroup(groupId)?.openEditor(editor, { preserveFocus: event.inBackground }), }; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 465d12b5cd4..20d731177d4 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -454,7 +454,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { const props: IStatusbarEntry = { text, - tooltip: nls.localize('gotoLine', "Go to Line"), + tooltip: nls.localize('gotoLine', "Go to Line/Column"), command: 'workbench.action.gotoLine' }; diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 3af508ded81..7e9d6d145bb 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -110,7 +110,7 @@ export class NoTabsTitleControl extends TitleControl { } } } else { - // @rebornix + // TODO@rebornix // gesture tap should open the quick open // editorGroupView will focus on the editor again when there are mouse/pointer/touch down events // we need to wait a bit as `GesureEvent.Tap` is generated from `touchstart` and then `touchend` evnets, which are not an atom event. diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index c85a70573e1..cf6fbb05c7e 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -202,13 +202,13 @@ export class TabsTitleControl extends TitleControl { EventHelper.stop(e); - this.group.openEditor(this.editorService.createEditorInput({ - forceUntitled: true, - options: { + this.group.openEditor( + this.editorService.createEditorInput({ forceUntitled: true }), + { pinned: true, // untitled is always pinned index: this.group.count // always at the end } - })); + ); })); }); diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index ecb204fdfac..16f9a7e71ac 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -107,6 +107,11 @@ margin-left: 9px; } +.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item:last-of-type::after { + margin-right: -10px; + margin-left: 8px; +} + .monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::before, .monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::after, .monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before, @@ -115,7 +120,8 @@ } .monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.left::before, -.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after { +.monaco-workbench .part.panel > .composite.title> .panel-switcher-container > .monaco-action-bar .action-item.right::after, +.monaco-workbench .part.panel > .composite.title.dragged-over > .panel-switcher-container > .monaco-action-bar .action-item:last-of-type::after { opacity: 1; } diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenActions.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenActions.ts index 3187a683ec4..c7ce7382422 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenActions.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenActions.ts @@ -39,6 +39,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'workbench.action.alternativeAcceptSelectedQuickOpenItem', + weight: KeybindingWeight.WorkbenchContrib, + when: inQuickOpenContext, + primary: 0, + handler: accessor => { + const quickInputService = accessor.get(IQuickInputService); + return quickInputService.accept({ ctrlCmd: true, alt: false }); + } +}); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'workbench.action.focusQuickOpen', weight: KeybindingWeight.WorkbenchContrib, diff --git a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts index 5db013a2e95..35c64a5331d 100644 --- a/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts +++ b/src/vs/workbench/browser/parts/quickopen/quickOpenController.ts @@ -47,7 +47,7 @@ import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ILabelService } from 'vs/platform/label/common/label'; import { timeout } from 'vs/base/common/async'; -import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { IQuickInputService, IQuickPickItem, ItemActivation } from 'vs/platform/quickinput/common/quickInput'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -179,7 +179,20 @@ export class QuickOpenController extends Component implements IQuickOpenService show(prefix?: string, options?: IShowOptions): Promise { if (this.useNewExperimentalVersion) { - this.quickInputService.quickAccess.show(prefix, options); + this.quickInputService.quickAccess.show(prefix, { + quickNavigateConfiguration: options?.quickNavigateConfiguration, + itemActivation: (() => { + if (options?.autoFocus?.autoFocusSecondEntry) { + return ItemActivation.SECOND; + } + + if (options?.autoFocus?.autoFocusLastEntry) { + return ItemActivation.LAST; + } + + return undefined; + })() + }); return Promise.resolve(); } @@ -724,7 +737,7 @@ class EditorHistoryHandler { // Sort by score and provide a fallback sorter that keeps the // recency of items in case the score for items is the same - .sort((e1, e2) => compareItemsByScore(e1, e2, query, false, accessor, this.scorerCache, () => -1)); + .sort((e1, e2) => compareItemsByScore(e1, e2, query, false, accessor, this.scorerCache)); } } diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts index e2777c725e1..8855d9e94d6 100644 --- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts +++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts @@ -33,7 +33,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { LayoutPriority } from 'vs/base/browser/ui/grid/grid'; import { assertIsDefined } from 'vs/base/common/types'; -import { LocalSelectionTransfer, DraggedViewIdentifier, DraggedCompositeIdentifier } from 'vs/workbench/browser/dnd'; +import { CompositeDragAndDropObserver } from 'vs/workbench/browser/dnd'; export class SidebarPart extends CompositePart implements IViewletService { @@ -165,28 +165,18 @@ export class SidebarPart extends CompositePart implements IViewletServi })); this.titleLabelElement!.draggable = true; - this._register(addDisposableListener(this.titleLabelElement!, EventType.DRAG_START, e => { - const activeViewlet = this.getActiveViewlet(); - if (activeViewlet) { - const visibleViews = activeViewlet.getViewPaneContainer().views.filter(v => v.isVisible()); - if (visibleViews.length === 1) { - LocalSelectionTransfer.getInstance().setData([new DraggedViewIdentifier(visibleViews[0].id)], DraggedViewIdentifier.prototype); - } else { - LocalSelectionTransfer.getInstance().setData([new DraggedCompositeIdentifier(activeViewlet.getId())], DraggedCompositeIdentifier.prototype); - } - } - })); - this._register(addDisposableListener(this.titleLabelElement!, EventType.DRAG_END, e => { - if (LocalSelectionTransfer.getInstance().hasData(DraggedViewIdentifier.prototype)) { - LocalSelectionTransfer.getInstance().clearData(DraggedViewIdentifier.prototype); + const draggedItemProvider = (): { type: 'view' | 'composite', id: string } => { + const activeViewlet = this.getActiveViewlet()!; + const visibleViews = activeViewlet.getViewPaneContainer().views.filter(v => v.isVisible()); + if (visibleViews.length === 1) { + return { type: 'view', id: visibleViews[0].id }; + } else { + return { type: 'composite', id: activeViewlet.getId() }; } + }; - if (LocalSelectionTransfer.getInstance().hasData(DraggedCompositeIdentifier.prototype)) { - LocalSelectionTransfer.getInstance().clearData(DraggedCompositeIdentifier.prototype); - } - })); - + this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(this.titleLabelElement!, draggedItemProvider, {})); return titleArea; } diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index 1624e9274c9..091340300e6 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -609,7 +609,6 @@ export class TreeView extends Disposable implements ITreeView { return tree.expand(element, false); })); } - return Promise.resolve(undefined); } setSelection(items: ITreeItem[]): void { @@ -625,11 +624,10 @@ export class TreeView extends Disposable implements ITreeView { } } - reveal(item: ITreeItem): Promise { + async reveal(item: ITreeItem): Promise { if (this.tree) { - return Promise.resolve(this.tree.reveal(item)); + return this.tree.reveal(item); } - return Promise.resolve(); } private refreshing: boolean = false; @@ -689,11 +687,11 @@ class TreeDataSource implements IAsyncDataSource { return !!this.treeView.dataProvider && (element.collapsibleState !== TreeItemCollapsibleState.None); } - getChildren(element: ITreeItem): ITreeItem[] | Promise { + async getChildren(element: ITreeItem): Promise { if (this.treeView.dataProvider) { return this.withProgress(this.treeView.dataProvider.getChildren(element)); } - return Promise.resolve([]); + return []; } } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 24591c76064..ac179e3e6a0 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -23,7 +23,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; import { PaneView, IPaneViewOptions, IPaneOptions, Pane } from 'vs/base/browser/ui/splitview/paneview'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { Extensions as ViewContainerExtensions, IView, FocusedViewContext, IViewContainersRegistry, IViewDescriptor, ViewContainer, IViewDescriptorService, ViewContainerLocation, IViewPaneContainer, IViewsRegistry, IViewContentDescriptor } from 'vs/workbench/common/views'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -209,8 +209,6 @@ export abstract class ViewPane extends Pane implements IView { this.title = options.title; this.showActionsAlways = !!options.showActionsAlways; this.focusedViewContextKey = FocusedViewContext.bindTo(contextKeyService); - this._preventCollapse = this.viewDescriptorService.getViewLocation(this.id) === ViewContainerLocation.Panel; - this._expanded = this._preventCollapse || this._expanded; this.menuActions = this._register(instantiationService.createInstance(ViewMenuActions, this.id, options.titleMenuId || MenuId.ViewTitle, MenuId.ViewTitleContext)); this._register(this.menuActions.onDidChangeTitle(() => this.updateActions())); @@ -275,9 +273,7 @@ export abstract class ViewPane extends Pane implements IView { protected renderHeader(container: HTMLElement): void { this.headerContainer = container; - if (!this._preventCollapse) { - this.renderTwisties(container); - } + this.renderTwisties(container); this.renderHeaderTitle(container, this.title); @@ -788,7 +784,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { create(parent: HTMLElement): void { const options = this.options as IPaneViewOptions; - options.orientation = this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Panel ? Orientation.HORIZONTAL : Orientation.VERTICAL; + options.orientation = this.orientation; this.paneview = this._register(new PaneView(parent, this.options)); this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane))); this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e)))); @@ -919,8 +915,20 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } } + private get orientation(): Orientation { + if (this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Sidebar) { + return Orientation.VERTICAL; + } else { + return this.layoutService.getPanelPosition() === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL; + } + } + layout(dimension: Dimension): void { if (this.paneview) { + if (this.paneview.orientation !== this.orientation) { + this.paneview.flipOrientation(dimension.height, dimension.width); + } + this.paneview.layout(dimension.height, dimension.width); } @@ -1142,7 +1150,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { let overlay: ViewPaneDropOverlay | undefined; - this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, 'view', pane.id, {})); + this._register(CompositeDragAndDropObserver.INSTANCE.registerDraggable(pane.draggableElement, () => { return { type: 'view', id: pane.id }; }, {})); this._register(CompositeDragAndDropObserver.INSTANCE.registerTarget(pane.dropTargetElement, { onDragEnter: (e) => { diff --git a/src/vs/workbench/browser/quickopen.ts b/src/vs/workbench/browser/quickopen.ts index 73553e42cce..c742ddb89a2 100644 --- a/src/vs/workbench/browser/quickopen.ts +++ b/src/vs/workbench/browser/quickopen.ts @@ -32,6 +32,7 @@ export interface IWorkbenchQuickOpenConfiguration { }, quickOpen: { enableExperimentalNewVersion: boolean; + preserveInput: boolean; } }; } @@ -325,19 +326,14 @@ export class QuickOpenAction extends Action { id: string, label: string, prefix: string, - @IQuickOpenService private readonly quickOpenService: IQuickOpenService + @IQuickOpenService protected readonly quickOpenService: IQuickOpenService ) { super(id, label); this.prefix = prefix; - this.enabled = !!this.quickOpenService; } - run(): Promise { - - // Show with prefix + async run(): Promise { this.quickOpenService.show(this.prefix); - - return Promise.resolve(undefined); } } diff --git a/src/vs/workbench/browser/viewlet.ts b/src/vs/workbench/browser/viewlet.ts index 096974a38ae..896fda4970a 100644 --- a/src/vs/workbench/browser/viewlet.ts +++ b/src/vs/workbench/browser/viewlet.ts @@ -194,10 +194,6 @@ export class ShowViewletAction extends Action { export class CollapseAction extends Action { constructor(tree: AsyncDataTree | AbstractTree, enabled: boolean, clazz?: string) { - super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, () => { - tree.collapseAll(); - - return Promise.resolve(undefined); - }); + super('workbench.action.collapse', nls.localize('collapse', "Collapse All"), clazz, enabled, async () => tree.collapseAll()); } } diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index 055cb1f93eb..e9070ab9bd3 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -182,7 +182,7 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio 'workbench.quickOpen.enableExperimentalNewVersion': { 'type': 'boolean', 'description': nls.localize('workbench.quickOpen.enableExperimentalNewVersion', "Will use the new quick open implementation for testing purposes."), - 'default': false + 'default': true }, 'workbench.settings.openDefaultSettings': { 'type': 'boolean', diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 854a32e9e3c..b2e0bcab1f3 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -168,6 +168,10 @@ export interface IFileEditorInputFactory { isFileEditorInput(obj: unknown): obj is IFileEditorInput; } +interface ICustomEditorInputFactory { + createCustomEditorInput(resource: URI, instantiationService: IInstantiationService): Promise; +} + export interface IEditorInputFactoryRegistry { /** @@ -180,6 +184,16 @@ export interface IEditorInputFactoryRegistry { */ getFileEditorInputFactory(): IFileEditorInputFactory; + /** + * Registers the custom editor input factory to use for custom inputs. + */ + registerCustomEditorInputFactory(factory: ICustomEditorInputFactory): void; + + /** + * Returns the custom editor input factory to use for custom inputs. + */ + getCustomEditorInputFactory(): ICustomEditorInputFactory; + /** * Registers a editor input factory for the given editor input to the registry. An editor input factory * is capable of serializing and deserializing editor inputs from string data. @@ -1387,6 +1401,7 @@ export interface IEditorMemento { class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { private instantiationService: IInstantiationService | undefined; private fileEditorInputFactory: IFileEditorInputFactory | undefined; + private customEditorInputFactory: ICustomEditorInputFactory | undefined; private readonly editorInputFactoryConstructors: Map> = new Map(); private readonly editorInputFactoryInstances: Map = new Map(); @@ -1414,6 +1429,14 @@ class EditorInputFactoryRegistry implements IEditorInputFactoryRegistry { return assertIsDefined(this.fileEditorInputFactory); } + registerCustomEditorInputFactory(factory: ICustomEditorInputFactory): void { + this.customEditorInputFactory = factory; + } + + getCustomEditorInputFactory(): ICustomEditorInputFactory { + return assertIsDefined(this.customEditorInputFactory); + } + registerEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0): IDisposable { if (!this.instantiationService) { this.editorInputFactoryConstructors.set(editorInputId, ctor); diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index c5d3cfad158..cf6840d00c8 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -697,15 +697,13 @@ export class ChoiceAction extends Action { private readonly _keepOpen: boolean; constructor(id: string, choice: IPromptChoice) { - super(id, choice.label, undefined, true, () => { + super(id, choice.label, undefined, true, async () => { // Pass to runner choice.run(); // Emit Event this._onDidRun.fire(); - - return Promise.resolve(); }); this._keepOpen = !!choice.keepOpen; diff --git a/src/vs/workbench/contrib/backup/common/backupRestorer.ts b/src/vs/workbench/contrib/backup/common/backupRestorer.ts index bb6ce23065f..483c29c97c0 100644 --- a/src/vs/workbench/contrib/backup/common/backupRestorer.ts +++ b/src/vs/workbench/contrib/backup/common/backupRestorer.ts @@ -10,9 +10,11 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { Schemas } from 'vs/base/common/network'; import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { IUntitledTextResourceEditorInput, IEditorInput } from 'vs/workbench/common/editor'; +import { IUntitledTextResourceEditorInput, IEditorInput, IEditorInputFactoryRegistry, Extensions as EditorExtensions, IEditorInputWithOptions } from 'vs/workbench/common/editor'; import { toLocalResource, isEqual } from 'vs/base/common/resources'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; export class BackupRestorer implements IWorkbenchContribution { @@ -22,7 +24,8 @@ export class BackupRestorer implements IWorkbenchContribution { @IEditorService private readonly editorService: IEditorService, @IBackupFileService private readonly backupFileService: IBackupFileService, @ILifecycleService private readonly lifecycleService: ILifecycleService, - @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, + @IInstantiationService private readonly instantiationService: IInstantiationService, ) { this.restoreBackups(); } @@ -78,13 +81,13 @@ export class BackupRestorer implements IWorkbenchContribution { private async doOpenEditors(resources: URI[]): Promise { const hasOpenedEditors = this.editorService.visibleEditors.length > 0; - const inputs = resources.map((resource, index) => this.resolveInput(resource, index, hasOpenedEditors)); + const inputs = await Promise.all(resources.map((resource, index) => this.resolveInput(resource, index, hasOpenedEditors))); // Open all remaining backups as editors and resolve them to load their backups await this.editorService.openEditors(inputs); } - private resolveInput(resource: URI, index: number, hasOpenedEditors: boolean): IResourceEditorInput | IUntitledTextResourceEditorInput { + private async resolveInput(resource: URI, index: number, hasOpenedEditors: boolean): Promise { const options = { pinned: true, preserveFocus: true, inactive: index > 0 || hasOpenedEditors }; // this is a (weak) strategy to find out if the untitled input had @@ -94,6 +97,12 @@ export class BackupRestorer implements IWorkbenchContribution { return { resource: toLocalResource(resource, this.environmentService.configuration.remoteAuthority), options, forceUntitled: true }; } + if (resource.scheme === Schemas.vscodeCustomEditor) { + const editor = await Registry.as(EditorExtensions.EditorInputFactories).getCustomEditorInputFactory() + .createCustomEditorInput(resource, this.instantiationService); + return { editor, options }; + } + return { resource, options }; } } diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts index c7916e7de2d..4a9b99b6971 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts @@ -399,7 +399,7 @@ export class BulkEditPreviewProvider implements ITextModelContentProvider { } // apply new edits and keep (future) undo edits const newEdits = this._operations.getFileEdits(uri); - const newUndoEdits = model.applyEdits(newEdits); + const newUndoEdits = model.applyEdits(newEdits, true); this._modelPreviewEdits.set(model.id, newUndoEdits); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index 4b2a6cb01fe..8bf6780d36e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -59,5 +59,5 @@ Registry.as(Extensions.Quickaccess).registerQuickAccessPro ctor: GotoLineQuickAccessProvider, prefix: AbstractGotoLineQuickAccessProvider.PREFIX, placeholder: localize('gotoLineQuickAccessPlaceholder', "Type the line number and optional column to go to (e.g. 42:5 for line 42 and column 5)."), - helpEntries: [{ description: localize('gotoLineQuickAccess', "Go to Line"), needsEditor: true }] + helpEntries: [{ description: localize('gotoLineQuickAccess', "Go to Line/Column"), needsEditor: true }] }); diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index f85d3f139c6..9cc9b501b45 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -4,15 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { IKeyMods } from 'vs/platform/quickinput/common/quickInput'; +import { IKeyMods, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { IEditor } from 'vs/editor/common/editorCommon'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IRange } from 'vs/editor/common/core/range'; import { Registry } from 'vs/platform/registry/common/platform'; import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess'; -import { AbstractGotoSymbolQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoSymbolQuickAccess'; +import { AbstractGotoSymbolQuickAccessProvider, IGotoSymbolQuickPickItem } from 'vs/editor/contrib/quickAccess/gotoSymbolQuickAccess'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; +import { ITextModel } from 'vs/editor/common/model'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { timeout } from 'vs/base/common/async'; +import { CancellationToken } from 'vs/base/common/cancellation'; export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider { @@ -56,11 +60,45 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess super.gotoLocation(editor, options); } } + + + //#region public methods to use this picker from other pickers + + private static readonly SYMBOL_PICKS_TIMEOUT = 8000; + + async getSymbolPicks(model: ITextModel, filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { + + // If the registry does not know the model, we wait for as long as + // the registry knows it. This helps in cases where a language + // registry was not activated yet for providing any symbols. + // To not wait forever, we eventually timeout though. + const result = await Promise.race([ + this.waitForLanguageSymbolRegistry(model, disposables), + timeout(GotoSymbolQuickAccessProvider.SYMBOL_PICKS_TIMEOUT) + ]); + + if (!result || token.isCancellationRequested) { + return []; + } + + return this.doGetSymbolPicks(this.getDocumentSymbols(model, true, token), filter, token); + } + + addDecorations(editor: IEditor, range: IRange): void { + super.addDecorations(editor, range); + } + + clearDecorations(editor: IEditor): void { + super.clearDecorations(editor); + } + + //#endregion } Registry.as(Extensions.Quickaccess).registerQuickAccessProvider({ ctor: GotoSymbolQuickAccessProvider, prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX, + contextKey: 'inFileSymbolsPicker', placeholder: localize('gotoSymbolQuickAccessPlaceholder', "Type the name of a symbol to go to."), helpEntries: [ { description: localize('gotoSymbolQuickAccess', "Go to Symbol in Editor"), prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX, needsEditor: true }, diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts index b3a167aca13..17acd2da4b4 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts @@ -19,7 +19,6 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { DefaultSettingsEditorContribution } from 'vs/workbench/contrib/preferences/browser/preferencesEditor'; -import { registerAndGetAmdImageURL } from 'vs/base/common/amd'; const transientWordWrapState = 'transientWordWrapState'; const isWordWrapMinifiedKey = 'isWordWrapMinified'; @@ -272,16 +271,12 @@ registerEditorContribution(ToggleWordWrapController.ID, ToggleWordWrapController registerEditorAction(ToggleWordWrapAction); -const WORD_WRAP_DARK_ICON = URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/codeEditor/browser/word-wrap-dark.svg')); -const WORD_WRAP_LIGHT_ICON = URI.parse(registerAndGetAmdImageURL('vs/workbench/contrib/codeEditor/browser/word-wrap-light.svg')); - MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: TOGGLE_WORD_WRAP_ID, title: nls.localize('unwrapMinified', "Disable wrapping for this file"), icon: { - dark: WORD_WRAP_DARK_ICON, - light: WORD_WRAP_LIGHT_ICON + id: 'codicon/word-wrap' } }, group: 'navigation', @@ -297,8 +292,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { id: TOGGLE_WORD_WRAP_ID, title: nls.localize('wrapMinified', "Enable wrapping for this file"), icon: { - dark: WORD_WRAP_DARK_ICON, - light: WORD_WRAP_LIGHT_ICON + id: 'codicon/word-wrap' } }, group: 'navigation', diff --git a/src/vs/workbench/contrib/codeEditor/browser/word-wrap-dark.svg b/src/vs/workbench/contrib/codeEditor/browser/word-wrap-dark.svg deleted file mode 100644 index f54d621127f..00000000000 --- a/src/vs/workbench/contrib/codeEditor/browser/word-wrap-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/codeEditor/browser/word-wrap-light.svg b/src/vs/workbench/contrib/codeEditor/browser/word-wrap-light.svg deleted file mode 100644 index 6a8e3fdf933..00000000000 --- a/src/vs/workbench/contrib/codeEditor/browser/word-wrap-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index 3938e3b5cac..c2acedc2a6f 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -3,21 +3,41 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { URI } from 'vs/base/common/uri'; -import { generateUuid } from 'vs/base/common/uuid'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; -import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; -import { IWebviewWorkbenchService } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { Lazy } from 'vs/base/common/lazy'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { generateUuid } from 'vs/base/common/uuid'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IEditorInput } from 'vs/workbench/common/editor'; +import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; +import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; +import { WebviewEditorInputFactory } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory'; +import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; +import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; + +export interface CustomDocumentBackupData { + readonly viewType: string; + readonly editorResource: UriComponents; + readonly extension: undefined | { + readonly location: UriComponents; + readonly id: string; + }; + + readonly webview: { + readonly id: string; + readonly options: WebviewInputOptions; + readonly state: any; + }; +} export class CustomEditorInputFactory extends WebviewEditorInputFactory { public static readonly ID = CustomEditorInput.typeId; public constructor( + @IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService, @IInstantiationService private readonly _instantiationService: IInstantiationService, - @IWebviewWorkbenchService private readonly webviewWorkbenchService: IWebviewWorkbenchService, + @IWebviewService private readonly _webviewService: IWebviewService, ) { super(webviewWorkbenchService); } @@ -43,11 +63,19 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory { const id = data.id || generateUuid(); const webview = new Lazy(() => { - const webviewInput = this.webviewWorkbenchService.reviveWebview(id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? { - location: data.extensionLocation, - id: data.extensionId - } : undefined, data.group); - return webviewInput.webview; + const webview = this._webviewService.createWebviewOverlay(id, { + enableFindWidget: data.options.enableFindWidget, + retainContextWhenHidden: data.options.retainContextWhenHidden + }, data.options); + + if (data.extensionLocation && data.extensionId) { + webview.extension = { + location: data.extensionLocation, + id: data.extensionId + }; + } + + return webview; }); const customInput = this._instantiationService.createInstance(CustomEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview); @@ -56,4 +84,37 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory { } return customInput; } + + public static createCustomEditorInput(resource: URI, instantiationService: IInstantiationService): Promise { + return instantiationService.invokeFunction(async accessor => { + const webviewService = accessor.get(IWebviewService); + const backupFileService = accessor.get(IBackupFileService); + + const backup = await backupFileService.resolve(resource); + if (!backup) { + throw new Error(`No backup found for custom editor: ${resource}`); + } + + const backupData = backup.meta as CustomDocumentBackupData; + const id = backupData.webview.id; + + const webview = new Lazy(() => { + const webview = webviewService.createWebviewOverlay(id, { + enableFindWidget: backupData.webview.options.enableFindWidget, + retainContextWhenHidden: backupData.webview.options.retainContextWhenHidden + }, backupData.webview.options); + + webview.extension = backupData.extension ? { + location: URI.revive(backupData.extension.location), + id: new ExtensionIdentifier(backupData.extension.id), + } : undefined; + + return webview; + }); + + const editor = instantiationService.createInstance(CustomEditorInput, URI.revive(backupData.editorResource), backupData.viewType, id, webview); + editor.updateGroup(0); + return editor; + }); + } } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 90b2642be0d..b128ad655fb 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -306,7 +306,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ private updateContexts() { const activeEditorPane = this.editorService.activeEditorPane; - const resource = activeEditorPane?.input.resource; + const resource = activeEditorPane?.input?.resource; if (!resource) { this._customEditorContextKey.reset(); this._focusedCustomEditorIsEditable.reset(); diff --git a/src/vs/workbench/contrib/customEditor/browser/webviewEditor.contribution.ts b/src/vs/workbench/contrib/customEditor/browser/webviewEditor.contribution.ts index 00f28e3ecd9..ccd535c3b0f 100644 --- a/src/vs/workbench/contrib/customEditor/browser/webviewEditor.contribution.ts +++ b/src/vs/workbench/contrib/customEditor/browser/webviewEditor.contribution.ts @@ -38,6 +38,8 @@ Registry.as(EditorInputExtensions.EditorInputFactor CustomEditorInputFactory.ID, CustomEditorInputFactory); +Registry.as(EditorInputExtensions.EditorInputFactories).registerCustomEditorInputFactory(CustomEditorInputFactory); + Registry.as(ConfigurationExtensions.Configuration) .registerConfiguration({ ...workbenchConfigurationNodeBase, diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 7c3220d2e54..8cb2bb87d47 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -95,13 +95,15 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewE focusCommand: { id: OpenDebugPanelAction.ID, keybindings: openPanelKb - } + }, + hideIfEmpty: true }, ViewContainerLocation.Panel); Registry.as(ViewExtensions.ViewsRegistry).registerViews([{ id: REPL_VIEW_ID, name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'), canToggleVisibility: false, + canMoveView: true, ctorDescriptor: new SyncDescriptor(Repl), }], VIEW_CONTAINER); @@ -180,6 +182,7 @@ registerDebugCommandPaletteItem(TOGGLE_INLINE_BREAKPOINT_ID, nls.localize('inlin Registry.as(QuickAccessExtensions.Quickaccess).registerQuickAccessProvider({ ctor: StartDebugQuickAccessProvider, prefix: StartDebugQuickAccessProvider.PREFIX, + contextKey: 'inLaunchConfigurationsPicker', placeholder: nls.localize('startDebugPlaceholder', "Type the name of a launch configuration to run."), helpEntries: [{ description: nls.localize('startDebugHelp', "Start Debug Configurations"), needsEditor: false }] }); diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index ca526214360..9a168614fcb 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -760,8 +760,9 @@ export class DebugService implements IDebugService { const control = editor.getControl(); if (stackFrame && isCodeEditor(control) && control.hasModel()) { const model = control.getModel(); - if (stackFrame.range.startLineNumber <= model.getLineCount()) { - const lineContent = control.getModel().getLineContent(stackFrame.range.startLineNumber); + const lineNumber = stackFrame.range.startLineNumber; + if (lineNumber >= 1 && lineNumber <= model.getLineCount()) { + const lineContent = control.getModel().getLineContent(lineNumber); aria.alert(nls.localize('debuggingPaused', "Debugging paused {0}, {1} {2} {3}", thread && thread.stoppedDetails ? `, reason ${thread.stoppedDetails.reason}` : '', stackFrame.source ? stackFrame.source.name : '', stackFrame.range.startLineNumber, lineContent)); } } diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 56022d9f636..42c5a0a8f7b 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -50,7 +50,6 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe import { RunOnceScheduler } from 'vs/base/common/async'; import { FuzzyScore } from 'vs/base/common/filters'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; import { ReplDelegate, ReplVariablesRenderer, ReplSimpleElementsRenderer, ReplEvaluationInputsRenderer, ReplEvaluationResultsRenderer, ReplRawObjectsRenderer, ReplDataSource, ReplAccessibilityProvider, ReplGroupRenderer } from 'vs/workbench/contrib/debug/browser/replViewer'; import { localize } from 'vs/nls'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; @@ -495,7 +494,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { setRowLineHeight: false, supportDynamicHeights: wordWrap, overrideStyles: { - listBackground: PANEL_BACKGROUND + listBackground: this.getBackgroundColor() } }); this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); diff --git a/src/vs/workbench/contrib/debug/common/debugUtils.ts b/src/vs/workbench/contrib/debug/common/debugUtils.ts index 2c25261bd41..02f3fdcd869 100644 --- a/src/vs/workbench/contrib/debug/common/debugUtils.ts +++ b/src/vs/workbench/contrib/debug/common/debugUtils.ts @@ -128,10 +128,12 @@ function stringToUri(source: PathContainer): string | undefined { function uriToString(source: PathContainer): string | undefined { if (typeof source.path === 'object') { const u = uri.revive(source.path); - if (u.scheme === 'file') { - return u.fsPath; - } else { - return u.toString(); + if (u) { + if (u.scheme === 'file') { + return u.fsPath; + } else { + return u.toString(); + } } } return source.path; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index b68c1e206e8..ef82fc250c8 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -650,7 +650,7 @@ export class ExtensionEditor extends BaseEditor { body { padding: 10px 20px; line-height: 22px; - max-width: 780px; + max-width: 882px; margin: 0 auto; } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts b/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts index d45a0ebb62a..921231f3f86 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts @@ -48,12 +48,10 @@ export class InstallExtensionQuickAccessProvider extends PickerQuickAccessProvid } // Extension name typed: offer to search it - else { - return [genericSearchPickItem]; - } + return [genericSearchPickItem]; } - protected async getPicksForExtensionId(filter: string, fallback: IPickerQuickAccessItem, token: CancellationToken): Promise> { + private async getPicksForExtensionId(filter: string, fallback: IPickerQuickAccessItem, token: CancellationToken): Promise> { try { const galleryResult = await this.galleryService.query({ names: [filter], pageSize: 1 }, token); if (token.isCancellationRequested) { @@ -63,12 +61,12 @@ export class InstallExtensionQuickAccessProvider extends PickerQuickAccessProvid const galleryExtension = galleryResult.firstPage[0]; if (!galleryExtension) { return [fallback]; - } else { - return [{ - label: localize('install', "Press Enter to install extension '{0}'.", filter), - accept: () => this.installExtension(galleryExtension, filter) - }]; } + + return [{ + label: localize('install', "Press Enter to install extension '{0}'.", filter), + accept: () => this.installExtension(galleryExtension, filter) + }]; } catch (error) { if (token.isCancellationRequested) { return []; // expected error diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg deleted file mode 100644 index a60d77cd37a..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg deleted file mode 100644 index f541ed4d519..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg deleted file mode 100644 index a0948780ee4..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg deleted file mode 100644 index d9222c3c312..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/save-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/save-dark.svg deleted file mode 100644 index 8acad37a99c..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/save-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/save-light.svg b/src/vs/workbench/contrib/extensions/browser/media/save-light.svg deleted file mode 100644 index 529e489a816..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/save-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg deleted file mode 100644 index 8b0a58eca9b..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/extensions/browser/media/start-light.svg b/src/vs/workbench/contrib/extensions/browser/media/start-light.svg deleted file mode 100644 index 2563bfa114b..00000000000 --- a/src/vs/workbench/contrib/extensions/browser/media/start-light.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 85b0c9e3147..0626bbb8cd8 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -18,10 +18,8 @@ import { RuntimeExtensionsEditor, ShowRuntimeExtensionsAction, IExtensionHostPro import { EditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, ActiveEditorContext } from 'vs/workbench/common/editor'; import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/electron-browser/extensionProfileService'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; -import { URI } from 'vs/base/common/uri'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler'; -import { registerAndGetAmdImageURL } from 'vs/base/common/amd'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { OpenExtensionsFolderAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions'; import { ExtensionsLabel } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -106,8 +104,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { id: DebugExtensionHostAction.ID, title: DebugExtensionHostAction.LABEL, icon: { - dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/start-dark.svg`)), - light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/start-light.svg`)), + id: 'codicon/debug-start' } }, group: 'navigation', @@ -119,8 +116,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { id: StartExtensionHostProfileAction.ID, title: StartExtensionHostProfileAction.LABEL, icon: { - dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg`)), - light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-start-light.svg`)), + id: 'codicon/circle-filled' } }, group: 'navigation', @@ -132,8 +128,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { id: StopExtensionHostProfileAction.ID, title: StopExtensionHostProfileAction.LABEL, icon: { - dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg`)), - light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg`)), + id: 'codicon/debug-stop' } }, group: 'navigation', @@ -145,8 +140,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { id: SaveExtensionHostProfileAction.ID, title: SaveExtensionHostProfileAction.LABEL, icon: { - dark: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/save-dark.svg`)), - light: URI.parse(registerAndGetAmdImageURL(`vs/workbench/contrib/extensions/browser/media/save-light.svg`)), + id: 'codicon/save-all' }, precondition: CONTEXT_EXTENSION_HOST_PROFILE_RECORDED }, diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 06f7b59aa6a..0a5a7859ad7 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -46,6 +46,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { sequence } from 'vs/base/common/async'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { once } from 'vs/base/common/functional'; export const NEW_FILE_COMMAND_ID = 'explorer.newFile'; export const NEW_FILE_LABEL = nls.localize('newFile', "New File"); @@ -498,9 +499,10 @@ export class GlobalCompareResourcesAction extends Action { return undefined; }); + once(this.quickOpenService.onHide)((() => toDispose.dispose())); + // Bring up quick open await this.quickOpenService.show('', { autoFocus: { autoFocusSecondEntry: true } }); - toDispose.dispose(); // make sure to unbind if quick open is closing } else { this.notificationService.info(nls.localize('openFileToCompare', "Open a file first to compare it with another file.")); } diff --git a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts index 2620461b323..971d20f9ea0 100644 --- a/src/vs/workbench/contrib/markers/browser/markers.contribution.ts +++ b/src/vs/workbench/contrib/markers/browser/markers.contribution.ts @@ -111,6 +111,7 @@ class ToggleMarkersPanelAction extends TogglePanelAction { const VIEW_CONTAINER: ViewContainer = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ id: Constants.MARKERS_CONTAINER_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, + hideIfEmpty: true, ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [Constants.MARKERS_CONTAINER_ID, Constants.MARKERS_VIEW_STORAGE_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), focusCommand: { id: ToggleMarkersPanelAction.ID, keybindings: { @@ -123,6 +124,7 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews id: Constants.MARKERS_VIEW_ID, name: Messages.MARKERS_PANEL_TITLE_PROBLEMS, canToggleVisibility: false, + canMoveView: true, ctorDescriptor: new SyncDescriptor(MarkersView), }], VIEW_CONTAINER); diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index d19f41ae6f6..5bc57f81a4a 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -44,7 +44,6 @@ import { withUndefinedAsNull } from 'vs/base/common/types'; import { MementoObject, Memento } from 'vs/workbench/common/memento'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { PANEL_BACKGROUND } from 'vs/workbench/common/theme'; import { KeyCode } from 'vs/base/common/keyCodes'; import { editorLightBulbForeground, editorLightBulbAutoFixForeground } from 'vs/platform/theme/common/colorRegistry'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; @@ -419,7 +418,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { dnd: new ResourceDragAndDrop(this.instantiationService), expandOnlyOnTwistieClick: (e: TreeElement) => e instanceof Marker && e.relatedInformation.length > 0, overrideStyles: { - listBackground: PANEL_BACKGROUND + listBackground: this.getBackgroundColor() } }, )); diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 2381b2bef49..47f1360e76c 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -26,5 +26,10 @@ export const EDITOR_BOTTOM_PADDING = 8; export const EDITOR_TOOLBAR_HEIGHT = 22; export const RUN_BUTTON_WIDTH = 20; -// Context Keys -export const NOTEBOOK_CELL_TYPE_CONTEXT_KEY = 'notebookCellType'; +// Cell context keys +export const NOTEBOOK_CELL_TYPE_CONTEXT_KEY = 'notebookCellType'; // code, markdown +export const NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY = 'notebookCellEditable'; // bool +export const NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY = 'notebookCellMarkdownEditMode'; // bool + +// Notebook context keys +export const NOTEBOOK_EDITABLE_CONTEXT_KEY = 'notebookEditable'; diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts index ced79da2b80..490334e53cc 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts @@ -11,12 +11,21 @@ import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/commo import { InputFocusedContext, InputFocusedContextKey, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { COPY_CELL_DOWN_COMMAND_ID, COPY_CELL_UP_COMMAND_ID, DELETE_CELL_COMMAND_ID, EDIT_CELL_COMMAND_ID, EXECUTE_CELL_COMMAND_ID, INSERT_CODE_CELL_ABOVE_COMMAND_ID, INSERT_CODE_CELL_BELOW_COMMAND_ID, INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID, INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, MOVE_CELL_DOWN_COMMAND_ID, MOVE_CELL_UP_COMMAND_ID, SAVE_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/constants'; -import { CellRenderTemplate, CellState, ICellViewModel, INotebookEditor, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { COPY_CELL_DOWN_COMMAND_ID, COPY_CELL_UP_COMMAND_ID, DELETE_CELL_COMMAND_ID, EDIT_CELL_COMMAND_ID, EXECUTE_CELL_COMMAND_ID, INSERT_CODE_CELL_ABOVE_COMMAND_ID, INSERT_CODE_CELL_BELOW_COMMAND_ID, INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID, INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, MOVE_CELL_DOWN_COMMAND_ID, MOVE_CELL_UP_COMMAND_ID, SAVE_CELL_COMMAND_ID, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellRenderTemplate, CellEditState, ICellViewModel, INotebookEditor, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, CellRunState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +const enum CellToolbarOrder { + MoveCellUp, + MoveCellDown, + EditCell, + SaveCell, + InsertCell, + DeleteCell +} + registerAction2(class extends Action2 { constructor() { super({ @@ -29,7 +38,8 @@ registerAction2(class extends Action2 { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.Enter }, weight: KeybindingWeight.WorkbenchContrib - } + }, + icon: { id: 'codicon/play' } }); } @@ -41,7 +51,7 @@ registerAction2(class extends Action2 { } } - runCell(accessor, context); + runCell(context); } }); @@ -159,6 +169,29 @@ registerAction2(class extends Action2 { } }); +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.executeNotebookCell', + title: localize('notebookActions.executeNotebookCell', "Execute Notebook Active Cell") + }); + } + + async run(accessor: ServicesAccessor): Promise { + let editorService = accessor.get(IEditorService); + let editor = getActiveNotebookEditor(editorService); + + if (!editor) { + return; + } + + let activeCell = editor.getActiveCell(); + if (activeCell) { + return editor.executeNotebookCell(activeCell); + } + } +}); + registerAction2(class extends Action2 { constructor() { super({ @@ -183,7 +216,7 @@ registerAction2(class extends Action2 { let activeCell = editor.getActiveCell(); if (activeCell) { if (activeCell.cellKind === CellKind.Markdown) { - activeCell.state = CellState.Preview; + activeCell.editState = CellEditState.Preview; } editor.focusNotebookCell(activeCell, false); @@ -300,73 +333,26 @@ function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor async function runActiveCell(accessor: ServicesAccessor): Promise { const editorService = accessor.get(IEditorService); - const notebookService = accessor.get(INotebookService); - - const resource = editorService.activeEditor?.resource; - if (!resource) { - return; - } - const editor = getActiveNotebookEditor(editorService); if (!editor) { return; } - const notebookProviders = notebookService.getContributedNotebookProviders(resource); - if (!notebookProviders.length) { - return; - } - const activeCell = editor.getActiveCell(); if (!activeCell) { return; } - const idx = editor.viewModel?.getViewCellIndex(activeCell); - if (typeof idx !== 'number') { - return; - } - - const viewType = notebookProviders[0].id; - await notebookService.executeNotebookActiveCell(viewType, resource); - + editor.executeNotebookCell(activeCell); return activeCell; } -async function runCell(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - const progress = context.cellTemplate?.progressBar; - if (progress) { - progress.infinite().show(500); +async function runCell(context: INotebookCellActionContext): Promise { + if (context.cell.runState === CellRunState.Running) { + return; } - try { - const editorService = accessor.get(IEditorService); - const notebookService = accessor.get(INotebookService); - const resource = editorService.activeEditor?.resource; - if (!resource) { - return; - } - - const editor = getActiveNotebookEditor(editorService); - if (!editor) { - return; - } - - const notebookProviders = notebookService.getContributedNotebookProviders(resource); - if (!notebookProviders.length) { - return; - } - - // Need to make active, maybe TODO - editor.focusNotebookCell(context.cell, false); - - const viewType = notebookProviders[0].id; - await notebookService.executeNotebookActiveCell(viewType, resource); - } finally { - if (progress) { - progress.hide(); - } - } + return context.notebookEditor.executeNotebookCell(context.cell); } async function changeActiveCellToKind(kind: CellKind, accessor: ServicesAccessor): Promise { @@ -464,7 +450,18 @@ registerAction2(class extends InsertCellCommand { super( { id: INSERT_CODE_CELL_BELOW_COMMAND_ID, - title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below") + title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below"), + icon: { id: 'codicon/add' }, + menu: { + id: MenuId.NotebookCellTitle, + order: CellToolbarOrder.InsertCell, + alt: { + id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, + title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"), + icon: { id: 'codicon/add' }, + }, + when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) + } }, CellKind.Code, 'below'); @@ -488,89 +485,13 @@ registerAction2(class extends InsertCellCommand { super( { id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, - title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"), + title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below") }, CellKind.Markdown, 'below'); } }); -export class InsertCodeCellAboveAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: INSERT_CODE_CELL_ABOVE_COMMAND_ID, - title: localize('notebookActions.insertCodeCellAbove', "Insert Code Cell Above"), - icon: { id: 'codicon/add' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - -export class InsertCodeCellBelowAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: INSERT_CODE_CELL_BELOW_COMMAND_ID, - title: localize('notebookActions.insertCodeCellBelow', "Insert Code Cell Below"), - icon: { id: 'codicon/add' } - }, - { - id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, - title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"), - icon: { id: 'codicon/add' } - }, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - -export class InsertMarkdownCellAboveAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID, - title: localize('notebookActions.insertMarkdownCellAbove', "Insert Markdown Cell Above"), - icon: { id: 'codicon/add' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - -export class InsertMarkdownCellBelowAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: INSERT_MARKDOWN_CELL_BELOW_COMMAND_ID, - title: localize('notebookActions.insertMarkdownCellBelow', "Insert Markdown Cell Below"), - icon: { id: 'codicon/add' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - registerAction2(class extends Action2 { constructor() { super( @@ -581,7 +502,16 @@ registerAction2(class extends Action2 { when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.not(InputFocusedContextKey)), primary: KeyCode.Enter, weight: KeybindingWeight.WorkbenchContrib - } + }, + menu: { + id: MenuId.NotebookCellTitle, + when: ContextKeyExpr.and( + ContextKeyExpr.equals(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown'), + ContextKeyExpr.equals(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, false), + ContextKeyExpr.equals(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, true)), + order: CellToolbarOrder.EditCell + }, + icon: { id: 'codicon/pencil' } }); } @@ -597,30 +527,21 @@ registerAction2(class extends Action2 { } }); -export class EditCellAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: EDIT_CELL_COMMAND_ID, - title: localize('notebookActions.editCell', "Edit Cell"), - icon: { id: 'codicon/pencil' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - registerAction2(class extends Action2 { constructor() { super( { id: SAVE_CELL_COMMAND_ID, - title: localize('notebookActions.saveCell', "Save Cell") + title: localize('notebookActions.saveCell', "Save Cell"), + menu: { + id: MenuId.NotebookCellTitle, + when: ContextKeyExpr.and( + ContextKeyExpr.equals(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown'), + ContextKeyExpr.equals(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, true), + ContextKeyExpr.equals(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, true)), + order: CellToolbarOrder.SaveCell + }, + icon: { id: 'codicon/save' } }); } @@ -636,30 +557,19 @@ registerAction2(class extends Action2 { } }); -export class SaveCellAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: SAVE_CELL_COMMAND_ID, - title: localize('notebookActions.saveCell', "Save Cell"), - icon: { id: 'codicon/save' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} registerAction2(class extends Action2 { constructor() { super( { id: DELETE_CELL_COMMAND_ID, - title: localize('notebookActions.deleteCell', "Delete Cell") + title: localize('notebookActions.deleteCell', "Delete Cell"), + menu: { + id: MenuId.NotebookCellTitle, + order: CellToolbarOrder.DeleteCell, + when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) + }, + icon: { id: 'codicon/x' } }); } @@ -675,26 +585,6 @@ registerAction2(class extends Action2 { } }); -export class DeleteCellAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: DELETE_CELL_COMMAND_ID, - title: localize('notebookActions.deleteCell', "Delete Cell"), - icon: { id: 'codicon/x' } - }, - undefined, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - - this.class = 'codicon-x'; - } -} - async function moveCell(context: INotebookCellActionContext, direction: 'up' | 'down'): Promise { direction === 'up' ? context.notebookEditor.moveCellUp(context.cell) : @@ -712,7 +602,18 @@ registerAction2(class extends Action2 { super( { id: MOVE_CELL_UP_COMMAND_ID, - title: localize('notebookActions.moveCellUp', "Move Cell Up") + title: localize('notebookActions.moveCellUp', "Move Cell Up"), + icon: { id: 'codicon/arrow-up' }, + menu: { + id: MenuId.NotebookCellTitle, + order: CellToolbarOrder.MoveCellUp, + alt: { + id: COPY_CELL_UP_COMMAND_ID, + title: localize('notebookActions.copyCellUp', "Copy Cell Up"), + icon: { id: 'codicon/arrow-up' } + }, + when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) + }, }); } @@ -728,34 +629,23 @@ registerAction2(class extends Action2 { } }); -export class MoveCellUpAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: MOVE_CELL_UP_COMMAND_ID, - title: localize('notebookActions.moveCellUp', "Move Cell Up"), - icon: { id: 'codicon/arrow-up' } - }, - { - id: COPY_CELL_UP_COMMAND_ID, - title: localize('notebookActions.copyCellUp', "Copy Cell Up"), - icon: { id: 'codicon/arrow-up' } - }, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - } -} - registerAction2(class extends Action2 { constructor() { super( { id: MOVE_CELL_DOWN_COMMAND_ID, - title: localize('notebookActions.moveCellDown', "Move Cell Down") + title: localize('notebookActions.moveCellDown', "Move Cell Down"), + icon: { id: 'codicon/arrow-down' }, + menu: { + id: MenuId.NotebookCellTitle, + order: CellToolbarOrder.MoveCellDown, + alt: { + id: COPY_CELL_DOWN_COMMAND_ID, + title: localize('notebookActions.copyCellDown', "Copy Cell Down"), + icon: { id: 'codicon/arrow-down' } + }, + when: ContextKeyExpr.equals(NOTEBOOK_EDITABLE_CONTEXT_KEY, true) + }, }); } @@ -771,30 +661,6 @@ registerAction2(class extends Action2 { } }); -export class MoveCellDownAction extends MenuItemAction { - constructor( - @IContextKeyService contextKeyService: IContextKeyService, - @ICommandService commandService: ICommandService - ) { - super( - { - id: MOVE_CELL_DOWN_COMMAND_ID, - title: localize('notebookActions.moveCellDown', "Move Cell Down"), - icon: { id: 'codicon/arrow-down' } - }, - { - id: COPY_CELL_DOWN_COMMAND_ID, - title: localize('notebookActions.copyCellDown', "Copy Cell Down"), - icon: { id: 'codicon/arrow-down' } - }, - { shouldForwardArgs: true }, - contextKeyService, - commandService); - - this.class = 'codicon-arrow-down'; - } -} - registerAction2(class extends Action2 { constructor() { super( diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget.ts index c070f9f7ac1..8a78e23134b 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget.ts @@ -5,7 +5,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, INotebookEditor, CellFindMatch, CellState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, INotebookEditor, CellFindMatch, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { FindDecorations } from 'vs/editor/contrib/find/findDecorations'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; @@ -118,7 +118,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget { } private revealCellRange(cellIndex: number, matchIndex: number) { - this._findMatches[cellIndex].cell.state = CellState.Editing; + this._findMatches[cellIndex].cell.editState = CellEditState.Editing; this._notebookEditor.selectElement(this._findMatches[cellIndex].cell); this._notebookEditor.setCellSelection(this._findMatches[cellIndex].cell, this._findMatches[cellIndex].matches[matchIndex].range); this._notebookEditor.revealRangeInCenterIfOutsideViewport(this._findMatches[cellIndex].cell, this._findMatches[cellIndex].matches[matchIndex].range); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index ea3158a9565..038d43e4290 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -4,23 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; -import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; -import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; -import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; -import { IOutput, CellKind, IRenderOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { NotebookViewModel, IModelDecorationsChangeAccessor } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { FindMatch } from 'vs/editor/common/model'; -import { Range } from 'vs/editor/common/core/range'; +import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; +import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; +import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; +import { Range } from 'vs/editor/common/core/range'; +import { FindMatch } from 'vs/editor/common/model'; +import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; +import { IModelDecorationsChangeAccessor, NotebookViewModel, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NOTEBOOK_EDITABLE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); export const NOTEBOOK_EDITOR_FOCUSED = new RawContextKey('notebookEditorFocused', false); +export const NOTEBOOK_EDITOR_EDITABLE = new RawContextKey(NOTEBOOK_EDITABLE_CONTEXT_KEY, true); export interface NotebookLayoutInfo { width: number; @@ -28,14 +29,49 @@ export interface NotebookLayoutInfo { fontInfo: BareFontInfo; } +export interface NotebookLayoutChangeEvent { + width?: boolean; + height?: boolean; + fontInfo?: boolean; +} + +export interface CodeCellLayoutInfo { + readonly fontInfo: BareFontInfo | null; + readonly editorHeight: number; + readonly editorWidth: number; + readonly totalHeight: number; + readonly outputTotalHeight: number; + readonly indicatorHeight: number; +} + +export interface CodeCellLayoutChangeEvent { + editorHeight?: boolean; + outputHeight?: boolean; + totalHeight?: boolean; + outerWidth?: number; + font?: BareFontInfo; +} + +export interface MarkdownCellLayoutInfo { + readonly fontInfo: BareFontInfo | null; + readonly editorWidth: number; +} + +export interface MarkdownCellLayoutChangeEvent { + font?: BareFontInfo; + outerWidth?: number; +} + export interface ICellViewModel { readonly id: string; handle: number; uri: URI; cellKind: CellKind; - state: CellState; + editState: CellEditState; + runState: CellRunState; focusMode: CellFocusMode; getText(): string; + metadata: NotebookCellMetadata | undefined; } export interface INotebookEditor { @@ -104,6 +140,11 @@ export interface INotebookEditor { */ focusNotebookCell(cell: ICellViewModel, focusEditor: boolean): void; + /** + * Execute the given notebook cell + */ + executeNotebookCell(cell: ICellViewModel): Promise; + /** * Get current active cell */ @@ -207,11 +248,13 @@ export interface CellRenderTemplate { toolbar: ToolBar; focusIndicator?: HTMLElement; runToolbar?: ToolBar; + runButtonContainer?: HTMLElement; editingContainer?: HTMLElement; outputContainer?: HTMLElement; editor?: CodeEditorWidget; progressBar?: ProgressBar; disposables: DisposableStore; + toJSON(): void; } export interface IOutputTransformContribution { @@ -238,7 +281,12 @@ export enum CellRevealPosition { Center } -export enum CellState { +export enum CellRunState { + Idle, + Running +} + +export enum CellEditState { /** * Default state. * For markdown cell, it's Markdown preview. diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 9a24e4a8cc9..0e2f685aa49 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -22,13 +22,13 @@ import { contrastBorder, editorBackground, focusBorder, foreground, textBlockQuo import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { EditorOptions, IEditorMemento, IEditorCloseEvent } from 'vs/workbench/common/editor'; -import { INotebookEditor, NotebookLayoutInfo, CellState, NOTEBOOK_EDITOR_FOCUSED, CellFocusMode, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, NotebookLayoutInfo, CellEditState, NOTEBOOK_EDITOR_FOCUSED, CellFocusMode, ICellViewModel, CellRunState, NOTEBOOK_EDITOR_EDITABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer'; -import { IOutput, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IOutput, CellKind, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -38,12 +38,13 @@ import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { Emitter, Event } from 'vs/base/common/event'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget'; -import { NotebookViewModel, INotebookEditorViewState, IModelDecorationsChangeAccessor } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { NotebookViewModel, INotebookEditorViewState, IModelDecorationsChangeAccessor, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { Range } from 'vs/editor/common/core/range'; import { CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants'; import { Color, RGBA } from 'vs/base/common/color'; +import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; const $ = DOM.$; const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState'; @@ -83,9 +84,7 @@ export class NotebookCodeEditors implements ICompositeCodeEditor { get activeCodeEditor(): IEditor | undefined { const [focused] = this._list.getFocusedElements(); - return focused instanceof CellViewModel - ? this._renderedEditors.get(focused) - : undefined; + return this._renderedEditors.get(focused); } } @@ -97,6 +96,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { private list: NotebookCellList | undefined; private control: ICompositeCodeEditor | undefined; private renderedEditors: Map = new Map(); + private eventDispatcher: NotebookEventDispatcher | undefined; private notebookViewModel: NotebookViewModel | undefined; private localStore: DisposableStore = this._register(new DisposableStore()); private editorMemento: IEditorMemento; @@ -104,6 +104,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { private fontInfo: BareFontInfo | undefined; private dimension: DOM.Dimension | null = null; private editorFocus: IContextKey | null = null; + private editorEditable: IContextKey | null = null; private outputRenderer: OutputRenderer; private findWidget: NotebookFindWidget; @@ -158,6 +159,9 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this._register(this.onDidBlur(() => { this.editorFocus?.set(false); })); + + this.editorEditable = NOTEBOOK_EDITOR_EDITABLE.bindTo(this.contextKeyService); + this.editorEditable.set(true); } private generateFontInfo(): void { @@ -177,8 +181,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { DOM.addClass(this.body, 'cell-list-container'); const renders = [ - this.instantiationService.createInstance(CodeCellRenderer, this, this.renderedEditors), - this.instantiationService.createInstance(MarkdownCellRenderer, this), + this.instantiationService.createInstance(CodeCellRenderer, this, this.contextKeyService, this.renderedEditors), + this.instantiationService.createInstance(MarkdownCellRenderer, this.contextKeyService, this), ]; this.list = this.instantiationService.createInstance( @@ -333,10 +337,17 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element); } - this.notebookViewModel = this.instantiationService.createInstance(NotebookViewModel, input.viewType!, model); + this.eventDispatcher = new NotebookEventDispatcher(); + this.notebookViewModel = this.instantiationService.createInstance(NotebookViewModel, input.viewType!, model, this.eventDispatcher); + this.editorEditable?.set(!!this.notebookViewModel.metadata?.editable); + this.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); const viewState = this.loadTextEditorViewState(input); this.notebookViewModel.restoreEditorViewState(viewState); + this.localStore.add(this.eventDispatcher.onDidChangeMetadata((e) => { + this.editorEditable?.set(e.source.editable); + })); + this.localStore.add(this.notebookViewModel.onDidChangeViewCells((e) => { if (e.synchronous) { e.splices.reverse().forEach((diff) => { @@ -361,7 +372,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const scrollTop = this.list?.scrollTop || 0; const scrollHeight = this.list?.scrollHeight || 0; this.webview!.element.style.height = `${scrollHeight}px`; - let updateItems: { cell: CellViewModel, output: IOutput, cellTop: number }[] = []; + let updateItems: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[] = []; if (this.webview?.insetMapping) { this.webview?.insetMapping.forEach((value, key) => { @@ -383,12 +394,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } })); - this.localStore.add(this.list!.onDidChangeFocus((e) => { - if (e.elements.length > 0) { - this.notebookService.updateNotebookActiveCell(input.viewType!, input.resource!, e.elements[0].handle); - } - })); - this.list?.splice(0, this.list?.length || 0); this.list?.splice(0, 0, this.notebookViewModel!.viewCells as CellViewModel[]); this.list?.layout(); @@ -415,6 +420,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { DOM.toggleClass(this.rootElement, 'narrow-width', dimension.width < 600); DOM.size(this.body, dimension.width, dimension.height); this.list?.layout(dimension.height, dimension.width); + this.eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]); } protected saveState(): void { @@ -562,7 +568,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.list?.setFocus([insertIndex]); if (type === CellKind.Markdown) { - newCell.state = CellState.Editing; + newCell.editState = CellEditState.Editing; } DOM.scheduleAtNextAnimationFrame(() => { @@ -600,13 +606,13 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } editNotebookCell(cell: CellViewModel): void { - cell.state = CellState.Editing; + cell.editState = CellEditState.Editing; this.renderedEditors.get(cell)?.focus(); } saveNotebookCell(cell: ICellViewModel): void { - cell.state = CellState.Preview; + cell.editState = CellEditState.Preview; } getActiveCell() { @@ -619,6 +625,22 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { return undefined; } + async executeNotebookCell(cell: ICellViewModel): Promise { + try { + cell.runState = CellRunState.Running; + const provider = this.notebookService.getContributedNotebookProviders(cell.uri)[0]; + if (provider) { + const viewType = provider.id; + const notebookUri = CellUri.parse(cell.uri)?.notebook; + if (notebookUri) { + return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle); + } + } + } finally { + cell.runState = CellRunState.Idle; + } + } + focusNotebookCell(cell: ICellViewModel, focusEditor: boolean) { const index = this.notebookViewModel!.getViewCellIndex(cell); @@ -627,7 +649,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.list?.setSelection([index]); this.list?.focusView(); - cell.state = CellState.Editing; + cell.editState = CellEditState.Editing; cell.focusMode = CellFocusMode.Editor; this.revealInCenterIfOutsideViewport(cell); } else { @@ -636,7 +658,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { (document.activeElement as HTMLElement).blur(); } - cell.state = CellState.Preview; + cell.editState = CellEditState.Preview; cell.focusMode = CellFocusMode.Editor; this.list?.setFocus([index]); @@ -661,15 +683,12 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { fontInfo: this.fontInfo! }; } - getFontInfo(): BareFontInfo | undefined { - return this.fontInfo; - } triggerScroll(event: IMouseWheelEvent) { this.list?.triggerScrollFromMouseWheelEvent(event); } - createInset(cell: CellViewModel, output: IOutput, shadowContent: string, offset: number) { + createInset(cell: CodeCellViewModel, output: IOutput, shadowContent: string, offset: number) { if (!this.webview) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts index 3f46e71b503..6ae9de2a215 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts @@ -53,7 +53,7 @@ export class NotebookEditorModel extends EditorModel { let notebook = this.getNotebook(); if (notebook) { - let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs); + let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs, cell.metadata); this.notebook.insertNewCell(index, mainCell); this._dirty = true; this._onDidChangeDirty.fire(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookService.ts b/src/vs/workbench/contrib/notebook/browser/notebookService.ts index 0e71cb6bc0d..98ef0a91973 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookService.ts @@ -26,11 +26,10 @@ export const INotebookService = createDecorator('notebookServi export interface IMainNotebookController { resolveNotebook(viewType: string, uri: URI): Promise; executeNotebook(viewType: string, uri: URI): Promise; - updateNotebookActiveCell(uri: URI, cellHandle: number): void; createRawCell(uri: URI, index: number, language: string, type: CellKind): Promise; deleteCell(uri: URI, index: number): Promise - executeNotebookActiveCell(uri: URI): Promise; onDidReceiveMessage(uri: URI, message: any): void; + executeNotebookCell(uri: URI, handle: number): Promise; destoryNotebookDocument(notebook: INotebookTextModel): Promise; save(uri: URI): Promise; } @@ -46,10 +45,10 @@ export interface INotebookService { getRendererInfo(handle: number): INotebookRendererInfo | undefined; resolveNotebook(viewType: string, uri: URI): Promise; executeNotebook(viewType: string, uri: URI): Promise; - executeNotebookActiveCell(viewType: string, uri: URI): Promise; + executeNotebookCell(viewType: string, uri: URI, handle: number): Promise; + getContributedNotebookProviders(resource: URI): readonly NotebookProviderInfo[]; getNotebookProviderResourceRoots(): URI[]; - updateNotebookActiveCell(viewType: string, resource: URI, cellHandle: number): void; createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: CellKind): Promise; deleteNotebookCell(viewType: string, resource: URI, index: number): Promise; destoryNotebookDocument(viewType: string, notebook: INotebookTextModel): void; @@ -242,14 +241,6 @@ export class NotebookService extends Disposable implements INotebookService { return modelData.model; } - updateNotebookActiveCell(viewType: string, resource: URI, cellHandle: number): void { - let provider = this._notebookProviders.get(viewType); - - if (provider) { - provider.controller.updateNotebookActiveCell(resource, cellHandle); - } - } - async createNotebookCell(viewType: string, resource: URI, index: number, language: string, type: CellKind): Promise { let provider = this._notebookProviders.get(viewType); @@ -280,11 +271,10 @@ export class NotebookService extends Disposable implements INotebookService { return; } - async executeNotebookActiveCell(viewType: string, uri: URI): Promise { - let provider = this._notebookProviders.get(viewType); - + async executeNotebookCell(viewType: string, uri: URI, handle: number): Promise { + const provider = this._notebookProviders.get(viewType); if (provider) { - await provider.controller.executeNotebookActiveCell(uri); + await provider.controller.executeNotebookCell(uri, handle); } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index a1ac5d121d4..c074a43e24b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -18,7 +18,7 @@ import { NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/c import { Range } from 'vs/editor/common/core/range'; import { CellRevealType, CellRevealPosition, CursorAtBoundary } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; +import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; export class NotebookCellList extends WorkbenchList implements IDisposable { get onWillScroll(): Event { return this.view.onWillScroll; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index ee45296a157..90f4f47c61f 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -14,7 +14,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebook import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; import { Emitter, Event } from 'vs/base/common/event'; @@ -76,7 +76,7 @@ let version = 0; export class BackLayerWebView extends Disposable { element: HTMLElement; webview: WebviewElement; - insetMapping: Map = new Map(); + insetMapping: Map = new Map(); reversedInsetMapping: Map = new Map(); preloadsCache: Map = new Map(); localResourceRootsCache: URI[] | undefined = undefined; @@ -278,7 +278,7 @@ export class BackLayerWebView extends Disposable { if (cell) { let outputIndex = cell.outputs.indexOf(output); cell.updateOutputHeight(outputIndex, outputHeight); - this.notebookEditor.layoutNotebookCell(cell, cell.getCellTotalHeight()); + this.notebookEditor.layoutNotebookCell(cell, cell.layoutInfo.totalHeight); } } else if (data.type === 'scroll-ack') { // const date = new Date(); @@ -305,12 +305,12 @@ export class BackLayerWebView extends Disposable { return webview; } - shouldUpdateInset(cell: CellViewModel, output: IOutput, cellTop: number) { + shouldUpdateInset(cell: CodeCellViewModel, output: IOutput, cellTop: number) { let outputCache = this.insetMapping.get(output)!; let outputIndex = cell.outputs.indexOf(output); let outputOffsetInOutputContainer = cell.getOutputOffset(outputIndex); - let outputOffset = cellTop + cell.editorHeight + 16 /* editor padding */ + 8 + outputOffsetInOutputContainer; + let outputOffset = cellTop + cell.layoutInfo.editorHeight + 16 /* editor padding */ + 8 + outputOffsetInOutputContainer; if (outputOffset === outputCache.cacheOffset) { return false; @@ -319,14 +319,14 @@ export class BackLayerWebView extends Disposable { return true; } - updateViewScrollTop(top: number, items: { cell: CellViewModel, output: IOutput, cellTop: number }[]) { + updateViewScrollTop(top: number, items: { cell: CodeCellViewModel, output: IOutput, cellTop: number }[]) { let widgets: IContentWidgetTopRequest[] = items.map(item => { let outputCache = this.insetMapping.get(item.output)!; let id = outputCache.outputId; let outputIndex = item.cell.outputs.indexOf(item.output); let outputOffsetInOutputContainer = item.cell.getOutputOffset(outputIndex); - let outputOffset = item.cellTop + item.cell.editorHeight + 16 /* editor padding */ + 16 + outputOffsetInOutputContainer; + let outputOffset = item.cellTop + item.cell.layoutInfo.editorHeight + 16 /* editor padding */ + 16 + outputOffsetInOutputContainer; outputCache.cacheOffset = outputOffset; return { @@ -345,7 +345,7 @@ export class BackLayerWebView extends Disposable { this.webview.sendMessage(message); } - createInset(cell: CellViewModel, output: IOutput, cellTop: number, offset: number, shadowContent: string, preloads: Set) { + createInset(cell: CodeCellViewModel, output: IOutput, cellTop: number, offset: number, shadowContent: string, preloads: Set) { this.updateRendererPreloads(preloads); let initialTop = cellTop + offset; let outputId = UUID.generateUuid(); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellMenus.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellMenus.ts index 9ef1bb22fa3..324d509dafa 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellMenus.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellMenus.ts @@ -3,20 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDisposable } from 'vs/base/common/lifecycle'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; import { IAction } from 'vs/base/common/actions'; -import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -export class CellMenus implements IDisposable { +export class CellMenus { constructor( @IMenuService private readonly menuService: IMenuService, @IContextMenuService private readonly contextMenuService: IContextMenuService ) { } - getCellTitleActions(contextKeyService: IContextKeyService): IMenu { + getCellTitleMenu(contextKeyService: IContextKeyService): IMenu { return this.getMenu(MenuId.NotebookCellTitle, contextKeyService); } @@ -31,8 +30,4 @@ export class CellMenus implements IDisposable { return menu; } - - dispose(): void { - - } } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index e84828e608e..b9cedf6c465 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -16,22 +16,24 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { MenuItemAction } from 'vs/platform/actions/common/actions'; +import { MenuItemAction, IMenu } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_TYPE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants'; -import { DeleteCellAction, EditCellAction, ExecuteCellAction, INotebookCellActionContext, InsertCodeCellBelowAction, MoveCellDownAction, MoveCellUpAction, SaveCellAction, InsertCodeCellAboveAction, InsertMarkdownCellAboveAction, InsertMarkdownCellBelowAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions'; -import { CellRenderTemplate, ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellRenderTemplate, CellRunState, ICellViewModel, INotebookEditor, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell'; import { StatefullMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; +import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; +import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { CellViewModel } from '../../viewModel/notebookCellViewModel'; +import { INotebookCellActionContext, ExecuteCellAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; const $ = DOM.$; @@ -114,56 +116,52 @@ abstract class AbstractCellRenderer { return toolbar; } - protected createMenu(): CellMenus { - const menu = this.instantiationService.createInstance(CellMenus); - return menu; + private getCellToolbarActions(menu: IMenu): IAction[] { + const actions: IAction[] = []; + for (let [, menuActions] of menu.getActions({ shouldForwardArgs: true })) { + actions.push(...menuActions); + } + + return actions; } - abstract getCellToolbarActions(element: CellViewModel): IAction[]; + protected setupCellToolbarActions(scopedContextKeyService: IContextKeyService, templateData: CellRenderTemplate, disposables: DisposableStore): void { + const cellMenu = this.instantiationService.createInstance(CellMenus); + const menu = disposables.add(cellMenu.getCellTitleMenu(scopedContextKeyService)); - showContextMenu(listIndex: number | undefined, element: CellViewModel, x: number, y: number) { - const actions: IAction[] = [ - this.instantiationService.createInstance(InsertCodeCellAboveAction), - this.instantiationService.createInstance(InsertCodeCellBelowAction), - this.instantiationService.createInstance(InsertMarkdownCellAboveAction), - this.instantiationService.createInstance(InsertMarkdownCellBelowAction), - ]; - actions.push(...this.getAdditionalContextMenuActions()); - actions.push(...[ - this.instantiationService.createInstance(DeleteCellAction) - ]); + const updateActions = () => { + const actions = this.getCellToolbarActions(menu); - this.contextMenuService.showContextMenu({ - getAnchor: () => { - return { - x, - y - }; - }, - getActions: () => actions, - getActionsContext: () => { - cell: element, - notebookEditor: this.notebookEditor - }, - autoSelectFirstItem: false - }); + templateData.toolbar.setActions(actions)(); + + if (templateData.focusIndicator) { + if (actions.length) { + templateData.focusIndicator.style.top = `24px`; + } else { + templateData.focusIndicator.style.top = `8px`; + } + } + }; + + updateActions(); + disposables.add(menu.onDidChange(() => { + updateActions(); + })); } - - abstract getAdditionalContextMenuActions(): IAction[]; } -export class MarkdownCellRenderer extends AbstractCellRenderer implements IListRenderer { +export class MarkdownCellRenderer extends AbstractCellRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'markdown_cell'; private disposables: Map = new Map(); constructor( + contextKeyService: IContextKeyService, notehookEditor: INotebookEditor, @IInstantiationService instantiationService: IInstantiationService, @IConfigurationService configurationService: IConfigurationService, @IContextMenuService contextMenuService: IContextMenuService, @IKeybindingService keybindingService: IKeybindingService, @INotificationService notificationService: INotificationService, - @IContextKeyService contextKeyService: IContextKeyService ) { super(instantiationService, notehookEditor, contextMenuService, configurationService, keybindingService, notificationService, contextKeyService, 'markdown'); } @@ -194,11 +192,12 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR cellContainer: innerContent, editingContainer: codeInnerContent, disposables, - toolbar + toolbar, + toJSON: () => { return {}; } }; } - renderElement(element: CellViewModel, index: number, templateData: CellRenderTemplate, height: number | undefined): void { + renderElement(element: MarkdownCellViewModel, index: number, templateData: CellRenderTemplate, height: number | undefined): void { templateData.editingContainer!.style.display = 'none'; templateData.cellContainer.innerHTML = ''; let renderedHTML = element.getHTML(); @@ -211,22 +210,23 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR if (!this.disposables.has(element)) { this.disposables.set(element, new DisposableStore()); } - let elementDisposable = this.disposables.get(element); + const elementDisposable = this.disposables.get(element)!; - elementDisposable!.add(new StatefullMarkdownCell(this.notebookEditor, element, templateData, this.editorOptions, this.instantiationService)); + elementDisposable.add(new StatefullMarkdownCell(this.notebookEditor, element, templateData, this.editorOptions, this.instantiationService)); const contextKeyService = this.contextKeyService.createScoped(templateData.container); contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown'); - const toolbarActions = this.getCellToolbarActions(element); - templateData.toolbar!.setActions(toolbarActions)(); + const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable)); + elementDisposable.add(element.onDidChangeMetadata((e) => { + cellEditableKey.set(!!e?.editable); + })); - if (templateData.focusIndicator) { - if (!toolbarActions.length) { - templateData.focusIndicator.style.top = `8px`; - } else { - templateData.focusIndicator.style.top = `24px`; - } - } + const editModeKey = contextKeyService.createKey(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, element.editState === CellEditState.Editing); + elementDisposable.add(element.onDidChangeCellEditState(() => { + editModeKey.set(element.editState === CellEditState.Editing); + })); + + this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable); } templateData.toolbar!.context = { @@ -236,51 +236,6 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR }; } - getCellToolbarActions(element: CellViewModel): IAction[] { - const viewModel = this.notebookEditor.viewModel; - - if (!viewModel) { - return []; - } - - const menu = this.createMenu().getCellTitleActions(this.contextKeyService); - const actions: IAction[] = []; - for (let [, actions] of menu.getActions({ shouldForwardArgs: true })) { - actions.push(...actions); - } - - const metadata = viewModel.metadata; - - if (!metadata || metadata.editable) { - actions.push( - this.instantiationService.createInstance(MoveCellUpAction), - this.instantiationService.createInstance(MoveCellDownAction), - this.instantiationService.createInstance(InsertCodeCellBelowAction) - ); - } - - const cellMetadata = element.metadata; - if (!cellMetadata || cellMetadata.editable) { - actions.push( - this.instantiationService.createInstance(EditCellAction), - this.instantiationService.createInstance(SaveCellAction) - ); - } - - if (!metadata || metadata.editable) { - this.instantiationService.createInstance(DeleteCellAction); - } - - return actions; - } - - getAdditionalContextMenuActions(): IAction[] { - return [ - this.instantiationService.createInstance(EditCellAction), - this.instantiationService.createInstance(SaveCellAction), - ]; - } - disposeTemplate(templateData: CellRenderTemplate): void { // throw nerendererw Error('Method not implemented.'); @@ -293,19 +248,19 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } } -export class CodeCellRenderer extends AbstractCellRenderer implements IListRenderer { +export class CodeCellRenderer extends AbstractCellRenderer implements IListRenderer { static readonly TEMPLATE_ID = 'code_cell'; private disposables: Map = new Map(); constructor( protected notebookEditor: INotebookEditor, + protected contextKeyService: IContextKeyService, private renderedEditors: Map, @IContextMenuService contextMenuService: IContextMenuService, @IConfigurationService configurationService: IConfigurationService, @IInstantiationService instantiationService: IInstantiationService, @IKeybindingService keybindingService: IKeybindingService, @INotificationService notificationService: INotificationService, - @IContextKeyService contextKeyService: IContextKeyService ) { super(instantiationService, notebookEditor, contextMenuService, configurationService, keybindingService, notificationService, contextKeyService, 'python'); } @@ -317,12 +272,6 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende renderTemplate(container: HTMLElement): CellRenderTemplate { const disposables = new DisposableStore(); const toolbar = this.createToolbar(container); - toolbar.setActions([ - this.instantiationService.createInstance(MoveCellUpAction), - this.instantiationService.createInstance(MoveCellDownAction), - this.instantiationService.createInstance(InsertCodeCellBelowAction), - this.instantiationService.createInstance(DeleteCellAction) - ])(); disposables.add(toolbar); const cellContainer = DOM.append(container, $('.cell.code')); @@ -360,13 +309,15 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende focusIndicator, toolbar, runToolbar, + runButtonContainer, outputContainer, editor, - disposables + disposables, + toJSON: () => { return {}; } }; } - renderElement(element: CellViewModel, index: number, templateData: CellRenderTemplate, height: number | undefined): void { + renderElement(element: CodeCellViewModel, index: number, templateData: CellRenderTemplate, height: number | undefined): void { if (height === undefined) { return; } @@ -380,13 +331,21 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.disposables.set(element, new DisposableStore()); } - const elementDisposable = this.disposables.get(element); + const elementDisposable = this.disposables.get(element)!; - elementDisposable?.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData)); + elementDisposable.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData)); this.renderedEditors.set(element, templateData.editor); - elementDisposable?.add(element.onDidChangeTotalHeight(() => { - templateData.focusIndicator!.style.height = `${element.getIndicatorHeight()}px`; + elementDisposable.add(element.onDidChangeLayout(() => { + templateData.focusIndicator!.style.height = `${element.layoutInfo.indicatorHeight}px`; + })); + + elementDisposable.add(element.onDidChangeCellRunState(() => { + if (element.runState === CellRunState.Running) { + templateData.progressBar?.infinite().show(500); + } else { + templateData.progressBar?.hide(); + } })); const toolbarContext = { @@ -398,51 +357,14 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende const contextKeyService = this.contextKeyService.createScoped(templateData.container); contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code'); - const toolbarActions = this.getCellToolbarActions(element); - templateData.toolbar!.setActions(toolbarActions)(); - templateData.toolbar!.context = toolbarContext; + const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable)); + elementDisposable.add(element.onDidChangeMetadata((e) => { + cellEditableKey.set(!!e?.editable); + })); + + this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable); + templateData.toolbar.context = toolbarContext; templateData.runToolbar!.context = toolbarContext; - - if (templateData.focusIndicator) { - if (!toolbarActions.length) { - templateData.focusIndicator.style.top = `8px`; - } else { - templateData.focusIndicator.style.top = `24px`; - } - } - } - - - getCellToolbarActions(element: CellViewModel): IAction[] { - const viewModel = this.notebookEditor.viewModel; - - if (!viewModel) { - return []; - } - - const menu = this.createMenu().getCellTitleActions(this.contextKeyService); - const actions: IAction[] = []; - for (let [, actions] of menu.getActions({ shouldForwardArgs: true })) { - actions.push(...actions); - } - - const metadata = viewModel.metadata; - - if (!metadata || metadata.editable) { - actions.push( - this.instantiationService.createInstance(MoveCellUpAction), - this.instantiationService.createInstance(MoveCellDownAction), - this.instantiationService.createInstance(InsertCodeCellBelowAction), - this.instantiationService.createInstance(DeleteCellAction) - ); - } - - return actions; - } - - - getAdditionalContextMenuActions(): IAction[] { - return []; } disposeTemplate(templateData: CellRenderTemplate): void { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts index ee05ead40cb..ac0ac7fb97b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/codeCell.ts @@ -13,8 +13,8 @@ import { raceCancellation } from 'vs/base/common/async'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; -import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; +import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; interface IMimeTypeRenderer extends IQuickPickItem { index: number; @@ -25,19 +25,16 @@ export class CodeCell extends Disposable { private outputElements = new Map(); constructor( private notebookEditor: INotebookEditor, - private viewCell: CellViewModel, + private viewCell: CodeCellViewModel, private templateData: CellRenderTemplate, @INotebookService private notebookService: INotebookService, @IQuickInputService private readonly quickInputService: IQuickInputService ) { super(); - let width: number; - const listDimension = notebookEditor.getLayoutInfo(); - width = listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH; - - const lineNum = viewCell.lineCount; - const lineHeight = notebookEditor.getLayoutInfo().fontInfo.lineHeight; + const width = this.viewCell.layoutInfo.editorWidth; + const lineNum = this.viewCell.lineCount; + const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17; const totalHeight = lineNum * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; templateData.editor?.layout( { @@ -57,10 +54,8 @@ export class CodeCell extends Disposable { templateData.editor?.focus(); } - let realContentHeight = templateData.editor?.getContentHeight(); - let width: number; - const listDimension = notebookEditor.getLayoutInfo(); - width = listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH; + const realContentHeight = templateData.editor?.getContentHeight(); + const width = this.viewCell.layoutInfo.editorWidth; if (realContentHeight !== undefined && realContentHeight !== totalHeight) { templateData.editor?.layout( @@ -85,6 +80,11 @@ export class CodeCell extends Disposable { } })); + templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) }); + this._register(viewCell.onDidChangeMetadata((e) => { + templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) }); + })); + let cellWidthResizeObserver = getResizesObserver(templateData.editorContainer!, { width: width, height: totalHeight @@ -106,7 +106,7 @@ export class CodeCell extends Disposable { this._register(templateData.editor!.onDidContentSizeChange((e) => { if (e.contentHeightChanged) { - if (this.viewCell.editorHeight !== e.contentHeight) { + if (this.viewCell.layoutInfo.editorHeight !== e.contentHeight) { let viewLayout = templateData.editor!.getLayoutInfo(); templateData.editor?.layout( @@ -256,7 +256,7 @@ export class CodeCell extends Disposable { if (result.shadowContent) { this.viewCell.selfSizeMonitoring = true; - let editorHeight = this.viewCell.editorHeight; + let editorHeight = this.viewCell.layoutInfo.editorHeight; this.notebookEditor.createInset(this.viewCell, currOutput, result.shadowContent, editorHeight + 8 + this.viewCell.getOutputOffset(index)); } else { DOM.addClass(outputItemDiv, 'foreground'); @@ -266,11 +266,10 @@ export class CodeCell extends Disposable { if (hasDynamicHeight) { let clientHeight = outputItemDiv.clientHeight; - let listDimension = this.notebookEditor.getLayoutInfo(); - let dimension = listDimension ? { - width: listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH, + let dimension = { + width: this.viewCell.layoutInfo.editorWidth, height: clientHeight - } : undefined; + }; const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => { if (this.templateData.outputContainer && document.body.contains(this.templateData.outputContainer!)) { let height = elementSizeObserver.getHeight() + 8 * 2; // include padding @@ -369,7 +368,7 @@ export class CodeCell extends Disposable { } relayoutCell() { - this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.getCellTotalHeight()); + this.notebookEditor.layoutNotebookCell(this.viewCell, this.viewCell.layoutInfo.totalHeight); } dispose() { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 7cc24ffc142..3b4f7b6b993 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -8,11 +8,11 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; -import { INotebookEditor, CellRenderTemplate, CellFocusMode, CellState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, CellRenderTemplate, CellFocusMode, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { raceCancellation } from 'vs/base/common/async'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; -import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; +import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; +import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; export class StatefullMarkdownCell extends Disposable { private editor: CodeEditorWidget | null = null; @@ -23,7 +23,7 @@ export class StatefullMarkdownCell extends Disposable { constructor( notebookEditor: INotebookEditor, - public viewCell: CellViewModel, + public viewCell: MarkdownCellViewModel, templateData: CellRenderTemplate, editorOptions: IEditorOptions, instantiationService: IInstantiationService @@ -36,18 +36,11 @@ export class StatefullMarkdownCell extends Disposable { this._register(this.localDisposables); const viewUpdate = () => { - if (viewCell.state === CellState.Editing) { + if (viewCell.editState === CellEditState.Editing) { // switch to editing mode - let width: number; - const listDimension = notebookEditor.getLayoutInfo(); - width = listDimension.width - CELL_MARGIN * 2; - // if (listDimension) { - // } else { - // width = this.cellContainer.clientWidth - 24 /** for scrollbar and margin right */; - // } - + let width = viewCell.layoutInfo.editorWidth; const lineNum = viewCell.lineCount; - const lineHeight = notebookEditor.getLayoutInfo().fontInfo.lineHeight; + const lineHeight = viewCell.layoutInfo.fontInfo?.lineHeight || 17; const totalHeight = Math.max(lineNum, 1) * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; if (this.editor) { @@ -106,7 +99,7 @@ export class StatefullMarkdownCell extends Disposable { notebookEditor.layoutNotebookCell(viewCell, this.editor!.getContentHeight() + 32 + clientHeight); })); - if (viewCell.state === CellState.Editing) { + if (viewCell.editState === CellEditState.Editing) { this.editor!.focus(); } }); @@ -197,7 +190,7 @@ export class StatefullMarkdownCell extends Disposable { } }; - this._register(viewCell.onDidChangeCellState(() => { + this._register(viewCell.onDidChangeCellEditState(() => { this.localDisposables.clear(); viewUpdate(); })); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts new file mode 100644 index 00000000000..3ac661e9737 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -0,0 +1,339 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import * as editorCommon from 'vs/editor/common/editorCommon'; +import * as model from 'vs/editor/common/model'; +import { Range } from 'vs/editor/common/core/range'; +import { ICell, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CursorAtBoundary, CellFocusMode, CellEditState, CellRunState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { EDITOR_TOP_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; +import { SearchParams } from 'vs/editor/common/model/textModelSearch'; + +export const NotebookCellMetadataDefaults = { + editable: true, + runnable: true +}; + +export abstract class BaseCellViewModel extends Disposable { + protected readonly _onDidDispose = new Emitter(); + readonly onDidDispose = this._onDidDispose.event; + protected readonly _onDidChangeCellEditState = new Emitter(); + readonly onDidChangeCellEditState = this._onDidChangeCellEditState.event; + protected readonly _onDidChangeCellRunState = new Emitter(); + readonly onDidChangeCellRunState = this._onDidChangeCellRunState.event; + protected readonly _onDidChangeFocusMode = new Emitter(); + readonly onDidChangeFocusMode = this._onDidChangeFocusMode.event; + protected readonly _onDidChangeEditorAttachState = new Emitter(); + readonly onDidChangeEditorAttachState = this._onDidChangeEditorAttachState.event; + protected readonly _onDidChangeCursorSelection: Emitter = this._register(new Emitter()); + public readonly onDidChangeCursorSelection: Event = this._onDidChangeCursorSelection.event; + protected readonly _onDidChangeMetadata: Emitter = this._register(new Emitter()); + public readonly onDidChangeMetadata: Event = this._onDidChangeMetadata.event; + get handle() { + return this.cell.handle; + } + get uri() { + return this.cell.uri; + } + get lineCount() { + return this.cell.source.length; + } + get metadata() { + return this.cell.metadata; + } + + private _editState: CellEditState = CellEditState.Preview; + + get editState(): CellEditState { + return this._editState; + } + + set editState(newState: CellEditState) { + if (newState === this._editState) { + return; + } + + this._editState = newState; + this._onDidChangeCellEditState.fire(); + } + private _runState: CellRunState = CellRunState.Idle; + + get runState(): CellRunState { + return this._runState; + } + + set runState(newState: CellRunState) { + if (newState === this._runState) { + return; + } + + this._runState = newState; + this._onDidChangeCellRunState.fire(); + } + private _focusMode: CellFocusMode = CellFocusMode.Container; + get focusMode() { + return this._focusMode; + } + set focusMode(newMode: CellFocusMode) { + this._focusMode = newMode; + this._onDidChangeFocusMode.fire(); + } + + protected _textEditor?: ICodeEditor; + get editorAttached(): boolean { + return !!this._textEditor; + } + private _cursorChangeListener: IDisposable | null = null; + private _editorViewStates: editorCommon.ICodeEditorViewState | null = null; + private _resolvedDecorations = new Map(); + private _lastDecorationId: number = 0; + protected _textModel?: model.ITextModel; + + constructor(readonly viewType: string, readonly notebookHandle: number, readonly cell: ICell, public id: string) { + super(); + + this._register(cell.onDidChangeMetadata((e) => { + this._onDidChangeMetadata.fire(e); + })); + } + + abstract hasDynamicHeight(): boolean; + abstract getHeight(lineHeight: number): number; + abstract onDeselect(): void; + + assertTextModelAttached(): boolean { + if (this._textModel && this._textEditor && this._textEditor.getModel() === this._textModel) { + return true; + } + + return false; + } + + attachTextEditor(editor: ICodeEditor) { + if (!editor.hasModel()) { + throw new Error('Invalid editor: model is missing'); + } + + if (this._textEditor === editor) { + if (this._cursorChangeListener === null) { + this._cursorChangeListener = this._textEditor.onDidChangeCursorSelection(() => this._onDidChangeCursorSelection.fire()); + this._onDidChangeCursorSelection.fire(); + } + return; + } + + this._textEditor = editor; + + if (this._editorViewStates) { + this.restoreViewState(this._editorViewStates); + } + + this._resolvedDecorations.forEach((value, key) => { + if (key.startsWith('_lazy_')) { + // lazy ones + const ret = this._textEditor!.deltaDecorations([], [value.options]); + this._resolvedDecorations.get(key)!.id = ret[0]; + } + else { + const ret = this._textEditor!.deltaDecorations([], [value.options]); + this._resolvedDecorations.get(key)!.id = ret[0]; + } + }); + + this._cursorChangeListener = this._textEditor.onDidChangeCursorSelection(() => this._onDidChangeCursorSelection.fire()); + this._onDidChangeCursorSelection.fire(); + this._onDidChangeEditorAttachState.fire(true); + } + + detachTextEditor() { + this._editorViewStates = this.saveViewState(); + // decorations need to be cleared first as editors can be resued. + this._resolvedDecorations.forEach(value => { + let resolvedid = value.id; + + if (resolvedid) { + this._textEditor?.deltaDecorations([resolvedid], []); + } + }); + + this._textEditor = undefined; + this._cursorChangeListener?.dispose(); + this._cursorChangeListener = null; + this._onDidChangeEditorAttachState.fire(false); + } + + getText(): string { + if (this._textModel) { + return this._textModel.getValue(); + } + + return this.cell.source.join('\n'); + } + + private saveViewState(): editorCommon.ICodeEditorViewState | null { + if (!this._textEditor) { + return null; + } + + return this._textEditor.saveViewState(); + } + + saveEditorViewState() { + if (this._textEditor) { + this._editorViewStates = this.saveViewState(); + } + + return this._editorViewStates; + } + + restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null) { + this._editorViewStates = editorViewStates; + } + + private restoreViewState(state: editorCommon.ICodeEditorViewState | null): void { + if (state) { + this._textEditor?.restoreViewState(state); + } + } + + addDecoration(decoration: model.IModelDeltaDecoration): string { + if (!this._textEditor) { + const id = ++this._lastDecorationId; + const decorationId = `_lazy_${this.id};${id}`; + this._resolvedDecorations.set(decorationId, { options: decoration }); + return decorationId; + } + + const result = this._textEditor.deltaDecorations([], [decoration]); + this._resolvedDecorations.set(result[0], { id: result[0], options: decoration }); + return result[0]; + } + + removeDecoration(decorationId: string) { + const realDecorationId = this._resolvedDecorations.get(decorationId); + + if (this._textEditor && realDecorationId && realDecorationId.id !== undefined) { + this._textEditor.deltaDecorations([realDecorationId.id!], []); + } + + // lastly, remove all the cache + this._resolvedDecorations.delete(decorationId); + } + + deltaDecorations(oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] { + oldDecorations.forEach(id => { + this.removeDecoration(id); + }); + + const ret = newDecorations.map(option => { + return this.addDecoration(option); + }); + + return ret; + } + + revealRangeInCenter(range: Range) { + this._textEditor?.revealRangeInCenter(range, editorCommon.ScrollType.Immediate); + } + + setSelection(range: Range) { + this._textEditor?.setSelection(range); + } + + getLineScrollTopOffset(line: number): number { + if (!this._textEditor) { + return 0; + } + + return this._textEditor.getTopForLineNumber(line) + EDITOR_TOP_PADDING + EDITOR_TOOLBAR_HEIGHT; + } + + cursorAtBoundary(): CursorAtBoundary { + if (!this._textEditor) { + return CursorAtBoundary.None; + } + + // only validate primary cursor + const selection = this._textEditor.getSelection(); + + // only validate empty cursor + if (!selection || !selection.isEmpty()) { + return CursorAtBoundary.None; + } + + // we don't allow attaching text editor without a model + const lineCnt = this._textEditor.getModel()!.getLineCount(); + + if (selection.startLineNumber === lineCnt) { + // bottom + if (selection.startLineNumber === 1) { + return CursorAtBoundary.Both; + } + else { + return CursorAtBoundary.Bottom; + } + } + + if (selection.startLineNumber === 1) { + return CursorAtBoundary.Top; + } + + return CursorAtBoundary.None; + } + + protected _buffer: model.ITextBuffer | null = null; + + protected cellStartFind(value: string): model.FindMatch[] | null { + let cellMatches: model.FindMatch[] = []; + + if (this.assertTextModelAttached()) { + cellMatches = this._textModel!.findMatches(value, false, false, false, null, false); + } else { + if (!this._buffer) { + this._buffer = this.cell.resolveTextBufferFactory().create(model.DefaultEndOfLine.LF); + } + + const lineCount = this._buffer.getLineCount(); + const fullRange = new Range(1, 1, lineCount, this._buffer.getLineLength(lineCount) + 1); + const searchParams = new SearchParams(value, false, false, null); + const searchData = searchParams.parseSearchRequest(); + + if (!searchData) { + return null; + } + + cellMatches = this._buffer.findMatchesLineByLine(fullRange, searchData, false, 1000); + } + + return cellMatches; + } + + getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata { + const editable: boolean = this.metadata?.editable === undefined + ? (documentMetadata?.cellEditable === undefined ? NotebookCellMetadataDefaults.editable : documentMetadata?.cellEditable) + : this.metadata?.editable; + + const runnable: boolean = this.metadata?.runnable === undefined + ? (documentMetadata?.cellRunnable === undefined ? NotebookCellMetadataDefaults.runnable : documentMetadata?.cellRunnable) + : this.metadata?.runnable; + + return { + editable, + runnable + }; + } + + toJSON(): any { + return { + handle: this.handle + }; + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts index 839c2b00306..85e74cabf6d 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts @@ -6,18 +6,16 @@ import { ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IResourceUndoRedoElement, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo'; import { URI } from 'vs/base/common/uri'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; - +import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; /** * It should not modify Undo/Redo stack */ export interface ICellEditingDelegate { - insertCell?(index: number, viewCell: CellViewModel): void; + insertCell?(index: number, viewCell: BaseCellViewModel): void; deleteCell?(index: number, cell: ICell): void; moveCell?(fromIndex: number, toIndex: number): void; + createCellViewModel?(cell: ICell): BaseCellViewModel; } export class InsertCellEdit implements IResourceUndoRedoElement { @@ -26,7 +24,7 @@ export class InsertCellEdit implements IResourceUndoRedoElement { constructor( public resource: URI, private insertIndex: number, - private cell: CellViewModel, + private cell: BaseCellViewModel, private editingDelegate: ICellEditingDelegate ) { } @@ -55,10 +53,8 @@ export class DeleteCellEdit implements IResourceUndoRedoElement { constructor( public resource: URI, private insertIndex: number, - cell: CellViewModel, - private editingDelegate: ICellEditingDelegate, - private instantiationService: IInstantiationService, - private notebookViewModel: NotebookViewModel + cell: BaseCellViewModel, + private editingDelegate: ICellEditingDelegate ) { this._rawCell = cell.cell; @@ -67,11 +63,11 @@ export class DeleteCellEdit implements IResourceUndoRedoElement { } undo(): void | Promise { - if (!this.editingDelegate.insertCell) { + if (!this.editingDelegate.insertCell || !this.editingDelegate.createCellViewModel) { throw new Error('Notebook Insert Cell not implemented for Undo/Redo'); } - const cell = this.instantiationService.createInstance(CellViewModel, this.notebookViewModel.viewType, this.notebookViewModel.handle, this._rawCell); + const cell = this.editingDelegate.createCellViewModel(this._rawCell); this.editingDelegate.insertCell(this.insertIndex, cell); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts new file mode 100644 index 00000000000..83b2814a5a6 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -0,0 +1,229 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import * as UUID from 'vs/base/common/uuid'; +import * as model from 'vs/editor/common/model'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; +import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CellEditState, ICellViewModel, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellKind, ICell, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { BaseCellViewModel } from './baseCellViewModel'; +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; + +export class CodeCellViewModel extends BaseCellViewModel implements ICellViewModel { + cellKind: CellKind.Code = CellKind.Code; + protected readonly _onDidChangeOutputs = new Emitter(); + readonly onDidChangeOutputs = this._onDidChangeOutputs.event; + private _outputCollection: number[] = []; + private _selfSizeMonitoring: boolean = false; + set selfSizeMonitoring(newVal: boolean) { + this._selfSizeMonitoring = newVal; + } + + get selfSizeMonitoring() { + return this._selfSizeMonitoring; + } + + private _outputsTop: PrefixSumComputer | null = null; + get outputs() { + return this.cell.outputs; + } + + private readonly _onDidChangeContent: Emitter = this._register(new Emitter()); + public readonly onDidChangeContent: Event = this._onDidChangeContent.event; + + protected readonly _onDidChangeLayout = new Emitter(); + readonly onDidChangeLayout = this._onDidChangeLayout.event; + + private _editorHeight = 0; + set editorHeight(height: number) { + this._editorHeight = height; + + this.layoutChange({ editorHeight: true }); + } + + get editorHeight() { + return this._editorHeight; + } + + private _layoutInfo: CodeCellLayoutInfo; + + get layoutInfo() { + return this._layoutInfo; + } + + constructor( + readonly viewType: string, + readonly notebookHandle: number, + readonly cell: ICell, + readonly eventDispatcher: NotebookEventDispatcher, + @ITextModelService private readonly _modelService: ITextModelService, + ) { + super(viewType, notebookHandle, cell, UUID.generateUuid()); + if (this.cell.onDidChangeOutputs) { + this._register(this.cell.onDidChangeOutputs((splices) => { + this._outputCollection = new Array(this.cell.outputs.length); + this._outputsTop = null; + this._onDidChangeOutputs.fire(splices); + })); + } + + this._outputCollection = new Array(this.cell.outputs.length); + this._buffer = null; + + this._layoutInfo = { + fontInfo: null, + editorHeight: 0, + editorWidth: 0, + outputTotalHeight: 0, + totalHeight: 0, + indicatorHeight: 0 + }; + + this._register(eventDispatcher.onDidChangeLayout((e) => { + if (e.source.width !== undefined) { + this.layoutChange({ outerWidth: e.value.width, font: e.value.fontInfo }); + } + })); + } + + layoutChange(state: CodeCellLayoutChangeEvent) { + // recompute + this._ensureOutputsTop(); + const outputTotalHeight = this._outputsTop!.getTotalValue(); + const totalHeight = this.outputs.length + ? EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + 16 + outputTotalHeight + : EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + outputTotalHeight; + const indicatorHeight = totalHeight - EDITOR_TOOLBAR_HEIGHT - 16; + const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH : 0; + this._layoutInfo = { + fontInfo: state.font || null, + editorHeight: this._editorHeight, + editorWidth, + outputTotalHeight, + totalHeight, + indicatorHeight + }; + + if (state.editorHeight || state.outputHeight) { + state.totalHeight = true; + } + + this._onDidChangeLayout.fire(state); + } + + hasDynamicHeight() { + if (this.selfSizeMonitoring) { + // if there is an output rendered in the webview, it should always be false + return false; + } + + if (this.outputs && this.outputs.length > 0) { + // if it contains output, it will be marked as dynamic height + // thus when it's being rendered, the list view will `probeHeight` + // inside which, we will check domNode's height directly instead of doing another `renderElement` with height undefined. + return true; + } + else { + return false; + } + } + + getHeight(lineHeight: number) { + return this.lineCount * lineHeight + 16 + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; + } + + save() { + if (this._textModel && !this._textModel.isDisposed() && this.editState === CellEditState.Editing) { + let cnt = this._textModel.getLineCount(); + this.cell.source = this._textModel.getLinesContent().map((str, index) => str + (index !== cnt - 1 ? '\n' : '')); + } + } + + async resolveTextModel(): Promise { + if (!this._textModel) { + const ref = await this._modelService.createModelReference(this.cell.uri); + this._textModel = ref.object.textEditorModel; + this._buffer = this._textModel.getTextBuffer(); + this._register(ref); + this._register(this._textModel.onDidChangeContent(() => { + this.cell.contentChange(); + this._onDidChangeContent.fire(); + })); + } + + return this._textModel; + } + + onDeselect() { + this.editState = CellEditState.Preview; + } + + updateOutputHeight(index: number, height: number) { + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + this._outputCollection[index] = height; + this._ensureOutputsTop(); + this._outputsTop!.changeValue(index, height); + this.layoutChange({ outputHeight: true }); + } + + getOutputOffset(index: number): number { + if (index >= this._outputCollection.length) { + throw new Error('Output index out of range!'); + } + + this._ensureOutputsTop(); + + return this._outputsTop!.getAccumulatedValue(index - 1); + } + + spliceOutputHeights(start: number, deleteCnt: number, heights: number[]) { + this._ensureOutputsTop(); + + this._outputsTop!.removeValues(start, deleteCnt); + if (heights.length) { + const values = new Uint32Array(heights.length); + for (let i = 0; i < heights.length; i++) { + values[i] = heights[i]; + } + + this._outputsTop!.insertValues(start, values); + } + + this.layoutChange({ outputHeight: true }); + } + + private _ensureOutputsTop(): void { + if (!this._outputsTop) { + const values = new Uint32Array(this._outputCollection.length); + for (let i = 0; i < this._outputCollection.length; i++) { + values[i] = this._outputCollection[i]; + } + + this._outputsTop = new PrefixSumComputer(values); + } + } + + private readonly _hasFindResult = this._register(new Emitter()); + public readonly hasFindResult: Event = this._hasFindResult.event; + + startFind(value: string): CellFindMatch | null { + const matches = super.cellStartFind(value); + + if (matches === null) { + return null; + } + + return { + cell: this, + matches + }; + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts new file mode 100644 index 00000000000..e67499fa1d6 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter } from 'vs/base/common/event'; +import { NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookLayoutChangeEvent, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; + +export enum NotebookViewEventType { + LayoutChanged = 1, + MetadataChanged = 2 +} + +export class NotebookLayoutChangedEvent { + public readonly type = NotebookViewEventType.LayoutChanged; + + constructor(readonly source: NotebookLayoutChangeEvent, readonly value: NotebookLayoutInfo) { + + } +} + + +export class NotebookMetadataChangedEvent { + public readonly type = NotebookViewEventType.MetadataChanged; + + constructor(readonly source: NotebookDocumentMetadata) { + + } +} + + +export type NotebookViewEvent = NotebookLayoutChangedEvent | NotebookMetadataChangedEvent; + +export class NotebookEventDispatcher { + protected readonly _onDidChangeLayout = new Emitter(); + readonly onDidChangeLayout = this._onDidChangeLayout.event; + protected readonly _onDidChangeMetadata = new Emitter(); + readonly onDidChangeMetadata = this._onDidChangeMetadata.event; + + constructor() { + } + + emit(events: NotebookViewEvent[]) { + for (let i = 0, len = events.length; i < len; i++) { + let e = events[i]; + + switch (e.type) { + case NotebookViewEventType.LayoutChanged: + this._onDidChangeLayout.fire(e); + break; + case NotebookViewEventType.MetadataChanged: + this._onDidChangeMetadata.fire(e); + break; + } + } + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts new file mode 100644 index 00000000000..33dfdae7ea5 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import * as UUID from 'vs/base/common/uuid'; +import * as model from 'vs/editor/common/model'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ICellViewModel, CellFindMatch, MarkdownCellLayoutInfo, MarkdownCellLayoutChangeEvent, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; +import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel'; +import { CellKind, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; + +export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel { + cellKind: CellKind.Markdown = CellKind.Markdown; + private _mdRenderer: MarkdownRenderer | null = null; + private _html: HTMLElement | null = null; + private readonly _onDidChangeContent: Emitter = this._register(new Emitter()); + public readonly onDidChangeContent: Event = this._onDidChangeContent.event; + + private _layoutInfo: MarkdownCellLayoutInfo; + + get layoutInfo() { + return this._layoutInfo; + } + + protected readonly _onDidChangeLayout = new Emitter(); + readonly onDidChangeLayout = this._onDidChangeLayout.event; + + constructor( + readonly viewType: string, + readonly notebookHandle: number, + readonly cell: ICell, + readonly eventDispatcher: NotebookEventDispatcher, + @IInstantiationService private readonly _instaService: IInstantiationService, + @ITextModelService private readonly _modelService: ITextModelService) { + super(viewType, notebookHandle, cell, UUID.generateUuid()); + + this._layoutInfo = { + fontInfo: null, + editorWidth: 0 + }; + + this._register(eventDispatcher.onDidChangeLayout((e) => { + if (e.source.width || e.source.fontInfo) { + this.layoutChange({ outerWidth: e.value.width, font: e.value.fontInfo }); + } + })); + } + + layoutChange(state: MarkdownCellLayoutChangeEvent) { + // recompute + const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 : 0; + + this._layoutInfo = { + fontInfo: state.font || null, + editorWidth + }; + + this._onDidChangeLayout.fire(state); + } + + hasDynamicHeight() { + return true; + } + + getHeight(lineHeight: number) { + return 100; + } + + setText(strs: string[]) { + this.cell.source = strs; + this._html = null; + } + + save() { + if (this._textModel && !this._textModel.isDisposed() && this.editState === CellEditState.Editing) { + let cnt = this._textModel.getLineCount(); + this.cell.source = this._textModel.getLinesContent().map((str, index) => str + (index !== cnt - 1 ? '\n' : '')); + } + } + + getHTML(): HTMLElement | null { + if (this.cellKind === CellKind.Markdown) { + if (this._html) { + return this._html; + } + let renderer = this.getMarkdownRenderer(); + this._html = renderer.render({ value: this.getText(), isTrusted: true }).element; + return this._html; + } + return null; + } + + async resolveTextModel(): Promise { + if (!this._textModel) { + const ref = await this._modelService.createModelReference(this.cell.uri); + this._textModel = ref.object.textEditorModel; + this._buffer = this._textModel.getTextBuffer(); + this._register(ref); + this._register(this._textModel.onDidChangeContent(() => { + this.cell.contentChange(); + this._html = null; + this._onDidChangeContent.fire(); + })); + } + return this._textModel; + } + + onDeselect() { + this.editState = CellEditState.Preview; + } + + getMarkdownRenderer() { + if (!this._mdRenderer) { + this._mdRenderer = this._instaService.createInstance(MarkdownRenderer); + } + return this._mdRenderer; + } + + private readonly _hasFindResult = this._register(new Emitter()); + public readonly hasFindResult: Event = this._hasFindResult.event; + + startFind(value: string): CellFindMatch | null { + const matches = super.cellStartFind(value); + + if (matches === null) { + return null; + } + + return { + cell: this, + matches + }; + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel.ts deleted file mode 100644 index cfbe176b7dc..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel.ts +++ /dev/null @@ -1,532 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; -import * as UUID from 'vs/base/common/uuid'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { Range } from 'vs/editor/common/core/range'; -import * as editorCommon from 'vs/editor/common/editorCommon'; -import * as model from 'vs/editor/common/model'; -import { SearchParams } from 'vs/editor/common/model/textModelSearch'; -import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; -import { CellKind, ICell, IOutput, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { CellFindMatch, CellState, CursorAtBoundary, CellFocusMode, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants'; - -export class CellViewModel extends Disposable implements ICellViewModel { - - private _mdRenderer: MarkdownRenderer | null = null; - private _html: HTMLElement | null = null; - protected readonly _onDidDispose = new Emitter(); - readonly onDidDispose = this._onDidDispose.event; - protected readonly _onDidChangeCellState = new Emitter(); - readonly onDidChangeCellState = this._onDidChangeCellState.event; - protected readonly _onDidChangeFocusMode = new Emitter(); - readonly onDidChangeFocusMode = this._onDidChangeFocusMode.event; - protected readonly _onDidChangeOutputs = new Emitter(); - readonly onDidChangeOutputs = this._onDidChangeOutputs.event; - - protected readonly _onDidChangeTotalHeight = new Emitter(); - readonly onDidChangeTotalHeight = this._onDidChangeTotalHeight.event; - private _outputCollection: number[] = []; - protected _outputsTop: PrefixSumComputer | null = null; - - get handle() { - return this.cell.handle; - } - - get uri() { - return this.cell.uri; - } - - get cellKind() { - return this.cell.cellKind; - } - get lineCount() { - return this.cell.source.length; - } - get outputs() { - return this.cell.outputs; - } - - get metadata() { - return this.cell.metadata; - } - - private _state: CellState = CellState.Preview; - - get state(): CellState { - return this._state; - } - - set state(newState: CellState) { - if (newState === this._state) { - return; - } - - this._state = newState; - this._onDidChangeCellState.fire(); - } - - private _focusMode: CellFocusMode = CellFocusMode.Container; - - get focusMode() { - return this._focusMode; - } - - set focusMode(newMode: CellFocusMode) { - this._focusMode = newMode; - this._onDidChangeFocusMode.fire(); - } - - private _selfSizeMonitoring: boolean = false; - - set selfSizeMonitoring(newVal: boolean) { - this._selfSizeMonitoring = newVal; - } - - get selfSizeMonitoring() { - return this._selfSizeMonitoring; - } - - private _editorHeight = 0; - set editorHeight(height: number) { - this._editorHeight = height; - this._onDidChangeTotalHeight.fire(); - } - - get editorHeight(): number { - return this._editorHeight; - } - - protected readonly _onDidChangeEditorAttachState = new Emitter(); - readonly onDidChangeEditorAttachState = this._onDidChangeEditorAttachState.event; - - get editorAttached(): boolean { - return !!this._textEditor; - } - - private _textModel?: model.ITextModel; - private _textEditor?: ICodeEditor; - private _buffer: model.ITextBuffer | null; - private _editorViewStates: editorCommon.ICodeEditorViewState | null; - private _lastDecorationId: number = 0; - private _resolvedDecorations = new Map(); - private readonly _onDidChangeContent: Emitter = this._register(new Emitter()); - public readonly onDidChangeContent: Event = this._onDidChangeContent.event; - private readonly _onDidChangeCursorSelection: Emitter = this._register(new Emitter()); - public readonly onDidChangeCursorSelection: Event = this._onDidChangeCursorSelection.event; - - private _cursorChangeListener: IDisposable | null = null; - - readonly id: string = UUID.generateUuid(); - - constructor( - readonly viewType: string, - readonly notebookHandle: number, - readonly cell: ICell, - @IInstantiationService private readonly _instaService: IInstantiationService, - @ITextModelService private readonly _modelService: ITextModelService, - ) { - super(); - if (this.cell.onDidChangeOutputs) { - this._register(this.cell.onDidChangeOutputs((splices) => { - this._outputCollection = new Array(this.cell.outputs.length); - this._outputsTop = null; - this._onDidChangeOutputs.fire(splices); - })); - } - - this._outputCollection = new Array(this.cell.outputs.length); - this._buffer = null; - this._editorViewStates = null; - } - - restoreEditorViewState(editorViewStates: editorCommon.ICodeEditorViewState | null) { - this._editorViewStates = editorViewStates; - } - - saveEditorViewState() { - if (this._textEditor) { - this._editorViewStates = this.saveViewState(); - } - - return this._editorViewStates; - } - - - //#region Search - private readonly _hasFindResult = this._register(new Emitter()); - public readonly hasFindResult: Event = this._hasFindResult.event; - - startFind(value: string): CellFindMatch | null { - let cellMatches: model.FindMatch[] = []; - - if (this.assertTextModelAttached()) { - cellMatches = this._textModel!.findMatches(value, false, false, false, null, false); - } else { - if (!this._buffer) { - this._buffer = this.cell.resolveTextBufferFactory().create(model.DefaultEndOfLine.LF); - } - - const lineCount = this._buffer.getLineCount(); - const fullRange = new Range(1, 1, lineCount, this._buffer.getLineLength(lineCount) + 1); - const searchParams = new SearchParams(value, false, false, null); - const searchData = searchParams.parseSearchRequest(); - - if (!searchData) { - return null; - } - - cellMatches = this._buffer.findMatchesLineByLine(fullRange, searchData, false, 1000); - } - - return { - cell: this, - matches: cellMatches - }; - } - - assertTextModelAttached(): boolean { - if (this._textModel && this._textEditor && this._textEditor.getModel() === this._textModel) { - return true; - } - - return false; - } - - private saveViewState(): editorCommon.ICodeEditorViewState | null { - if (!this._textEditor) { - return null; - } - - return this._textEditor.saveViewState(); - } - - - private restoreViewState(state: editorCommon.ICodeEditorViewState | null): void { - if (state) { - this._textEditor?.restoreViewState(state); - } - } - - //#endregion - - hasDynamicHeight() { - if (this.selfSizeMonitoring) { - // if there is an output rendered in the webview, it should always be false - return false; - } - - if (this.cellKind === CellKind.Code) { - if (this.outputs && this.outputs.length > 0) { - // if it contains output, it will be marked as dynamic height - // thus when it's being rendered, the list view will `probeHeight` - // inside which, we will check domNode's height directly instead of doing another `renderElement` with height undefined. - return true; - } - else { - return false; - } - } - - return true; - } - - getHeight(lineHeight: number) { - if (this.cellKind === CellKind.Markdown) { - return 100; - } - else { - return this.lineCount * lineHeight + 16 + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING; - } - } - setText(strs: string[]) { - this.cell.source = strs; - this._html = null; - } - - save() { - if (this._textModel && !this._textModel.isDisposed() && this.state === CellState.Editing) { - let cnt = this._textModel.getLineCount(); - this.cell.source = this._textModel.getLinesContent().map((str, index) => str + (index !== cnt - 1 ? '\n' : '')); - } - } - getText(): string { - if (this._textModel) { - return this._textModel.getValue(); - } - - return this.cell.source.join('\n'); - } - - getHTML(): HTMLElement | null { - if (this.cellKind === CellKind.Markdown) { - if (this._html) { - return this._html; - } - let renderer = this.getMarkdownRenderer(); - this._html = renderer.render({ value: this.getText(), isTrusted: true }).element; - return this._html; - } - return null; - } - - async resolveTextModel(): Promise { - if (!this._textModel) { - const ref = await this._modelService.createModelReference(this.cell.uri); - this._textModel = ref.object.textEditorModel; - this._buffer = this._textModel.getTextBuffer(); - this._register(ref); - this._register(this._textModel.onDidChangeContent(() => { - this.cell.contentChange(); - this._html = null; - this._onDidChangeContent.fire(); - })); - } - return this._textModel; - } - - attachTextEditor(editor: ICodeEditor) { - if (!editor.hasModel()) { - throw new Error('Invalid editor: model is missing'); - } - - if (this._textEditor === editor) { - if (this._cursorChangeListener === null) { - this._cursorChangeListener = this._textEditor.onDidChangeCursorSelection(() => this._onDidChangeCursorSelection.fire()); - this._onDidChangeCursorSelection.fire(); - } - return; - } - - this._textEditor = editor; - - if (this._editorViewStates) { - this.restoreViewState(this._editorViewStates); - } - - this._resolvedDecorations.forEach((value, key) => { - if (key.startsWith('_lazy_')) { - // lazy ones - - const ret = this._textEditor!.deltaDecorations([], [value.options]); - this._resolvedDecorations.get(key)!.id = ret[0]; - } else { - const ret = this._textEditor!.deltaDecorations([], [value.options]); - this._resolvedDecorations.get(key)!.id = ret[0]; - } - }); - - this._cursorChangeListener = this._textEditor.onDidChangeCursorSelection(() => this._onDidChangeCursorSelection.fire()); - this._onDidChangeCursorSelection.fire(); - this._onDidChangeEditorAttachState.fire(true); - } - - detachTextEditor() { - this._editorViewStates = this.saveViewState(); - - // decorations need to be cleared first as editors can be resued. - this._resolvedDecorations.forEach(value => { - let resolvedid = value.id; - - if (resolvedid) { - this._textEditor?.deltaDecorations([resolvedid], []); - } - }); - this._textEditor = undefined; - this._cursorChangeListener?.dispose(); - this._cursorChangeListener = null; - this._onDidChangeEditorAttachState.fire(false); - } - - revealRangeInCenter(range: Range) { - this._textEditor?.revealRangeInCenter(range, editorCommon.ScrollType.Immediate); - } - - setSelection(range: Range) { - this._textEditor?.setSelection(range); - } - - getLineScrollTopOffset(line: number): number { - if (!this._textEditor) { - return 0; - } - - return this._textEditor.getTopForLineNumber(line) + EDITOR_TOP_PADDING + EDITOR_TOOLBAR_HEIGHT; - } - - addDecoration(decoration: model.IModelDeltaDecoration): string { - if (!this._textEditor) { - const id = ++this._lastDecorationId; - const decorationId = `_lazy_${this.id};${id}`; - - this._resolvedDecorations.set(decorationId, { options: decoration }); - return decorationId; - } - - const result = this._textEditor.deltaDecorations([], [decoration]); - this._resolvedDecorations.set(result[0], { id: result[0], options: decoration }); - - return result[0]; - } - - removeDecoration(decorationId: string) { - const realDecorationId = this._resolvedDecorations.get(decorationId); - - if (this._textEditor && realDecorationId && realDecorationId.id !== undefined) { - this._textEditor.deltaDecorations([realDecorationId.id!], []); - } - - // lastly, remove all the cache - this._resolvedDecorations.delete(decorationId); - } - - deltaDecorations(oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] { - oldDecorations.forEach(id => { - this.removeDecoration(id); - }); - - const ret = newDecorations.map(option => { - return this.addDecoration(option); - }); - - return ret; - } - - onDeselect() { - this.state = CellState.Preview; - } - - cursorAtBoundary(): CursorAtBoundary { - if (!this._textEditor) { - return CursorAtBoundary.None; - } - - // only validate primary cursor - const selection = this._textEditor.getSelection(); - - // only validate empty cursor - if (!selection || !selection.isEmpty()) { - return CursorAtBoundary.None; - } - - // we don't allow attaching text editor without a model - const lineCnt = this._textEditor.getModel()!.getLineCount(); - - if (selection.startLineNumber === lineCnt) { - // bottom - - if (selection.startLineNumber === 1) { - return CursorAtBoundary.Both; - } else { - return CursorAtBoundary.Bottom; - } - } - - if (selection.startLineNumber === 1) { - return CursorAtBoundary.Top; - } - - return CursorAtBoundary.None; - } - - getMarkdownRenderer() { - if (!this._mdRenderer) { - this._mdRenderer = this._instaService.createInstance(MarkdownRenderer); - } - return this._mdRenderer; - } - - updateOutputHeight(index: number, height: number) { - if (index >= this._outputCollection.length) { - throw new Error('Output index out of range!'); - } - - this._outputCollection[index] = height; - this._ensureOutputsTop(); - this._outputsTop!.changeValue(index, height); - this._onDidChangeTotalHeight.fire(); - } - - getOutputOffset(index: number): number { - if (index >= this._outputCollection.length) { - throw new Error('Output index out of range!'); - } - - this._ensureOutputsTop(); - - return this._outputsTop!.getAccumulatedValue(index - 1); - } - - getOutputHeight(output: IOutput): number | undefined { - let index = this.cell.outputs.indexOf(output); - - if (index < 0) { - return undefined; - } - - if (index < this._outputCollection.length) { - return this._outputCollection[index]; - } - - return undefined; - } - - private getOutputTotalHeight(): number { - this._ensureOutputsTop(); - - return this._outputsTop!.getTotalValue(); - } - - spliceOutputHeights(start: number, deleteCnt: number, heights: number[]) { - this._ensureOutputsTop(); - - this._outputsTop!.removeValues(start, deleteCnt); - if (heights.length) { - const values = new Uint32Array(heights.length); - for (let i = 0; i < heights.length; i++) { - values[i] = heights[i]; - } - - this._outputsTop!.insertValues(start, values); - } - - this._onDidChangeTotalHeight.fire(); - } - - getCellTotalHeight(): number { - if (this.outputs.length) { - return EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + 16 + this.getOutputTotalHeight(); - } else { - return EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + this.getOutputTotalHeight(); - } - } - - getIndicatorHeight(): number { - return this.getCellTotalHeight() - EDITOR_TOOLBAR_HEIGHT - 16; - } - - protected _ensureOutputsTop(): void { - if (!this._outputsTop) { - const values = new Uint32Array(this._outputCollection.length); - for (let i = 0; i < this._outputCollection.length; i++) { - values[i] = this._outputCollection[i]; - } - - this._outputsTop = new PrefixSumComputer(values); - } - } - - toJSON(): any { - return { - handle: this.handle - }; - } -} diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 1fabc77efa0..8acd6c15f1e 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -3,22 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import * as editorCommon from 'vs/editor/common/editorCommon'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; -import { ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { IModelDeltaDecoration } from 'vs/editor/common/model'; -import { onUnexpectedError } from 'vs/base/common/errors'; -import { CellFindMatch, CellState, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { URI } from 'vs/base/common/uri'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { Range } from 'vs/editor/common/core/range'; +import * as editorCommon from 'vs/editor/common/editorCommon'; +import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { WorkspaceTextEdit } from 'vs/editor/common/modes'; -import { URI } from 'vs/base/common/uri'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -import { InsertCellEdit, DeleteCellEdit, MoveCellEdit } from 'vs/workbench/contrib/notebook/browser/viewModel/cellEdit'; +import { CellFindMatch, CellEditState, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; +import { DeleteCellEdit, InsertCellEdit, MoveCellEdit } from 'vs/workbench/contrib/notebook/browser/viewModel/cellEdit'; +import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; +import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; +import { CellKind, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; export interface INotebookEditorViewState { editingCells: { [key: number]: boolean }; @@ -100,6 +102,7 @@ export class NotebookViewModel extends Disposable { constructor( public viewType: string, private _model: NotebookEditorModel, + readonly eventDispatcher: NotebookEventDispatcher, @IInstantiationService private readonly instantiationService: IInstantiationService, @IBulkEditService private readonly bulkEditService: IBulkEditService, @IUndoRedoService private readonly undoService: IUndoRedoService @@ -110,15 +113,19 @@ export class NotebookViewModel extends Disposable { this._onDidChangeViewCells.fire({ synchronous: true, splices: e.map(splice => { - return [splice[0], splice[1], splice[2].map(cell => this.instantiationService.createInstance(CellViewModel, this.viewType, this.handle, cell))]; + return [splice[0], splice[1], splice[2].map(cell => { + return createCellViewModel(this.instantiationService, this, cell); + })]; }) }); })); + this._register(this._model.notebook.onDidChangeMetadata(e => { + this.eventDispatcher.emit([new NotebookMetadataChangedEvent(e)]); + })); + this._viewCells = this._model!.notebook!.cells.map(cell => { - const viewCell = this.instantiationService.createInstance(CellViewModel, this.viewType, this._model!.notebook!.handle, cell); - this._localStore.add(viewCell); - return viewCell; + return createCellViewModel(this.instantiationService, this, cell); }); } @@ -129,7 +136,7 @@ export class NotebookViewModel extends Disposable { hide() { this._viewCells.forEach(cell => { if (cell.getText() !== '') { - cell.state = CellState.Preview; + cell.editState = CellEditState.Preview; } }); } @@ -152,7 +159,7 @@ export class NotebookViewModel extends Disposable { } insertCell(index: number, cell: ICell, synchronous: boolean): CellViewModel { - const newCell = this.instantiationService.createInstance(CellViewModel, this.viewType, this.handle, cell); + let newCell: CellViewModel = createCellViewModel(this.instantiationService, this, cell); this._viewCells!.splice(index, 0, newCell); this._model.insertCell(newCell.cell, index); this._localStore.add(newCell); @@ -172,8 +179,11 @@ export class NotebookViewModel extends Disposable { this.undoService.pushElement(new DeleteCellEdit(this.uri, index, viewCell, { insertCell: this._insertCellDelegate.bind(this), - deleteCell: this._deleteCellDelegate.bind(this) - }, this.instantiationService, this)); + deleteCell: this._deleteCellDelegate.bind(this), + createCellViewModel: (cell: ICell) => { + return createCellViewModel(this.instantiationService, this, cell); + } + })); this._onDidChangeViewCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); viewCell.dispose(); @@ -207,7 +217,7 @@ export class NotebookViewModel extends Disposable { saveEditorViewState(): INotebookEditorViewState { const state: { [key: number]: boolean } = {}; - this._viewCells.filter(cell => cell.state === CellState.Editing).forEach(cell => state[cell.cell.handle] = true); + this._viewCells.filter(cell => cell.editState === CellEditState.Editing).forEach(cell => state[cell.cell.handle] = true); const editorViewStates: { [key: number]: editorCommon.ICodeEditorViewState } = {}; this._viewCells.map(cell => ({ handle: cell.cell.handle, state: cell.saveEditorViewState() })).forEach(viewState => { if (viewState.state) { @@ -230,7 +240,7 @@ export class NotebookViewModel extends Disposable { const isEditing = viewState.editingCells && viewState.editingCells[cell.handle]; const editorViewState = viewState.editorViewStates && viewState.editorViewStates[cell.handle]; - cell.state = isEditing ? CellState.Editing : CellState.Preview; + cell.editState = isEditing ? CellEditState.Editing : CellEditState.Preview; cell.restoreEditorViewState(editorViewState); }); } @@ -382,3 +392,13 @@ export class NotebookViewModel extends Disposable { super.dispose(); } } + +export type CellViewModel = CodeCellViewModel | MarkdownCellViewModel; + +export function createCellViewModel(instantiationService: IInstantiationService, notebookViewModel: NotebookViewModel, cell: ICell) { + if (cell.cellKind === CellKind.Code) { + return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, notebookViewModel.handle, cell, notebookViewModel.eventDispatcher); + } else { + return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, notebookViewModel.handle, cell, notebookViewModel.eventDispatcher); + } +} diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index e11f76aadb7..9c920405eda 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; -import { ICell, IOutput, NotebookCellOutputsSplice, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ICell, IOutput, NotebookCellOutputsSplice, CellKind, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { PieceTreeTextBufferFactory, PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; import { URI } from 'vs/base/common/uri'; @@ -15,6 +15,9 @@ export class NotebookCellTextModel implements ICell { private _onDidChangeContent = new Emitter(); onDidChangeContent: Event = this._onDidChangeContent.event; + private _onDidChangeMetadata = new Emitter(); + onDidChangeMetadata: Event = this._onDidChangeMetadata.event; + private _outputs: IOutput[]; get outputs(): IOutput[] { @@ -30,6 +33,17 @@ export class NotebookCellTextModel implements ICell { this._buffer = null; } + private _metadata: NotebookCellMetadata | undefined; + + get metadata() { + return this._metadata; + } + + set metadata(newMetadata: NotebookCellMetadata | undefined) { + this._metadata = newMetadata; + this._onDidChangeMetadata.fire(this._metadata); + } + private _buffer: PieceTreeTextBufferFactory | null = null; constructor( @@ -38,9 +52,11 @@ export class NotebookCellTextModel implements ICell { private _source: string[], public language: string, public cellKind: CellKind, - outputs: IOutput[] + outputs: IOutput[], + metadata: NotebookCellMetadata | undefined ) { this._outputs = outputs; + this._metadata = metadata; } contentChange() { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index ccce0be30a4..c2945fc41fd 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -7,7 +7,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellsSplice, NotebookDocumentMetadata, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class NotebookTextModel extends Disposable implements INotebookTextModel { private readonly _onWillDispose: Emitter = this._register(new Emitter()); @@ -16,12 +16,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel get onDidChangeCells(): Event { return this._onDidChangeCells.event; } private _onDidChangeContent = new Emitter(); onDidChangeContent: Event = this._onDidChangeContent.event; + private _onDidChangeMetadata = new Emitter(); + onDidChangeMetadata: Event = this._onDidChangeMetadata.event; private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; - activeCell: NotebookCellTextModel | undefined; languages: string[] = []; - metadata: NotebookDocumentMetadata | undefined = undefined; + metadata: NotebookDocumentMetadata | undefined = { editable: true }; renderers = new Set(); constructor( @@ -37,8 +38,17 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.languages = languages; } - updateNotebookMetadata(metadata: NotebookDocumentMetadata | undefined) { + updateNotebookMetadata(metadata: NotebookDocumentMetadata) { this.metadata = metadata; + this._onDidChangeMetadata.fire(this.metadata); + } + + updateNotebookCellMetadata(handle: number, metadata: NotebookCellMetadata) { + const cell = this.cells.find(cell => cell.handle === handle); + + if (cell) { + cell.metadata = metadata; + } } updateRenderers(renderers: number[]) { @@ -47,10 +57,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }); } - updateActiveCell(handle: number) { - this.activeCell = this._mapping.get(handle); - } - insertNewCell(index: number, cell: NotebookCellTextModel): void { this._mapping.set(cell.handle, cell); this.cells.splice(index, 0, cell); @@ -77,7 +83,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel splices.reverse().forEach(splice => { let cellDtos = splice[2]; let newCells = cellDtos.map(cell => { - let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs || []); + let mainCell = new NotebookCellTextModel(URI.revive(cell.uri), cell.handle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata); this._mapping.set(cell.handle, mainCell); let dirtyStateListener = mainCell.onDidChangeContent(() => { this._onDidChangeContent.fire(); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index a76f4cc9392..cef539f748f 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -38,10 +38,13 @@ export const NOTEBOOK_DISPLAY_ORDER = [ export interface NotebookDocumentMetadata { editable: boolean; + cellEditable?: boolean; + cellRunnable?: boolean; } export interface NotebookCellMetadata { - editable: boolean; + editable?: boolean; + runnable?: boolean; } export interface INotebookDisplayOrder { @@ -132,6 +135,7 @@ export interface ICell { outputs: IOutput[]; metadata?: NotebookCellMetadata; onDidChangeOutputs?: Event; + onDidChangeMetadata: Event; resolveTextBufferFactory(): PieceTreeTextBufferFactory; // TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel contentChange(): void; diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index 9cc8e077e65..2a423d24a0b 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -13,6 +13,7 @@ import { withTestNotebook, TestCell } from 'vs/workbench/contrib/notebook/test/t import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; suite('NotebookViewModel', () => { const instantiationService = new TestInstantiationService(); @@ -23,7 +24,8 @@ suite('NotebookViewModel', () => { test('ctor', function () { const notebook = new NotebookTextModel(0, 'notebook', URI.parse('test')); const model = new NotebookEditorModel(notebook); - const viewModel = new NotebookViewModel('notebook', model, instantiationService, blukEditService, undoRedoService); + const eventDispatcher = new NotebookEventDispatcher(); + const viewModel = new NotebookViewModel('notebook', model, eventDispatcher, instantiationService, blukEditService, undoRedoService); assert.equal(viewModel.viewType, 'notebook'); }); @@ -33,10 +35,13 @@ suite('NotebookViewModel', () => { blukEditService, undoRedoService, [ - [['var a = 1;'], 'javascript', CellKind.Code, []], - [['var b = 2;'], 'javascript', CellKind.Code, []] + [['var a = 1;'], 'javascript', CellKind.Code, [], { editable: true }], + [['var b = 2;'], 'javascript', CellKind.Code, [], { editable: false }] ], (editor, viewModel) => { + assert.equal(viewModel.viewCells[0].metadata?.editable, true); + assert.equal(viewModel.viewCells[1].metadata?.editable, false); + const cell = viewModel.insertCell(1, new TestCell(viewModel.viewType, 0, ['var c = 3;'], 'javascript', CellKind.Code, []), true); assert.equal(viewModel.viewCells.length, 3); assert.equal(viewModel.notebookDocument.cells.length, 3); @@ -56,8 +61,8 @@ suite('NotebookViewModel', () => { blukEditService, undoRedoService, [ - [['var a = 1;'], 'javascript', CellKind.Code, []], - [['var b = 2;'], 'javascript', CellKind.Code, []] + [['var a = 1;'], 'javascript', CellKind.Code, [], { editable: true }], + [['var b = 2;'], 'javascript', CellKind.Code, [], { editable: true }] ], (editor, viewModel) => { const firstViewCell = viewModel.viewCells[0]; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 86198b35b2c..ed4e270a817 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -6,12 +6,11 @@ import { Emitter, Event } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; -import { CellKind, ICell, IOutput, NotebookCellOutputsSplice, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { NotebookViewModel, IModelDecorationsChangeAccessor } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { CellKind, ICell, IOutput, NotebookCellOutputsSplice, CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookViewModel, IModelDecorationsChangeAccessor, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; -import { INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, NotebookLayoutInfo, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; @@ -20,13 +19,21 @@ import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; export class TestCell implements ICell { uri: URI; private _onDidChangeOutputs = new Emitter(); onDidChangeOutputs: Event = this._onDidChangeOutputs.event; + private _onDidChangeMetadata = new Emitter(); + onDidChangeMetadata: Event = this._onDidChangeMetadata.event; private _isDirty: boolean = false; private _outputs: IOutput[]; + + get metadata(): NotebookCellMetadata { + return { editable: true }; + } + get outputs(): IOutput[] { return this._outputs; } @@ -69,6 +76,10 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + executeNotebookCell(cell: ICellViewModel): Promise { + throw new Error('Method not implemented.'); + } + isNotebookEditor = true; postMessage(message: any): void { @@ -179,20 +190,21 @@ export class TestNotebookEditor implements INotebookEditor { } } -export function createTestCellViewModel(instantiationService: IInstantiationService, viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cellKind: CellKind, outputs: IOutput[]) { - const mockCell = new TestCell(viewType, cellhandle, source, language, cellKind, outputs); - return instantiationService.createInstance(CellViewModel, viewType, notebookHandle, mockCell); -} +// export function createTestCellViewModel(instantiationService: IInstantiationService, viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cellKind: CellKind, outputs: IOutput[]) { +// const mockCell = new TestCell(viewType, cellhandle, source, language, cellKind, outputs); +// return createCellViewModel(instantiationService, viewType, notebookHandle, mockCell); +// } -export function withTestNotebook(instantiationService: IInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string[], string, CellKind, IOutput[]][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel) => void) { +export function withTestNotebook(instantiationService: IInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string[], string, CellKind, IOutput[], NotebookCellMetadata][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel) => void) { const viewType = 'notebook'; const editor = new TestNotebookEditor(); const notebook = new NotebookTextModel(0, viewType, URI.parse('test')); notebook.cells = cells.map((cell, index) => { - return new NotebookCellTextModel(notebook.uri, index, cell[0], cell[1], cell[2], cell[3]); + return new NotebookCellTextModel(notebook.uri, index, cell[0], cell[1], cell[2], cell[3], cell[4]); }); const model = new NotebookEditorModel(notebook); - const viewModel = new NotebookViewModel(viewType, model, instantiationService, blukEditService, undoRedoService); + const eventDispatcher = new NotebookEventDispatcher(); + const viewModel = new NotebookViewModel(viewType, model, eventDispatcher, instantiationService, blukEditService, undoRedoService); callback(editor, viewModel); diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index d1d96f732da..14fb8d60eff 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -32,7 +32,7 @@ import { KeybindingsEditor } from 'vs/workbench/contrib/preferences/browser/keyb import { ConfigureLanguageBasedSettingsAction, OpenDefaultKeybindingsFileAction, OpenFolderSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenGlobalSettingsAction, OpenRawDefaultSettingsAction, OpenRemoteSettingsAction, OpenSettings2Action, OpenSettingsJsonAction, OpenWorkspaceSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OPEN_FOLDER_SETTINGS_LABEL } from 'vs/workbench/contrib/preferences/browser/preferencesActions'; import { PreferencesEditor } from 'vs/workbench/contrib/preferences/browser/preferencesEditor'; import { SettingsEditor2 } from 'vs/workbench/contrib/preferences/browser/settingsEditor2'; -import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_COMMAND_OPEN_SETTINGS, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON } from 'vs/workbench/contrib/preferences/common/preferences'; +import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_COMMAND_OPEN_SETTINGS, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, SETTINGS_EDITOR_COMMAND_FOCUS_TOC } from 'vs/workbench/contrib/preferences/common/preferences'; import { PreferencesContribution } from 'vs/workbench/contrib/preferences/common/preferencesContribution'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -765,6 +765,23 @@ registerAction2(class extends Action2 { } }); +registerAction2(class extends Action2 { + constructor() { + super({ + id: SETTINGS_EDITOR_COMMAND_FOCUS_TOC, + precondition: CONTEXT_SETTINGS_EDITOR, + title: nls.localize('settings.focusSettingsTOC', "Focus settings TOC tree") + }); + } + + run(accessor: ServicesAccessor): void { + const preferencesEditor = getPreferencesEditor(accessor); + if (preferencesEditor instanceof SettingsEditor2) { + preferencesEditor.focusTOC(); + } + } +}); + registerAction2(class extends Action2 { constructor() { super({ diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 0be05b45226..42017a6c213 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -346,6 +346,10 @@ export class SettingsEditor2 extends BaseEditor { } } + focusTOC(): void { + this.tocTree.domFocus(); + } + showContextMenu(): void { const activeElement = this.getActiveElementInSettingsTree(); if (!activeElement) { diff --git a/src/vs/workbench/contrib/preferences/common/preferences.ts b/src/vs/workbench/contrib/preferences/common/preferences.ts index 3da748834d8..df315b95efa 100644 --- a/src/vs/workbench/contrib/preferences/common/preferences.ts +++ b/src/vs/workbench/contrib/preferences/common/preferences.ts @@ -83,6 +83,7 @@ export const SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING = 'settings.action.edi export const SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH = 'settings.action.focusSettingsFromSearch'; export const SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST = 'settings.action.focusSettingsList'; export const SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU = 'settings.action.showContextMenu'; +export const SETTINGS_EDITOR_COMMAND_FOCUS_TOC = 'settings.action.focusTOC'; export const SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON = 'settings.switchToJSON'; export const SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED = 'settings.filterByModified'; diff --git a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts index 47bf09f848b..a4a8b61f30c 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @@ -20,6 +20,9 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen'; export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider { @@ -34,6 +37,14 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce protected get activeTextEditorControl(): IEditor | undefined { return this.editorService.activeTextEditorControl; } + get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined { + if (this.configuration.preserveInput) { + return DefaultQuickAccessFilterValue.LAST; + } + + return undefined; + } + constructor( @IEditorService private readonly editorService: IEditorService, @IMenuService private readonly menuService: IMenuService, @@ -42,11 +53,20 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce @IKeybindingService keybindingService: IKeybindingService, @ICommandService commandService: ICommandService, @ITelemetryService telemetryService: ITelemetryService, - @INotificationService notificationService: INotificationService + @INotificationService notificationService: INotificationService, + @IConfigurationService private readonly configurationService: IConfigurationService ) { super({ showAlias: !Language.isDefaultVariant() }, instantiationService, keybindingService, commandService, telemetryService, notificationService); } + private get configuration() { + const commandPaletteConfig = this.configurationService.getValue().workbench.commandPalette; + + return { + preserveInput: commandPaletteConfig.preserveInput + }; + } + protected async getCommandPicks(disposables: DisposableStore, token: CancellationToken): Promise> { // wait for extensions registration or 800ms once diff --git a/src/vs/workbench/contrib/quickaccess/browser/quickAccess.contribution.ts b/src/vs/workbench/contrib/quickaccess/browser/quickAccess.contribution.ts index e0fffb808b4..0e6bc3aa3e9 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/quickAccess.contribution.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/quickAccess.contribution.ts @@ -22,6 +22,7 @@ registry.registerQuickAccessProvider({ registry.registerQuickAccessProvider({ ctor: ViewQuickAccessProvider, prefix: ViewQuickAccessProvider.PREFIX, + contextKey: 'inViewsPicker', placeholder: localize('viewQuickAccessPlaceholder', "Type the name of a view, output channel or terminal to open."), helpEntries: [{ description: localize('viewQuickAccess', "Open View"), needsEditor: false }] }); @@ -29,6 +30,7 @@ registry.registerQuickAccessProvider({ registry.registerQuickAccessProvider({ ctor: CommandsQuickAccessProvider, prefix: CommandsQuickAccessProvider.PREFIX, + contextKey: 'inCommandsPicker', placeholder: localize('commandsQuickAccessPlaceholder', "Type the name of a command to run."), helpEntries: [{ description: localize('commandsQuickAccess', "Show and Run Commands"), needsEditor: false }] }); diff --git a/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts b/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts index 98c39f8386c..76750058f50 100644 --- a/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/commandsHandler.ts @@ -12,7 +12,7 @@ import { Mode, IEntryRunContext, IAutoFocus, IModel, IQuickNavigateConfiguration import { QuickOpenEntryGroup, IHighlight, QuickOpenModel, QuickOpenEntry } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { QuickOpenHandler, IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen'; +import { QuickOpenHandler, IWorkbenchQuickOpenConfiguration, ENABLE_EXPERIMENTAL_VERSION_CONFIG } from 'vs/workbench/browser/quickopen'; import { IEditorAction } from 'vs/editor/common/editorCommon'; import { matchesWords, matchesPrefix, matchesContiguousSubString, or } from 'vs/base/common/filters'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; @@ -34,6 +34,8 @@ import { Disposable, DisposableStore, IDisposable, toDisposable, dispose } from import { timeout } from 'vs/base/common/async'; import { isFirefox } from 'vs/base/browser/browser'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { CommandsHistory } from 'vs/platform/quickinput/browser/commandsQuickAccess'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; export const ALL_COMMANDS_PREFIX = '>'; @@ -42,7 +44,7 @@ interface ISerializedCommandHistory { entries: { key: string; value: number }[]; } -class CommandsHistory extends Disposable { +class LegacyCommandsHistory extends Disposable { static readonly DEFAULT_COMMANDS_HISTORY_LENGTH = 50; @@ -71,17 +73,17 @@ class CommandsHistory extends Disposable { } private updateConfiguration(): void { - this.configuredCommandsHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(this.configurationService); + this.configuredCommandsHistoryLength = LegacyCommandsHistory.getConfiguredCommandHistoryLength(this.configurationService); - if (CommandsHistory.cache && CommandsHistory.cache.limit !== this.configuredCommandsHistoryLength) { - CommandsHistory.cache.limit = this.configuredCommandsHistoryLength; + if (LegacyCommandsHistory.cache && LegacyCommandsHistory.cache.limit !== this.configuredCommandsHistoryLength) { + LegacyCommandsHistory.cache.limit = this.configuredCommandsHistoryLength; - CommandsHistory.saveState(this.storageService); + LegacyCommandsHistory.saveState(this.storageService); } } private load(): void { - const raw = this.storageService.get(CommandsHistory.PREF_KEY_CACHE, StorageScope.GLOBAL); + const raw = this.storageService.get(LegacyCommandsHistory.PREF_KEY_CACHE, StorageScope.GLOBAL); let serializedCache: ISerializedCommandHistory | undefined; if (raw) { try { @@ -91,7 +93,7 @@ class CommandsHistory extends Disposable { } } - const cache = CommandsHistory.cache = new LRUCache(this.configuredCommandsHistoryLength, 1); + const cache = LegacyCommandsHistory.cache = new LRUCache(this.configuredCommandsHistoryLength, 1); if (serializedCache) { let entries: { key: string; value: number }[]; if (serializedCache.usesLRU) { @@ -102,33 +104,33 @@ class CommandsHistory extends Disposable { entries.forEach(entry => cache.set(entry.key, entry.value)); } - CommandsHistory.counter = this.storageService.getNumber(CommandsHistory.PREF_KEY_COUNTER, StorageScope.GLOBAL, CommandsHistory.counter); + LegacyCommandsHistory.counter = this.storageService.getNumber(LegacyCommandsHistory.PREF_KEY_COUNTER, StorageScope.GLOBAL, LegacyCommandsHistory.counter); } push(commandId: string): void { - if (!CommandsHistory.cache) { + if (!LegacyCommandsHistory.cache) { return; } - CommandsHistory.cache.set(commandId, CommandsHistory.counter++); // set counter to command + LegacyCommandsHistory.cache.set(commandId, LegacyCommandsHistory.counter++); // set counter to command - CommandsHistory.saveState(this.storageService); + LegacyCommandsHistory.saveState(this.storageService); } peek(commandId: string): number | undefined { - return CommandsHistory.cache?.peek(commandId); + return LegacyCommandsHistory.cache?.peek(commandId); } static saveState(storageService: IStorageService): void { - if (!CommandsHistory.cache) { + if (!LegacyCommandsHistory.cache) { return; } const serializedCache: ISerializedCommandHistory = { usesLRU: true, entries: [] }; - CommandsHistory.cache.forEach((value, key) => serializedCache.entries.push({ key, value })); + LegacyCommandsHistory.cache.forEach((value, key) => serializedCache.entries.push({ key, value })); - storageService.store(CommandsHistory.PREF_KEY_CACHE, JSON.stringify(serializedCache), StorageScope.GLOBAL); - storageService.store(CommandsHistory.PREF_KEY_COUNTER, CommandsHistory.counter, StorageScope.GLOBAL); + storageService.store(LegacyCommandsHistory.PREF_KEY_CACHE, JSON.stringify(serializedCache), StorageScope.GLOBAL); + storageService.store(LegacyCommandsHistory.PREF_KEY_COUNTER, LegacyCommandsHistory.counter, StorageScope.GLOBAL); } static getConfiguredCommandHistoryLength(configurationService: IConfigurationService): number { @@ -139,15 +141,15 @@ class CommandsHistory extends Disposable { return configuredCommandHistoryLength; } - return CommandsHistory.DEFAULT_COMMANDS_HISTORY_LENGTH; + return LegacyCommandsHistory.DEFAULT_COMMANDS_HISTORY_LENGTH; } static clearHistory(configurationService: IConfigurationService, storageService: IStorageService): void { - const commandHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(configurationService); - CommandsHistory.cache = new LRUCache(commandHistoryLength); - CommandsHistory.counter = 1; + const commandHistoryLength = LegacyCommandsHistory.getConfiguredCommandHistoryLength(configurationService); + LegacyCommandsHistory.cache = new LRUCache(commandHistoryLength); + LegacyCommandsHistory.counter = 1; - CommandsHistory.saveState(storageService); + LegacyCommandsHistory.saveState(storageService); } } @@ -162,6 +164,7 @@ export class ShowAllCommandsAction extends Action { id: string, label: string, @IQuickOpenService private readonly quickOpenService: IQuickOpenService, + @IQuickInputService private readonly quickInputService: IQuickInputService, @IConfigurationService private readonly configurationService: IConfigurationService ) { super(id, label); @@ -171,13 +174,18 @@ export class ShowAllCommandsAction extends Action { const config = this.configurationService.getValue(); const restoreInput = config.workbench?.commandPalette?.preserveInput === true; - // Show with last command palette input if any and configured - let value = ALL_COMMANDS_PREFIX; - if (restoreInput && lastCommandPaletteInput) { - value = `${value}${lastCommandPaletteInput}`; - } + if (this.configurationService.getValue(ENABLE_EXPERIMENTAL_VERSION_CONFIG) === true) { + this.quickInputService.quickAccess.show(ALL_COMMANDS_PREFIX); + } else { - this.quickOpenService.show(value, { inputSelection: lastCommandPaletteInput ? { start: 1 /* after prefix */, end: value.length } : undefined }); + // Show with last command palette input if any and configured + let value = ALL_COMMANDS_PREFIX; + if (restoreInput && lastCommandPaletteInput) { + value = `${value}${lastCommandPaletteInput}`; + } + + this.quickOpenService.show(value, { inputSelection: lastCommandPaletteInput ? { start: 1 /* after prefix */, end: value.length } : undefined }); + } return Promise.resolve(undefined); } @@ -197,13 +205,16 @@ export class ClearCommandHistoryAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { + const legacyCommandHistoryLength = LegacyCommandsHistory.getConfiguredCommandHistoryLength(this.configurationService); + if (legacyCommandHistoryLength > 0) { + LegacyCommandsHistory.clearHistory(this.configurationService, this.storageService); + } + const commandHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(this.configurationService); if (commandHistoryLength > 0) { CommandsHistory.clearHistory(this.configurationService, this.storageService); } - - return Promise.resolve(undefined); } } @@ -222,13 +233,11 @@ class CommandPaletteEditorAction extends EditorAction { }); } - run(accessor: ServicesAccessor, editor: ICodeEditor): Promise { + async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise { const quickOpenService = accessor.get(IQuickOpenService); // Show with prefix quickOpenService.show(ALL_COMMANDS_PREFIX); - - return Promise.resolve(undefined); } } @@ -406,7 +415,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { static readonly ID = 'workbench.picker.commands'; private commandHistoryEnabled: boolean | undefined; - private readonly commandsHistory: CommandsHistory; + private readonly commandsHistory: LegacyCommandsHistory; private readonly disposables = new DisposableStore(); private readonly disposeOnClose = new DisposableStore(); @@ -423,7 +432,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { ) { super(); - this.commandsHistory = this.disposables.add(this.instantiationService.createInstance(CommandsHistory)); + this.commandsHistory = this.disposables.add(this.instantiationService.createInstance(LegacyCommandsHistory)); this.extensionService.whenInstalledExtensionsRegistered().then(() => this.waitedForExtensionsRegistered = true); @@ -432,7 +441,7 @@ export class CommandsHandler extends QuickOpenHandler implements IDisposable { } private updateConfiguration(): void { - this.commandHistoryEnabled = CommandsHistory.getConfiguredCommandHistoryLength(this.configurationService) > 0; + this.commandHistoryEnabled = LegacyCommandsHistory.getConfiguredCommandHistoryLength(this.configurationService) > 0; } async getResults(searchValue: string, token: CancellationToken): Promise { diff --git a/src/vs/workbench/contrib/quickopen/browser/gotoLineHandler.ts b/src/vs/workbench/contrib/quickopen/browser/gotoLineHandler.ts index f9dd148c97c..1f9b796d44c 100644 --- a/src/vs/workbench/contrib/quickopen/browser/gotoLineHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/gotoLineHandler.ts @@ -22,31 +22,29 @@ import { isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Event } from 'vs/base/common/event'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; export const GOTO_LINE_PREFIX = ':'; export class GotoLineAction extends QuickOpenAction { static readonly ID = 'workbench.action.gotoLine'; - static readonly LABEL = nls.localize('gotoLine', "Go to Line..."); + static readonly LABEL = nls.localize('gotoLine', "Go to Line/Column..."); constructor(actionId: string, actionLabel: string, - @IQuickOpenService private readonly _quickOpenService: IQuickOpenService, + @IQuickOpenService quickOpenService: IQuickOpenService, + @IQuickInputService private readonly quickInputService: IQuickInputService, @IEditorService private readonly editorService: IEditorService ) { - super(actionId, actionLabel, GOTO_LINE_PREFIX, _quickOpenService); + super(actionId, actionLabel, GOTO_LINE_PREFIX, quickOpenService); } - run(): Promise { - + async run(): Promise { let activeTextEditorControl = this.editorService.activeTextEditorControl; - if (!activeTextEditorControl) { - return Promise.resolve(); - } - if (isDiffEditor(activeTextEditorControl)) { activeTextEditorControl = activeTextEditorControl.getModifiedEditor(); } + let restoreOptions: IEditorOptions | null = null; if (isCodeEditor(activeTextEditorControl)) { @@ -65,7 +63,7 @@ export class GotoLineAction extends QuickOpenAction { const result = super.run(); if (restoreOptions) { - Event.once(this._quickOpenService.onHide)(() => { + Event.once(Event.any(this.quickOpenService.onHide, this.quickInputService.onHide))(() => { activeTextEditorControl!.updateOptions(restoreOptions!); }); } diff --git a/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts b/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts index 51f9fbb9caf..99d38e899e2 100644 --- a/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts +++ b/src/vs/workbench/contrib/quickopen/browser/gotoSymbolHandler.ts @@ -61,7 +61,7 @@ const NLS_SYMBOL_KIND_CACHE: { [type: number]: string } = { export class GotoSymbolAction extends QuickOpenAction { static readonly ID = 'workbench.action.gotoSymbol'; - static readonly LABEL = nls.localize('gotoSymbol', "Go to Symbol in File..."); + static readonly LABEL = nls.localize('gotoSymbol', "Go to Symbol in Editor..."); constructor(actionId: string, actionLabel: string, @IQuickOpenService quickOpenService: IQuickOpenService) { super(actionId, actionLabel, GOTO_SYMBOL_PREFIX, quickOpenService); diff --git a/src/vs/workbench/contrib/quickopen/browser/quickopen.contribution.ts b/src/vs/workbench/contrib/quickopen/browser/quickopen.contribution.ts index ecac0bf8cc0..b8bd9429542 100644 --- a/src/vs/workbench/contrib/quickopen/browser/quickopen.contribution.ts +++ b/src/vs/workbench/contrib/quickopen/browser/quickopen.contribution.ts @@ -30,11 +30,11 @@ registry.registerWorkbenchAction(SyncActionDescriptor.create(ShowAllCommandsActi registry.registerWorkbenchAction(SyncActionDescriptor.create(GotoLineAction, GotoLineAction.ID, GotoLineAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_G } -}), 'Go to Line...'); +}), 'Go to Line/Column...'); registry.registerWorkbenchAction(SyncActionDescriptor.create(GotoSymbolAction, GotoSymbolAction.ID, GotoSymbolAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_O -}), 'Go to Symbol in File...'); +}), 'Go to Symbol in Editor...'); const inViewsPickerContextKey = 'inViewsPicker'; const inViewsPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inViewsPickerContextKey)); @@ -91,7 +91,7 @@ Registry.as(QuickOpenExtensions.Quickopen).registerQuickOpen { prefix: GOTO_LINE_PREFIX, needsEditor: true, - description: env.isMacintosh ? nls.localize('gotoLineDescriptionMac', "Go to Line") : nls.localize('gotoLineDescriptionWin', "Go to Line") + description: env.isMacintosh ? nls.localize('gotoLineDescriptionMac', "Go to Line/Column") : nls.localize('gotoLineDescriptionWin', "Go to Line/Column") }, ] ) @@ -107,12 +107,12 @@ Registry.as(QuickOpenExtensions.Quickopen).registerQuickOpen { prefix: GOTO_SYMBOL_PREFIX, needsEditor: true, - description: nls.localize('gotoSymbolDescription', "Go to Symbol in File") + description: nls.localize('gotoSymbolDescription', "Go to Symbol in Editor") }, { prefix: GOTO_SYMBOL_PREFIX + SCOPE_PREFIX, needsEditor: true, - description: nls.localize('gotoSymbolDescriptionScoped', "Go to Symbol in File by Category") + description: nls.localize('gotoSymbolDescriptionScoped', "Go to Symbol in Editor by Category") } ] ) @@ -170,7 +170,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, { group: '4_symbol_nav', command: { id: 'workbench.action.gotoSymbol', - title: nls.localize({ key: 'miGotoSymbolInFile', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in File...") + title: nls.localize({ key: 'miGotoSymbolInEditor', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in Editor...") }, order: 1 }); diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index e5b159005f9..7ff4c083fc5 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -15,11 +15,11 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { untildify } from 'vs/base/common/labels'; import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService'; import { URI } from 'vs/base/common/uri'; -import { toLocalResource, dirname, basenameOrAuthority } from 'vs/base/common/resources'; +import { toLocalResource, dirname, basenameOrAuthority, isEqual } from 'vs/base/common/resources'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService } from 'vs/platform/files/common/files'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { DisposableStore, IDisposable, toDisposable, MutableDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ILabelService } from 'vs/platform/label/common/label'; import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -39,11 +39,31 @@ import { Schemas } from 'vs/base/common/network'; import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { ResourceMap } from 'vs/base/common/map'; import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess'; +import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess'; +import { IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen'; +import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { ScrollType, IEditor, ICodeEditorViewState, IDiffEditorViewState } from 'vs/editor/common/editorCommon'; +import { once } from 'vs/base/common/functional'; +import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { getCodeEditor } from 'vs/editor/browser/editorBrowser'; +import { withNullAsUndefined } from 'vs/base/common/types'; interface IAnythingQuickPickItem extends IPickerQuickAccessItem { resource: URI | undefined; } +interface IEditorSymbolAnythingQuickPickItem extends IAnythingQuickPickItem { + resource: URI; + range: { decoration: IRange, selection: IRange } +} + +function isEditorSymbolQuickPickItem(pick?: IAnythingQuickPickItem): pick is IEditorSymbolAnythingQuickPickItem { + const candidate = pick ? pick as IEditorSymbolAnythingQuickPickItem : undefined; + + return !!candidate && !!candidate.range && !!candidate.resource; +} + export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { static PREFIX = ''; @@ -53,29 +73,76 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider | undefined = undefined; + + editorViewState: { + editor: IEditorInput, + group: IEditorGroup, + state: ICodeEditorViewState | IDiffEditorViewState | undefined + } | undefined = undefined; + scorerCache: ScorerCache = Object.create(null); fileQueryCache: FileQueryCacheState | undefined = undefined; lastOriginalFilter: string | undefined = undefined; lastFilter: string | undefined = undefined; lastRange: IRange | undefined = undefined; + lastActiveGlobalPick: IAnythingQuickPickItem | undefined = undefined; - constructor(private readonly provider: AnythingQuickAccessProvider) { } + isQuickNavigating: boolean | undefined = undefined; - reset(prepareForSearching: boolean): void { + constructor(private readonly provider: AnythingQuickAccessProvider, private readonly editorService: IEditorService) { } + + set(picker: IQuickPick): void { + + // Picker for this run + this.picker = picker; + once(picker.onDispose)(() => { + if (picker === this.picker) { + this.picker = undefined; // clear the picker when disposed to not keep it in memory for too long + } + }); // Caches - if (prepareForSearching) { + const isQuickNavigating = !!picker.quickNavigate; + if (!isQuickNavigating) { this.fileQueryCache = this.provider.createFileQueryCache(); this.scorerCache = Object.create(null); } // Other + this.isQuickNavigating = isQuickNavigating; this.lastOriginalFilter = undefined; this.lastFilter = undefined; this.lastRange = undefined; + this.lastActiveGlobalPick = undefined; + this.editorViewState = undefined; } - }(this); + + rememberEditorViewState(): void { + if (this.editorViewState) { + return; // return early if already done + } + + const activeEditorPane = this.editorService.activeEditorPane; + if (activeEditorPane) { + this.editorViewState = { + group: activeEditorPane.group, + editor: activeEditorPane.input, + state: withNullAsUndefined(getCodeEditor(activeEditorPane.getControl())?.saveViewState()) + }; + } + } + }(this, this.editorService); + + get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined { + if (this.configuration.preserveInput) { + return DefaultQuickAccessFilterValue.LAST; + } + + return undefined; + } constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @@ -91,38 +158,93 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider().workbench.editor; - const searchConfig = this.configurationService.getValue(); + const searchConfig = this.configurationService.getValue().search; + const quickOpenConfig = this.configurationService.getValue().workbench.quickOpen; return { openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, openSideBySideDirection: editorConfig.openSideBySideDirection, - includeSymbols: searchConfig.search.quickOpen.includeSymbols, - workspaceSymbolsFilter: searchConfig.search.quickOpen.workspaceSymbolsFilter, - includeHistory: searchConfig.search.quickOpen.includeHistory, - shortAutoSaveDelay: this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY + includeSymbols: searchConfig.quickOpen.includeSymbols, + includeHistory: searchConfig.quickOpen.includeHistory, + historyFilterSortOrder: searchConfig.quickOpen.history.filterSortOrder, + shortAutoSaveDelay: this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY, + preserveInput: quickOpenConfig.preserveInput }; } provide(picker: IQuickPick, token: CancellationToken): IDisposable { + const disposables = new DisposableStore(); - // Reset the pick state for this run - this.pickState.reset(!picker.quickNavigate); + // Update the pick state for this run + this.pickState.set(picker); + + // Add editor decorations for active editor symbol picks + const editorDecorationsDisposable = disposables.add(new MutableDisposable()); + disposables.add(picker.onDidChangeActive(() => { + + // Clear old decorations + editorDecorationsDisposable.value = undefined; + + // Add new decoration if editor symbol is active + const [item] = picker.activeItems; + if (isEditorSymbolQuickPickItem(item)) { + editorDecorationsDisposable.value = this.decorateAndRevealSymbolRange(item); + } + })); + + // Restore view state upon cancellation if we changed it + disposables.add(once(token.onCancellationRequested)(() => { + if (this.pickState.editorViewState) { + this.editorService.openEditor( + this.pickState.editorViewState.editor, + { viewState: this.pickState.editorViewState.state, preserveFocus: true /* import to not close the picker as a result */ }, + this.pickState.editorViewState.group + ); + } + })); // Start picker - return super.provide(picker, token); + disposables.add(super.provide(picker, token)); + + return disposables; } - protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): FastAndSlowPicksType | null { + private decorateAndRevealSymbolRange(pick: IEditorSymbolAnythingQuickPickItem): IDisposable { + const activeEditor = this.editorService.activeEditor; + if (!isEqual(pick.resource, activeEditor?.resource)) { + return Disposable.None; // active editor needs to be for resource + } + + const activeEditorControl = this.editorService.activeTextEditorControl; + if (!activeEditorControl) { + return Disposable.None; // we need a text editor control to decorate and reveal + } + + // we must remember our curret view state to be able to restore + this.pickState.rememberEditorViewState(); + + // Reveal + activeEditorControl.revealRangeInCenter(pick.range.selection, ScrollType.Smooth); + + // Decorate + this.addDecorations(activeEditorControl, pick.range.decoration); + + return toDisposable(() => this.clearDecorations(activeEditorControl)); + } + + protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Promise> | FastAndSlowPicksType | null { // Find a suitable range from the pattern looking for ":", "#" or "," - const filterWithRange = extractRangeFromFilter(originalFilter); + // unless we have the `@` editor symbol character inside the filter + const filterWithRange = extractRangeFromFilter(originalFilter, [GotoSymbolQuickAccessProvider.PREFIX]); // Update filter with normalized values let filter: string; @@ -147,18 +269,39 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider> | FastAndSlowPicksType | null { const query = prepareQuery(filter); + // Return early if we have editor symbol picks. We support this by: + // - having a previously active global pick (e.g. a file) + // - the user typing `@` to start the local symbol query + const editorSymbolPicks = this.getEditorSymbolPicks(query, disposables, token); + if (editorSymbolPicks) { + return editorSymbolPicks; + } + + // Otherwise return normally with history and file/symbol results const historyEditorPicks = this.getEditorHistoryPicks(query); return { // Fast picks: editor history - picks: historyEditorPicks.length > 0 ? - [ - { type: 'separator', label: localize('recentlyOpenedSeparator', "recently opened") }, - ...historyEditorPicks - ] : [], + picks: + (this.pickState.isQuickNavigating || historyEditorPicks.length === 0) ? + historyEditorPicks : + [ + { type: 'separator', label: localize('recentlyOpenedSeparator', "recently opened") }, + ...historyEditorPicks + ], // Slow picks: files and symbols additionalPicks: (async (): Promise> => { @@ -189,7 +332,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider compareItemsByScore(editorA, editorB, query, false, editorHistoryScorerAccessor, this.pickState.scorerCache, () => -1)); + // Return without sorting if settings tell to sort by recency + if (this.configuration.historyFilterSortOrder === 'recency') { + return editorHistoryPicks; + } + + return editorHistoryPicks.sort((editorA, editorB) => compareItemsByScore(editorA, editorB, query, false, editorHistoryScorerAccessor, this.pickState.scorerCache)); } //#endregion @@ -348,9 +496,25 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider result.resource); + } + + // Otherwise, make sure to filter relative path results from + // the search results to prevent duplicates + const relativePathFileResultsMap = new ResourceMap(); + for (const relativePathFileResult of relativePathFileResults) { + relativePathFileResultsMap.set(relativePathFileResult, true); + } + return [ - ...fileSearchResults.results.map(result => result.resource), - ...(relativePathFileResults || []) + ...fileSearchResults.results.filter(result => !relativePathFileResultsMap.has(result.resource)).map(result => result.resource), + ...relativePathFileResults ]; } @@ -442,11 +606,11 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider> { + private async getWorkspaceSymbolPicks(query: IPreparedQuery, token: CancellationToken): Promise> { const configuration = this.configuration; if ( !query.value || // we need a value for search for @@ -458,8 +622,8 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider> | null { + const filter = query.original.split(GotoSymbolQuickAccessProvider.PREFIX)[1]?.trim(); + if (typeof filter !== 'string') { + return null; // we need to be searched for editor symbols via `@` + } + + const activeGlobalPick = this.pickState.lastActiveGlobalPick; + if (!activeGlobalPick) { + return null; // we need an active global pick to find symbols for + } + + const activeGlobalResource = activeGlobalPick.resource; + if (!activeGlobalResource || (!this.fileService.canHandleResource(activeGlobalResource) && activeGlobalResource.scheme !== Schemas.untitled)) { + return null; // we need a resource that we can resolve + } + + return this.doGetEditorSymbolPicks(activeGlobalPick, activeGlobalResource, filter, disposables, token); + } + + private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { + + // Bring the editor to front to review symbols to go to + try { + + // we must remember our curret view state to be able to restore + this.pickState.rememberEditorViewState(); + + // open it + await this.editorService.openEditor({ + resource: activeGlobalResource, + options: { preserveFocus: true, revealIfOpened: true, ignoreError: true } + }); + } catch (error) { + return []; // return if resource cannot be opened + } + + if (token.isCancellationRequested) { + return []; + } + + // Obtain model from resource + let model = this.modelService.getModel(activeGlobalResource); + if (!model) { + try { + const modelReference = disposables.add(await this.textModelService.createModelReference(activeGlobalResource)); + if (token.isCancellationRequested) { + return []; + } + + model = modelReference.object.textEditorModel; + } catch (error) { + return []; // return if model cannot be resolved + } + } + + // Ask provider for editor symbols + const editorSymbolPicks = (await this.editorSymbolsQuickAccess.getSymbolPicks(model, filter, disposables, token)); + if (token.isCancellationRequested) { + return []; + } + + return editorSymbolPicks.map(editorSymbolPick => { + + // Preserve separators + if (editorSymbolPick.type === 'separator') { + return editorSymbolPick; + } + + // Convert editor symbols to anything pick + return { + ...editorSymbolPick, + resource: activeGlobalResource, + description: editorSymbolPick.description ? `${activeGlobalPick.label} • ${editorSymbolPick.description}` : activeGlobalPick.label, + trigger: (buttonIndex, keyMods) => { + this.openAnything(activeGlobalResource, { keyMods, range: editorSymbolPick.range?.selection, forceOpenSideBySide: true }); + + return TriggerAction.CLOSE_PICKER; + }, + accept: (keyMods, event) => this.openAnything(activeGlobalResource, { keyMods, range: editorSymbolPick.range?.selection, preserveFocus: event.inBackground }) + }; + }); + } + + addDecorations(editor: IEditor, range: IRange): void { + this.editorSymbolsQuickAccess.addDecorations(editor, range); + } + + clearDecorations(editor: IEditor): void { + this.editorSymbolsQuickAccess.clearDecorations(editor); + } + + //#endregion + + //#region Helpers private createAnythingPick(resourceOrEditor: URI | IEditorInput | IResourceEditorInput, configuration: { shortAutoSaveDelay: boolean, openSideBySideDirection: 'right' | 'down' | undefined }): IAnythingQuickPickItem { @@ -499,6 +761,10 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { + if (this.pickState.isQuickNavigating) { + return undefined; // no actions when quick navigating + } + const openSideBySideDirection = configuration.openSideBySideDirection; const buttons: IQuickInputButton[] = []; @@ -519,12 +785,13 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { + trigger: (buttonIndex, keyMods) => { switch (buttonIndex) { // Open to side / below case 0: this.openAnything(resourceOrEditor, { keyMods, range: this.pickState.lastRange, forceOpenSideBySide: true }); + return TriggerAction.CLOSE_PICKER; // Remove from History @@ -532,7 +799,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { + async run(): Promise { + if (this.configurationService.getValue(ENABLE_EXPERIMENTAL_VERSION_CONFIG) === true) { + this.quickInputService.quickAccess.show(ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX); + } else { + let prefix = ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX; + let inputSelection: { start: number; end: number; } | undefined = undefined; + const editor = this.editorService.getFocusedCodeEditor(); + const word = editor && getSelectionSearchString(editor); + if (word) { + prefix = prefix + word; + inputSelection = { start: 1, end: word.length + 1 }; + } - let prefix = ShowAllSymbolsAction.ALL_SYMBOLS_PREFIX; - let inputSelection: { start: number; end: number; } | undefined = undefined; - const editor = this.editorService.getFocusedCodeEditor(); - const word = editor && getSelectionSearchString(editor); - if (word) { - prefix = prefix + word; - inputSelection = { start: 1, end: word.length + 1 }; + this.quickOpenService.show(prefix, { inputSelection }); } - - this.quickOpenService.show(prefix, { inputSelection }); - - return Promise.resolve(undefined); } } @@ -660,8 +668,8 @@ const quickAccessRegistry = Registry.as(QuickAccessExtensi quickAccessRegistry.registerQuickAccessProvider({ ctor: AnythingQuickAccessProvider, prefix: AnythingQuickAccessProvider.PREFIX, - placeholder: nls.localize('anythingQuickAccessPlaceholder', "Type '?' to get help on the actions you can take from here"), - contextKey: 'inFilesPicker', + placeholder: nls.localize('anythingQuickAccessPlaceholder', "Search files by name (append {0} to go to line or {1} to go to symbol)", AbstractGotoLineQuickAccessProvider.PREFIX, GotoSymbolQuickAccessProvider.PREFIX), + contextKey: defaultQuickOpenContextKey, helpEntries: [{ description: nls.localize('anythingQuickAccess', "Go to File"), needsEditor: false }] }); @@ -734,22 +742,21 @@ configurationRegistry.registerConfiguration({ description: nls.localize('search.quickOpen.includeSymbols', "Whether to include results from a global symbol search in the file results for Quick Open."), default: false }, - 'search.quickOpen.workspaceSymbolsFilter': { - type: 'string', - enum: ['default', 'reduced', 'all'], - markdownEnumDescriptions: [ - nls.localize('search.quickOpen.workspaceSymbolsFilter.default', "All symbols including local variables are included in the specific workspace symbols picker but excluded from the files picker when `#search.quickOpen.includeSymbols#` is enabled."), - nls.localize('search.quickOpen.workspaceSymbolsFilter.reduced', "Some symbols like local variables are excluded in all pickers."), - nls.localize('search.quickOpen.workspaceSymbolsFilter.all', "All symbols including local variables are included in all pickers.") - ], - default: 'default', - description: nls.localize('search.quickOpen.workspaceSymbolsFilter', "Controls the filter to apply for the workspace symbols search in quick open. Depending on the setting, some symbols like local variables will be excluded to reduce the total number of results."), - }, 'search.quickOpen.includeHistory': { type: 'boolean', description: nls.localize('search.quickOpen.includeHistory', "Whether to include results from recently opened files in the file results for Quick Open."), default: true }, + 'search.quickOpen.history.filterSortOrder': { + 'type': 'string', + 'enum': ['default', 'recency'], + 'default': 'default', + 'enumDescriptions': [ + nls.localize('filterSortOrder.default', 'History entries are sorted by relevance based on the filter value used. More relevant entries appear first.'), + nls.localize('filterSortOrder.recency', 'History entries are sorted by recency. More recently opened entries appear first.') + ], + 'description': nls.localize('filterSortOrder', "Controls sorting order of editor history in quick open when filtering.") + }, 'search.followSymlinks': { type: 'boolean', description: nls.localize('search.followSymlinks', "Controls whether to follow symlinks while searching."), diff --git a/src/vs/workbench/contrib/search/browser/searchActions.ts b/src/vs/workbench/contrib/search/browser/searchActions.ts index b72da53d121..cc255f9057c 100644 --- a/src/vs/workbench/contrib/search/browser/searchActions.ts +++ b/src/vs/workbench/contrib/search/browser/searchActions.ts @@ -145,7 +145,7 @@ export abstract class FindOrReplaceInFilesAction extends Action { const searchAndReplaceWidget = openedView.searchAndReplaceWidget; searchAndReplaceWidget.toggleReplace(this.expandSearchReplaceWidget); - const updatedText = openedView.updateTextFromSelection(!this.expandSearchReplaceWidget); + const updatedText = openedView.updateTextFromSelection({ allowUnselectedWord: !this.expandSearchReplaceWidget }); openedView.searchAndReplaceWidget.focus(undefined, updatedText, updatedText); } }); @@ -172,7 +172,7 @@ export const FindInFilesCommand: ICommandHandler = (accessor, args: IFindInFiles if (typeof args.query === 'string') { openedView.setSearchParameters(args); } else { - updatedText = openedView.updateTextFromSelection((typeof args.replace !== 'string')); + updatedText = openedView.updateTextFromSelection({ allowUnselectedWord: typeof args.replace !== 'string' }); } openedView.searchAndReplaceWidget.focus(undefined, updatedText, updatedText); } diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 3b28518b509..d3024273740 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -867,11 +867,11 @@ export class SearchView extends ViewPane { focus(): void { super.focus(); - const updatedText = this.updateTextFromSelection(); + const updatedText = this.updateTextFromSelection({ allowSearchOnType: false }); this.searchWidget.focus(undefined, undefined, updatedText); } - updateTextFromSelection(allowUnselectedWord = true): boolean { + updateTextFromSelection({ allowUnselectedWord = true, allowSearchOnType = true }): boolean { let updatedText = false; const seedSearchStringFromSelection = this.configurationService.getValue('editor').find!.seedSearchStringFromSelection; if (seedSearchStringFromSelection) { @@ -880,9 +880,14 @@ export class SearchView extends ViewPane { if (this.searchWidget.searchInput.getRegex()) { selectedText = strings.escapeRegExpCharacters(selectedText); } - this.pauseSearching = true; - this.searchWidget.setValue(selectedText); - this.pauseSearching = false; + + if (allowSearchOnType && !this.viewModel.searchResult.hasRemovedResults) { + this.searchWidget.setValue(selectedText); + } else { + this.pauseSearching = true; + this.searchWidget.setValue(selectedText); + this.pauseSearching = false; + } updatedText = true; } } @@ -1891,9 +1896,11 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = collector.addRule(`.monaco-workbench .search-view .monaco-list.element-focused .monaco-list-row.focused.selected:not(.highlighted) .action-label:focus { outline-color: ${outlineSelectionColor} }`); } - const foregroundColor = theme.getColor(foreground); - if (foregroundColor) { - const fgWithOpacity = new Color(new RGBA(foregroundColor.rgba.r, foregroundColor.rgba.g, foregroundColor.rgba.b, 0.65)); - collector.addRule(`.vs-dark .search-view .message { color: ${fgWithOpacity}; }`); + if (theme.type === 'dark') { + const foregroundColor = theme.getColor(foreground); + if (foregroundColor) { + const fgWithOpacity = new Color(new RGBA(foregroundColor.rgba.r, foregroundColor.rgba.g, foregroundColor.rgba.b, 0.65)); + collector.addRule(`.search-view .message { color: ${fgWithOpacity}; }`); + } } }); diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index 74a9fa14c5e..22bba26028b 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -10,7 +10,7 @@ import { stripWildcards } from 'vs/base/common/strings'; import { CancellationToken } from 'vs/base/common/cancellation'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { ThrottledDelayer } from 'vs/base/common/async'; -import { getWorkspaceSymbols, IWorkspaceSymbol, IWorkspaceSymbolProvider, IWorkbenchSearchConfiguration } from 'vs/workbench/contrib/search/common/search'; +import { getWorkspaceSymbols, IWorkspaceSymbol, IWorkspaceSymbolProvider } from 'vs/workbench/contrib/search/common/search'; import { SymbolKinds, SymbolTag, SymbolKind } from 'vs/editor/common/modes'; import { ILabelService } from 'vs/platform/label/common/label'; import { Schemas } from 'vs/base/common/network'; @@ -24,6 +24,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { createResourceExcludeMatcher } from 'vs/workbench/services/search/common/search'; import { ResourceMap } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { getSelectionSearchString } from 'vs/editor/contrib/find/findController'; +import { withNullAsUndefined } from 'vs/base/common/types'; interface ISymbolQuickPickItem extends IPickerQuickAccessItem { resource: URI | undefined; @@ -51,29 +54,39 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider().workbench.editor; - const searchConfig = this.configurationService.getValue(); return { openEditorPinned: !editorConfig.enablePreviewFromQuickOpen, - openSideBySideDirection: editorConfig.openSideBySideDirection, - workspaceSymbolsFilter: searchConfig.search.quickOpen.workspaceSymbolsFilter + openSideBySideDirection: editorConfig.openSideBySideDirection }; } protected getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { - return this.getSymbolPicks(filter, { skipLocal: this.configuration.workspaceSymbolsFilter === 'reduced' }, token); + return this.getSymbolPicks(filter, undefined, token); } async getSymbolPicks(filter: string, options: { skipLocal?: boolean, skipSorting?: boolean, delay?: number } | undefined, token: CancellationToken): Promise> { diff --git a/src/vs/workbench/contrib/search/common/search.ts b/src/vs/workbench/contrib/search/common/search.ts index b3932374a09..a3fd05bf82c 100644 --- a/src/vs/workbench/contrib/search/common/search.ts +++ b/src/vs/workbench/contrib/search/common/search.ts @@ -77,7 +77,9 @@ export interface IWorkbenchSearchConfigurationProperties extends ISearchConfigur quickOpen: { includeSymbols: boolean; includeHistory: boolean; - workspaceSymbolsFilter: 'default' | 'reduced' | 'all'; + history: { + filterSortOrder: 'default' | 'recency' + } }; } @@ -108,8 +110,8 @@ export interface IFilterAndRange { range: IRange; } -export function extractRangeFromFilter(filter: string): IFilterAndRange | undefined { - if (!filter) { +export function extractRangeFromFilter(filter: string, unless?: string[]): IFilterAndRange | undefined { + if (!filter || unless?.some(value => filter.indexOf(value) !== -1)) { return undefined; } diff --git a/src/vs/workbench/contrib/search/common/searchModel.ts b/src/vs/workbench/contrib/search/common/searchModel.ts index 1505579db92..f063edc3eb9 100644 --- a/src/vs/workbench/contrib/search/common/searchModel.ts +++ b/src/vs/workbench/contrib/search/common/searchModel.ts @@ -703,6 +703,8 @@ export class SearchResult extends Disposable { private _rangeHighlightDecorations: RangeHighlightDecorations; private disposePastResults: () => void = () => { }; + private _hasRemovedResults = false; + constructor( private _searchModel: SearchModel, @IReplaceService private readonly replaceService: IReplaceService, @@ -714,6 +716,16 @@ export class SearchResult extends Disposable { this._rangeHighlightDecorations = this.instantiationService.createInstance(RangeHighlightDecorations); this._register(this.modelService.onModelAdded(model => this.onModelAdded(model))); + + this._register(this.onChange(e => { + if (e.removed) { + this._hasRemovedResults = true; + } + })); + } + + get hasRemovedResults(): boolean { + return this._hasRemovedResults; } get query(): ITextQuery | null { @@ -725,7 +737,8 @@ export class SearchResult extends Disposable { const oldFolderMatches = this.folderMatches(); new Promise(resolve => this.disposePastResults = resolve) .then(() => oldFolderMatches.forEach(match => match.clear())) - .then(() => oldFolderMatches.forEach(match => match.dispose())); + .then(() => oldFolderMatches.forEach(match => match.dispose())) + .then(() => this._hasRemovedResults = false); this._rangeHighlightDecorations.removeHighlightRange(); this._folderMatchesMap = TernarySearchTree.forPaths(); @@ -1028,7 +1041,6 @@ export class SearchModel extends Disposable { search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise { this.cancelSearch(true); - this._searchQuery = query; if (!this.searchConfig.searchOnType) { this.searchResult.clear(); diff --git a/src/vs/workbench/contrib/search/test/common/extractRange.test.ts b/src/vs/workbench/contrib/search/test/common/extractRange.test.ts index d508b8be961..a0894323734 100644 --- a/src/vs/workbench/contrib/search/test/common/extractRange.test.ts +++ b/src/vs/workbench/contrib/search/test/common/extractRange.test.ts @@ -42,4 +42,10 @@ suite('extractRangeFromFilter', () => { assert.equal(res?.range.startLineNumber, 19); assert.equal(res?.range.startColumn, 20); }); + + test('unless', async function () { + let res = extractRangeFromFilter('/some/path/file.txt@ (19,20)', ['@']); + + assert.ok(!res); + }); }); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 51d2257b813..739884ee6cb 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -381,7 +381,8 @@ const VIEW_CONTAINER = Registry.as(ViewContainerExtensi id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), ctorDescriptor: new SyncDescriptor(ViewPaneContainer, [TERMINAL_VIEW_ID, TERMINAL_VIEW_ID, { mergeViewWithContainerWhenSingleView: true, donotShowContainerTitleWhenMergedWithContainer: true }]), - focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS } + focusCommand: { id: TERMINAL_COMMAND_ID.FOCUS }, + hideIfEmpty: true }, ViewContainerLocation.Panel); Registry.as(panel.Extensions.Panels).setDefaultPanelId(TERMINAL_VIEW_ID); @@ -389,6 +390,7 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews id: TERMINAL_VIEW_ID, name: nls.localize('terminal', "Terminal"), canToggleVisibility: false, + canMoveView: true, ctorDescriptor: new SyncDescriptor(TerminalViewPane) }], VIEW_CONTAINER); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 7efd8924fe2..f9ab4f8b194 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -137,7 +137,7 @@ export class QuickKillTerminalAction extends Action { instance.dispose(true); } await timeout(50); - return this.quickOpenService.show(TERMINAL_PICKER_PREFIX, undefined); + return this.quickOpenService.show(TERMINAL_PICKER_PREFIX); } } @@ -1139,7 +1139,7 @@ export class QuickOpenTermAction extends Action { } public run(): Promise { - return this.quickOpenService.show(TERMINAL_PICKER_PREFIX, undefined); + return this.quickOpenService.show(TERMINAL_PICKER_PREFIX); } } @@ -1160,7 +1160,7 @@ export class RenameTerminalQuickOpenAction extends RenameTerminalAction { await super.run(this.terminal); // This timeout is needed to make sure the previous quickOpen has time to close before we show the next one await timeout(50); - await this.quickOpenService.show(TERMINAL_PICKER_PREFIX, undefined); + await this.quickOpenService.show(TERMINAL_PICKER_PREFIX); } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts b/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts index 32546d2eaab..04a24206f0c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalsQuickAccess.ts @@ -55,7 +55,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider('timelineFollowActiveEditor', true); @@ -283,6 +312,25 @@ export class TimelinePane extends ViewPane { if ((uri?.toString(true) === this.uri?.toString(true) && uri !== undefined) || // Fallback to match on fsPath if we are dealing with files or git schemes (uri?.fsPath === this.uri?.fsPath && (uri?.scheme === 'file' || uri?.scheme === 'git') && (this.uri?.scheme === 'file' || this.uri?.scheme === 'git'))) { + + // If the uri hasn't changed, make sure we have valid caches + for (const source of this.timelineService.getSources()) { + if (this.excludedSources.has(source.id)) { + continue; + } + + const timeline = this.timelinesBySource.get(source.id); + if (timeline !== undefined && !timeline.stale) { + continue; + } + + if (timeline !== undefined) { + this.updateTimeline(timeline, timeline.requiresReset); + } else { + this.loadTimelineForSource(source.id, uri, true); + } + } + return; } @@ -290,8 +338,6 @@ export class TimelinePane extends ViewPane { } private onProvidersChanged(e: TimelineProvidersChangeEvent) { - // TODO@eamodio only do work if we are visible - if (e.removed) { for (const source of e.removed) { this.timelinesBySource.delete(source); @@ -306,23 +352,16 @@ export class TimelinePane extends ViewPane { } private onTimelineChanged(e: TimelineChangeEvent) { - // TODO@eamodio only do work if we are visible - if (e?.uri === undefined || e.uri.toString(true) !== this.uri?.toString(true)) { const timeline = this.timelinesBySource.get(e.id); if (timeline === undefined) { return; } - if (e.reset) { - this.timelinesBySource.delete(e.id); - // Override the limit, to re-query for all our existing cached (possibly visible) items to keep visual continuity - const { oldest } = timeline; - this.loadTimelineForSource(e.id, this.uri!, true, oldest !== undefined ? { limit: { timestamp: oldest.timestamp, id: oldest.id } } : undefined); + if (this.isBodyVisible()) { + this.updateTimeline(timeline, e.reset ?? false); } else { - // Override the limit, to query for any newer items - const { newest } = timeline; - this.loadTimelineForSource(e.id, this.uri!, false, newest !== undefined ? { limit: { timestamp: newest.timestamp, id: newest.id } } : { limit: PageSize }); + timeline.invalidate(e.reset ?? false); } } } @@ -379,29 +418,37 @@ export class TimelinePane extends ViewPane { return this._visibleItemCount > 0; } + private clear(cancelPending: boolean) { + this._visibleItemCount = 0; + this._maxItemCount = PageSize; + this.timelinesBySource.clear(); + + if (cancelPending) { + for (const { tokenSource } of this.pendingRequests.values()) { + tokenSource.dispose(true); + } + + this.pendingRequests.clear(); + + if (!this.isBodyVisible()) { + this.tree.setChildren(null, undefined); + this._isEmpty = true; + } + } + } + private async loadTimeline(reset: boolean, sources?: string[]) { // If we have no source, we are reseting all sources, so cancel everything in flight and reset caches if (sources === undefined) { if (reset) { - this._visibleItemCount = 0; - this._maxItemCount = PageSize; - this.timelinesBySource.clear(); - - for (const { tokenSource } of this.pendingRequests.values()) { - tokenSource.dispose(true); - } - - this.pendingRequests.clear(); + this.clear(true); } // TODO@eamodio: Are these the right the list of schemes to exclude? Is there a better way? - if (this.uri?.scheme === 'vscode-settings' || this.uri?.scheme === 'webview-panel' || this.uri?.scheme === 'walkThrough') { + if (this.uri?.scheme === Schemas.vscodeSettings || this.uri?.scheme === Schemas.webviewPanel || this.uri?.scheme === Schemas.walkThrough) { this.uri = undefined; - this._visibleItemCount = 0; - this._maxItemCount = PageSize; - this.timelinesBySource.clear(); - + this.clear(false); this.refresh(); return; @@ -413,15 +460,16 @@ export class TimelinePane extends ViewPane { } if (this.uri === undefined) { - this._visibleItemCount = 0; - this._maxItemCount = PageSize; - this.timelinesBySource.clear(); - + this.clear(false); this.refresh(); return; } + if (!this.isBodyVisible()) { + return; + } + let hasPendingRequests = false; for (const source of sources ?? this.timelineService.getSources().map(s => s.id)) { @@ -490,6 +538,19 @@ export class TimelinePane extends ViewPane { return true; } + private updateTimeline(timeline: TimelineAggregate, reset: boolean) { + if (reset) { + this.timelinesBySource.delete(timeline.source); + // Override the limit, to re-query for all our existing cached (possibly visible) items to keep visual continuity + const { oldest } = timeline; + this.loadTimelineForSource(timeline.source, this.uri!, true, oldest !== undefined ? { limit: { timestamp: oldest.timestamp, id: oldest.id } } : undefined); + } else { + // Override the limit, to query for any newer items + const { newest } = timeline; + this.loadTimelineForSource(timeline.source, this.uri!, false, newest !== undefined ? { limit: { timestamp: newest.timestamp, id: newest.id } } : { limit: PageSize }); + } + } + private _pendingRefresh = false; private async handleRequest(request: TimelineRequest) { @@ -569,13 +630,18 @@ export class TimelinePane extends ViewPane { more = timeline.more; + let lastRelativeTime: string | undefined; for (const item of timeline.items) { + item.relativeTime = undefined; + item.hideRelativeTime = undefined; + count++; if (count > maxCount) { more = true; break; } + lastRelativeTime = updateRelativeTime(item, lastRelativeTime); yield { element: item }; } @@ -590,7 +656,7 @@ export class TimelinePane extends ViewPane { for (const [source, timeline] of this.timelinesBySource) { timeline.lastRenderedIndex = -1; - if (this.excludedSources.has(source)) { + if (this.excludedSources.has(source) || timeline.stale) { continue; } @@ -619,18 +685,24 @@ export class TimelinePane extends ViewPane { .reduce((previous, current) => (previous === undefined || current.nextItem!.value.timestamp >= previous.nextItem!.value.timestamp) ? current : previous, undefined!); } + let lastRelativeTime: string | undefined; let nextSource; while (nextSource = getNextMostRecentSource()) { nextSource.timeline.lastRenderedIndex++; - if (nextSource.nextItem.value.timestamp >= mostRecentEnd) { + const item = nextSource.nextItem.value; + item.relativeTime = undefined; + item.hideRelativeTime = undefined; + + if (item.timestamp >= mostRecentEnd) { count++; if (count > maxCount) { more = true; break; } - yield { element: nextSource.nextItem.value }; + lastRelativeTime = updateRelativeTime(item, lastRelativeTime); + yield { element: item }; } nextSource.nextItem = nextSource.iterator.next(); @@ -651,6 +723,10 @@ export class TimelinePane extends ViewPane { } private refresh() { + if (!this.isBodyVisible()) { + return; + } + this.tree.setChildren(null, this.getItems() as any); this._isEmpty = !this.hasVisibleItems; @@ -682,11 +758,23 @@ export class TimelinePane extends ViewPane { this.tree.domFocus(); } + setExpanded(expanded: boolean): boolean { + const changed = super.setExpanded(expanded); + + if (changed && this.isBodyVisible()) { + this.onActiveEditorChanged(); + } + + return changed; + } + setVisible(visible: boolean): void { if (visible) { this.visibilityDisposables = new DisposableStore(); this.editorService.onDidActiveEditorChange(this.onActiveEditorChanged, this, this.visibilityDisposables); + // Refresh the view on focus to update the relative timestamps + this.onDidFocus(() => this.refreshDebounced(), this, this.visibilityDisposables); this.onActiveEditorChanged(); } else { @@ -958,7 +1046,8 @@ class TimelineTreeRenderer implements ITreeRenderer('authTokenStatus', AuthStatus.Initializing); const CONTEXT_CONFLICTS_SOURCES = new RawContextKey('conflictsSources', ''); +const USER_DATA_SYNC_ACCOUNT_PREFERENCE_KEY = 'userDataSyncAccountPreference'; + type ConfigureSyncQuickPickItem = { id: SyncResource, label: string, description?: string }; function getSyncAreaLabel(source: SyncResource): string { @@ -195,18 +197,16 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo return; } - const selectedAccount = await this.quickInputService.pick(sessions.map(session => { - return { - id: session.id, - label: session.accountName - }; - }), { canPickMany: false }); - - if (selectedAccount) { - const selected = sessions.filter(account => selectedAccount.id === account.id)[0]; - this.logAuthenticatedEvent(selected); - await this.setActiveAccount(selected); + const accountPreference = this.storageService.get(USER_DATA_SYNC_ACCOUNT_PREFERENCE_KEY, StorageScope.GLOBAL); + if (accountPreference) { + const matchingSession = sessions.find(session => session.id === accountPreference); + if (matchingSession) { + this.setActiveAccount(matchingSession); + return; + } } + + await this.showSwitchAccountPicker(sessions); } private logAuthenticatedEvent(session: AuthenticationSession): void { @@ -246,15 +246,80 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo this.updateBadge(); } - private async onDidChangeSessions(providerId: string): Promise { + private async showSwitchAccountPicker(sessions: readonly AuthenticationSession[]): Promise { + return new Promise((resolve, _) => { + const quickPick = this.quickInputService.createQuickPick<{ label: string, session: AuthenticationSession }>(); + quickPick.title = localize('chooseAccountTitle', "Sync: Choose Account"); + quickPick.placeholder = localize('chooseAccount', "Choose an account you would like to use for settings sync"); + quickPick.items = sessions.map(session => { + return { + label: session.accountName, + session: session + }; + }); + + quickPick.onDidHide(() => { + quickPick.dispose(); + resolve(); + }); + + quickPick.onDidAccept(() => { + const selected = quickPick.selectedItems[0]; + this.setActiveAccount(selected.session); + this.storageService.store(USER_DATA_SYNC_ACCOUNT_PREFERENCE_KEY, selected.session.id, StorageScope.GLOBAL); + quickPick.dispose(); + resolve(); + }); + + quickPick.show(); + }); + } + + private async onDidChangeSessions(e: { providerId: string, event: AuthenticationSessionsChangeEvent }): Promise { + const { providerId, event } = e; if (providerId === this.userDataSyncStore!.authenticationProviderId) { if (this.activeAccount) { - // Try to update existing account, case where access token has been refreshed - const accounts = (await this.authenticationService.getSessions(this.userDataSyncStore!.authenticationProviderId) || []); - const matchingAccount = accounts.filter(a => a.id === this.activeAccount?.id)[0]; - this.setActiveAccount(matchingAccount); + if (event.removed.length) { + const activeWasRemoved = !!event.removed.find(removed => removed === this.activeAccount!.id); + + // If the current account was removed, check if another account can be used, otherwise offer to turn off sync + if (activeWasRemoved) { + const accounts = (await this.authenticationService.getSessions(this.userDataSyncStore!.authenticationProviderId) || []); + if (accounts.length) { + // Show switch dialog here + await this.showSwitchAccountPicker(accounts); + } else { + await this.turnOff(); + this.setActiveAccount(undefined); + return; + } + + } + } + + if (event.added.length) { + // Offer to switch accounts + const accounts = (await this.authenticationService.getSessions(this.userDataSyncStore!.authenticationProviderId) || []); + await this.showSwitchAccountPicker(accounts); + return; + } + + if (event.changed.length) { + const activeWasChanged = !!event.changed.find(changed => changed === this.activeAccount!.id); + if (activeWasChanged) { + // Try to update existing account, case where access token has been refreshed + const accounts = (await this.authenticationService.getSessions(this.userDataSyncStore!.authenticationProviderId) || []); + const matchingAccount = accounts.filter(a => a.id === this.activeAccount?.id)[0]; + this.setActiveAccount(matchingAccount); + } + } } else { - this.initializeActiveAccount(); + await this.initializeActiveAccount(); + + // If logged in for the first time from accounts menu, prompt if sync should be turned on + if (this.activeAccount) { + this.turnOn(true); + } } } } @@ -520,7 +585,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo } } - private async turnOn(): Promise { + private async turnOn(skipAccountPick?: boolean): Promise { if (!this.storageService.getBoolean('sync.donotAskPreviewConfirmation', StorageScope.GLOBAL, false)) { const result = await this.dialogService.show( Severity.Info, @@ -562,7 +627,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo disposables.add(Event.any(quickPick.onDidAccept, quickPick.onDidCustom)(async () => { if (quickPick.selectedItems.length) { this.updateConfiguration(items, quickPick.selectedItems); - this.doTurnOn().then(c, e); + this.doTurnOn(skipAccountPick).then(c, e); quickPick.hide(); } })); @@ -571,8 +636,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo }); } - private async doTurnOn(): Promise { - if (this.authenticationState.get() === AuthStatus.SignedIn) { + private async doTurnOn(skipAccountPick?: boolean): Promise { + if (this.authenticationState.get() === AuthStatus.SignedIn && !skipAccountPick) { await new Promise((c, e) => { const disposables: DisposableStore = new DisposableStore(); const displayName = this.authenticationService.getDisplayName(this.userDataSyncStore!.authenticationProviderId); @@ -706,7 +771,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo private async turnOff(): Promise { const result = await this.dialogService.confirm({ type: 'info', - message: localize('turn off sync confirmation', "Turn off Sync"), + message: localize('turn off sync confirmation', "Do you want to turn off sync?"), detail: localize('turn off sync detail', "Your settings, keybindings, extensions and UI State will no longer be synced."), primaryButton: localize('turn off', "Turn Off"), checkbox: { @@ -750,14 +815,14 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo private getConflictsEditorInputs(syncResource: SyncResource): DiffEditorInput[] { return this.editorService.editors.filter(input => { const resource = input instanceof DiffEditorInput ? input.master.resource : input.resource; - return getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) === syncResource; + return resource && getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) === syncResource; }) as DiffEditorInput[]; } private getAllConflictsEditorInputs(): IEditorInput[] { return this.editorService.editors.filter(input => { const resource = input instanceof DiffEditorInput ? input.master.resource : input.resource; - return getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) !== undefined; + return resource && getSyncResourceFromLocalPreview(resource!, this.workbenchEnvironmentService) !== undefined; }); } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts index bc59eeaff1d..cd83abd8dda 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncView.ts @@ -10,13 +10,12 @@ import { localize } from 'vs/nls'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { TreeViewPane, TreeView } from 'vs/workbench/browser/parts/views/treeView'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { ALL_SYNC_RESOURCES, CONTEXT_SYNC_ENABLEMENT, IUserDataSyncStoreService, toRemoteBackupSyncResource, resolveBackupSyncResource, IUserDataSyncBackupStoreService, IResourceRefHandle, toLocalBackupSyncResource, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; +import { ALL_SYNC_RESOURCES, CONTEXT_SYNC_ENABLEMENT, SyncResource, IUserDataSyncService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions'; import { IContextKeyService, RawContextKey, ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey'; import { URI } from 'vs/base/common/uri'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { FolderThemeIcon, FileThemeIcon } from 'vs/platform/theme/common/themeService'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { FolderThemeIcon } from 'vs/platform/theme/common/themeService'; import { fromNow } from 'vs/base/common/date'; import { pad } from 'vs/base/common/strings'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; @@ -26,8 +25,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { constructor( @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService, - @IUserDataSyncBackupStoreService private readonly userDataSyncBackupStoreService: IUserDataSyncBackupStoreService, + @IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService, ) { const container = this.registerSyncViewContainer(); this.registerBackupView(container, true); @@ -59,9 +57,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { const disposable = treeView.onDidChangeVisibility(visible => { if (visible && !treeView.dataProvider) { disposable.dispose(); - treeView.dataProvider = this.instantiationService.createInstance(UserDataSyncHistoryViewDataProvider, id, - (resource: SyncResource) => remote ? this.userDataSyncStoreService.getAllRefs(resource) : this.userDataSyncBackupStoreService.getAllRefs(resource), - (resource: SyncResource, ref: string) => remote ? toRemoteBackupSyncResource(resource, ref) : toLocalBackupSyncResource(resource, ref)); + treeView.dataProvider = new UserDataSyncHistoryViewDataProvider(remote, this.userDataSyncService); } }); const viewsRegistry = Registry.as(Extensions.ViewsRegistry); @@ -104,28 +100,11 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { registerAction2(class extends Action2 { constructor() { super({ - id: `workbench.actions.sync.${viewId}.resolveResourceRef`, - title: localize('workbench.actions.sync.resolveResourceRef', "Resolve Resource Ref"), - }); - } - async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise { - const editorService = accessor.get(IEditorService); - let resource = URI.parse(handle.$treeItemHandle); - const result = resolveBackupSyncResource(resource); - if (result) { - resource = resource.with({ fragment: result.resource }); - await editorService.openEditor({ resource }); - } - } - }); - registerAction2(class extends Action2 { - constructor() { - super({ - id: `workbench.actions.sync.${viewId}.resolveResourceRefCompletely`, - title: localize('workbench.actions.sync.resolveResourceRefCompletely', "Show full content"), + id: `workbench.actions.sync.resolveResource`, + title: localize('workbench.actions.sync.resolveResourceRef', "Show full content"), menu: { id: MenuId.ViewItemContext, - when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /syncref-.*/i)) + when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /sync-resource-.*/i)) }, }); } @@ -134,34 +113,28 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { await editorService.openEditor({ resource: URI.parse(handle.$treeItemHandle) }); } }); + registerAction2(class extends Action2 { constructor() { super({ - id: `workbench.actions.${viewId}.commpareWithLocal`, - title: localize('workbench.action.deleteRef', "Open Changes"), - menu: { - id: MenuId.ViewItemContext, - when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', viewId), ContextKeyExpr.regex('viewItem', /syncref-(settings|keybindings).*/i)) - }, + id: `workbench.actions.sync.commpareWithLocal`, + title: localize('workbench.actions.sync.commpareWithLocal', "Open Changes"), }); } async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise { const editorService = accessor.get(IEditorService); - const environmentService = accessor.get(IEnvironmentService); - const resource = URI.parse(handle.$treeItemHandle); - const result = resolveBackupSyncResource(resource); - if (result) { - const leftResource: URI = resource.with({ fragment: result.resource }); - const rightResource: URI = result.resource === 'settings' ? environmentService.settingsResource : environmentService.keybindingsResource; + const { resource, comparableResource } = <{ resource: string, comparableResource?: string }>JSON.parse(handle.$treeItemHandle); + if (comparableResource) { await editorService.openEditor({ - leftResource, - rightResource, + leftResource: URI.parse(resource), + rightResource: URI.parse(comparableResource), options: { - preserveFocus: false, - pinned: true, + preserveFocus: true, revealIfVisible: true, }, }); + } else { + await editorService.openEditor({ resource: URI.parse(resource) }); } } }); @@ -169,48 +142,55 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution { } +interface SyncResourceTreeItem extends ITreeItem { + resource: SyncResource; + resourceHandle: ISyncResourceHandle; +} + class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider { - constructor( - private readonly viewId: string, - private getAllRefs: (resource: SyncResource) => Promise, - private toResource: (resource: SyncResource, ref: string) => URI - ) { - } + constructor(private readonly remote: boolean, private userDataSyncService: IUserDataSyncService) { } async getChildren(element?: ITreeItem): Promise { - if (element) { - return this.getResources(element.handle); + if (!element) { + return ALL_SYNC_RESOURCES.map(resourceKey => ({ + handle: resourceKey, + collapsibleState: TreeItemCollapsibleState.Collapsed, + label: { label: resourceKey }, + themeIcon: FolderThemeIcon, + })); } - return ALL_SYNC_RESOURCES.map(resourceKey => ({ - handle: resourceKey, - collapsibleState: TreeItemCollapsibleState.Collapsed, - label: { label: resourceKey }, - themeIcon: FolderThemeIcon, - contextValue: `sync-${resourceKey}` - })); - } - - private async getResources(handle: string): Promise { - const resourceKey = ALL_SYNC_RESOURCES.filter(key => key === handle)[0]; + const resourceKey = ALL_SYNC_RESOURCES.filter(key => key === element.handle)[0] as SyncResource; if (resourceKey) { - const refHandles = await this.getAllRefs(resourceKey); - return refHandles.map(({ ref, created }) => { - const handle = this.toResource(resourceKey, ref).toString(); + const refHandles = this.remote ? await this.userDataSyncService.getRemoteSyncResourceHandles(resourceKey) : await this.userDataSyncService.getLocalSyncResourceHandles(resourceKey); + return refHandles.map(({ uri, created }) => { + return { + handle: uri.toString(), + collapsibleState: TreeItemCollapsibleState.Collapsed, + label: { label: label(new Date(created)) }, + description: fromNow(created, true), + resourceUri: uri, + resource: resourceKey, + resourceHandle: { uri, created }, + contextValue: `sync-resource-${resourceKey}` + }; + }); + } + if ((element).resourceHandle) { + const associatedResources = await this.userDataSyncService.getAssociatedResources((element).resource, (element).resourceHandle); + return associatedResources.map(({ resource, comparableResource }) => { + const handle = JSON.stringify({ resource: resource.toString(), comparableResource: comparableResource?.toString() }); return { handle, collapsibleState: TreeItemCollapsibleState.None, - label: { label: label(new Date(created)) }, - description: fromNow(created, true), - command: { id: `workbench.actions.sync.${this.viewId}.resolveResourceRef`, title: '', arguments: [{ $treeItemHandle: handle, $treeViewId: '' }] }, - themeIcon: FileThemeIcon, - contextValue: `syncref-${resourceKey}` + resourceUri: resource, + command: { id: `workbench.actions.sync.commpareWithLocal`, title: '', arguments: [{ $treeViewId: '', $treeItemHandle: handle }] }, + contextValue: `sync-associatedResource-${(element).resource}` }; }); } return []; } - } function label(date: Date): string { diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts index 3da701349a1..cee6146281e 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditorInput.ts @@ -7,8 +7,7 @@ import { Lazy } from 'vs/base/common/lazy'; import { URI } from 'vs/base/common/uri'; import { EditorInput, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { IWebviewService, WebviewIcons, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; - -const WebviewPanelResourceScheme = 'webview-panel'; +import { Schemas } from 'vs/base/common/network'; export class WebviewInput extends EditorInput { @@ -24,7 +23,7 @@ export class WebviewInput extends EditorInput { get resource() { return URI.from({ - scheme: WebviewPanelResourceScheme, + scheme: Schemas.webviewPanel, path: `webview-panel/webview-${this.id}` }); } diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index e7e50346aa5..3ee82a7b2c2 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -7,10 +7,9 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ViewsWelcomeExtensionPoint, ViewWelcome, viewsWelcomeExtensionPointDescriptor, ViewIdentifierMap } from './viewsWelcomeExtensionPoint'; +import { ViewsWelcomeExtensionPoint, ViewWelcome, ViewIdentifierMap } from './viewsWelcomeExtensionPoint'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ViewContainerExtensions, IViewsRegistry, ViewContentPriority } from 'vs/workbench/common/views'; -import { localize } from 'vs/nls'; const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); @@ -23,11 +22,6 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo extensionPoint.setHandler((_, { added, removed }) => { for (const contribution of removed) { - // Proposed API check - if (!contribution.description.enableProposedApi) { - continue; - } - for (const welcome of contribution.value) { const disposable = this.viewWelcomeContents.get(welcome); @@ -38,12 +32,6 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo } for (const contribution of added) { - // Proposed API check - if (!contribution.description.enableProposedApi) { - contribution.collector.error(localize('proposedAPI.invalid', "The '{0}' contribution is a proposed API and is only available when running out of dev or with the following command line switch: --enable-proposed-api {1}", viewsWelcomeExtensionPointDescriptor.extensionPoint, contribution.description.identifier.value)); - continue; - } - for (const welcome of contribution.value) { const id = ViewIdentifierMap[welcome.view] ?? welcome.view; const disposable = viewsRegistry.registerViewWelcomeContent(id, { diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-browser/actions/windowActions.ts index a39c21631d8..44de240a80d 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-browser/actions/windowActions.ts @@ -34,10 +34,8 @@ export class CloseCurrentWindowAction extends Action { super(id, label); } - run(): Promise { + async run(): Promise { this.electronService.closeWindow(); - - return Promise.resolve(true); } } @@ -91,10 +89,8 @@ export class ZoomInAction extends BaseZoomAction { super(id, label, configurationService); } - run(): Promise { + async run(): Promise { this.setConfiguredZoomLevel(webFrame.getZoomLevel() + 1); - - return Promise.resolve(true); } } @@ -111,10 +107,8 @@ export class ZoomOutAction extends BaseZoomAction { super(id, label, configurationService); } - run(): Promise { + async run(): Promise { this.setConfiguredZoomLevel(webFrame.getZoomLevel() - 1); - - return Promise.resolve(true); } } @@ -131,10 +125,8 @@ export class ZoomResetAction extends BaseZoomAction { super(id, label, configurationService); } - run(): Promise { + async run(): Promise { this.setConfiguredZoomLevel(0); - - return Promise.resolve(true); } } @@ -160,8 +152,8 @@ export class ReloadWindowWithExtensionsDisabledAction extends Action { export abstract class BaseSwitchWindow extends Action { - private closeWindowAction: IQuickInputButton = { - iconClass: 'action-remove-from-recently-opened', + private readonly closeWindowAction: IQuickInputButton = { + iconClass: 'codicon-close', tooltip: nls.localize('close', "Close Window") }; @@ -204,7 +196,7 @@ export abstract class BaseSwitchWindow extends Action { placeHolder, quickNavigate: this.isQuickNavigate() ? { keybindings: this.keybindingService.lookupKeybindings(this.id) } : undefined, onDidTriggerItemButton: async context => { - await this.electronService.closeWindow(); + await this.electronService.closeWindowById(context.item.payload); context.removeItem(); } }); diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index ef3552ed42f..4bb44555753 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -3,12 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { AuthenticationSession } from 'vs/editor/common/modes'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/editor/common/modes'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { MainThreadAuthenticationProvider } from 'vs/workbench/api/browser/mainThreadAuthentication'; +import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; export const IAuthenticationService = createDecorator('IAuthenticationService'); @@ -17,12 +19,12 @@ export interface IAuthenticationService { registerAuthenticationProvider(id: string, provider: MainThreadAuthenticationProvider): void; unregisterAuthenticationProvider(id: string): void; - sessionsUpdate(providerId: string): void; + sessionsUpdate(providerId: string, event: AuthenticationSessionsChangeEvent): void; readonly onDidRegisterAuthenticationProvider: Event; readonly onDidUnregisterAuthenticationProvider: Event; - readonly onDidChangeSessions: Event; + readonly onDidChangeSessions: Event<{ providerId: string, event: AuthenticationSessionsChangeEvent }>; getSessions(providerId: string): Promise | undefined>; getDisplayName(providerId: string): string; login(providerId: string, scopes: string[]): Promise; @@ -31,6 +33,7 @@ export interface IAuthenticationService { export class AuthenticationService extends Disposable implements IAuthenticationService { _serviceBrand: undefined; + private _placeholderMenuItem: IDisposable | undefined; private _authenticationProviders: Map = new Map(); @@ -40,25 +43,53 @@ export class AuthenticationService extends Disposable implements IAuthentication private _onDidUnregisterAuthenticationProvider: Emitter = this._register(new Emitter()); readonly onDidUnregisterAuthenticationProvider: Event = this._onDidUnregisterAuthenticationProvider.event; - private _onDidChangeSessions: Emitter = this._register(new Emitter()); - readonly onDidChangeSessions: Event = this._onDidChangeSessions.event; + private _onDidChangeSessions: Emitter<{ providerId: string, event: AuthenticationSessionsChangeEvent }> = this._register(new Emitter<{ providerId: string, event: AuthenticationSessionsChangeEvent }>()); + readonly onDidChangeSessions: Event<{ providerId: string, event: AuthenticationSessionsChangeEvent }> = this._onDidChangeSessions.event; constructor() { super(); + this._placeholderMenuItem = MenuRegistry.appendMenuItem(MenuId.AccountsContext, { + command: { + id: 'noAuthenticationProviders', + title: nls.localize('noAuthenticationProviders', "No authentication providers registered") + }, + }); } registerAuthenticationProvider(id: string, authenticationProvider: MainThreadAuthenticationProvider): void { this._authenticationProviders.set(id, authenticationProvider); this._onDidRegisterAuthenticationProvider.fire(id); + + if (authenticationProvider.dependents.length && this._placeholderMenuItem) { + this._placeholderMenuItem.dispose(); + this._placeholderMenuItem = undefined; + } } unregisterAuthenticationProvider(id: string): void { - this._authenticationProviders.delete(id); - this._onDidUnregisterAuthenticationProvider.fire(id); + const provider = this._authenticationProviders.get(id); + if (provider) { + provider.dispose(); + this._authenticationProviders.delete(id); + this._onDidUnregisterAuthenticationProvider.fire(id); + } + + if (!this._authenticationProviders.size) { + this._placeholderMenuItem = MenuRegistry.appendMenuItem(MenuId.AccountsContext, { + command: { + id: 'noAuthenticationProviders', + title: nls.localize('noAuthenticationProviders', "No authentication providers registered") + }, + }); + } } - sessionsUpdate(id: string): void { - this._onDidChangeSessions.fire(id); + sessionsUpdate(id: string, event: AuthenticationSessionsChangeEvent): void { + this._onDidChangeSessions.fire({ providerId: id, event: event }); + const provider = this._authenticationProviders.get(id); + if (provider) { + provider.updateSessionItems(); + } } getDisplayName(id: string): string { diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index 250fbf72436..23cc7b80b96 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -28,7 +28,7 @@ import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerServ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -import { EditStackElement, MultiModelEditStackElement } from 'vs/editor/common/model/editStack'; +import { SingleModelEditStackElement, MultiModelEditStackElement } from 'vs/editor/common/model/editStack'; type ValidationResult = { canApply: true } | { canApply: false, reason: URI }; @@ -234,7 +234,7 @@ class BulkEditModel implements IDisposable { const multiModelEditStackElement = new MultiModelEditStackElement( this._label || localize('workspaceEdit', "Workspace Edit"), - tasks.map(t => new EditStackElement(t.model, t.getBeforeCursorState())) + tasks.map(t => new SingleModelEditStackElement(t.model, t.getBeforeCursorState())) ); this._undoRedoService.pushElement(multiModelEditStackElement); diff --git a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts index 436e469c343..6432e6993f5 100644 --- a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts +++ b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts @@ -19,6 +19,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; +import { Schemas } from 'vs/base/common/network'; export class PreferencesEditorInput extends SideBySideEditorInput { static readonly ID: string = 'workbench.editorinputs.preferencesEditorInput'; @@ -105,7 +106,7 @@ export class SettingsEditor2Input extends EditorInput { private readonly _settingsModel: Settings2EditorModel; readonly resource: URI = URI.from({ - scheme: 'vscode-settings', + scheme: Schemas.vscodeSettings, path: `settingseditor` }); diff --git a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncBackupStoreService.ts b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncBackupStoreService.ts deleted file mode 100644 index 7ce287cdc13..00000000000 --- a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncBackupStoreService.ts +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IResourceRefHandle, IUserDataSyncBackupStoreService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; -import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; - -export class UserDataSyncBackupStoreService implements IUserDataSyncBackupStoreService { - - _serviceBrand: undefined; - private readonly channel: IChannel; - - constructor( - @ISharedProcessService sharedProcessService: ISharedProcessService, - ) { - this.channel = sharedProcessService.getChannel('userDataSyncBackupStoreService'); - } - - backup(key: SyncResource, content: string): Promise { - return this.channel.call('backup', [key, content]); - } - - - getAllRefs(key: SyncResource): Promise { - return this.channel.call('getAllRefs', [key]); - } - - resolveContent(key: SyncResource, ref: string): Promise { - return this.channel.call('resolveContent', [key, ref]); - } - -} - -registerSingleton(IUserDataSyncBackupStoreService, UserDataSyncBackupStoreService); diff --git a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts index c33de4a7cde..3cfea3362a7 100644 --- a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts +++ b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SyncStatus, SyncResource, IUserDataSyncService, UserDataSyncError, SyncResourceConflicts } from 'vs/platform/userDataSync/common/userDataSync'; +import { SyncStatus, SyncResource, IUserDataSyncService, UserDataSyncError, SyncResourceConflicts, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; @@ -73,8 +73,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ return this.channel.call('sync'); } - acceptConflict(conflict: URI, content: string): Promise { - return this.channel.call('acceptConflict', [conflict, content]); + stop(): Promise { + return this.channel.call('stop'); } reset(): Promise { @@ -85,16 +85,31 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ return this.channel.call('resetLocal'); } - stop(): Promise { - return this.channel.call('stop'); + isFirstTimeSyncWithMerge(): Promise { + return this.channel.call('isFirstTimeSyncWithMerge'); + } + + acceptConflict(conflict: URI, content: string): Promise { + return this.channel.call('acceptConflict', [conflict, content]); } resolveContent(resource: URI): Promise { return this.channel.call('resolveContent', [resource]); } - isFirstTimeSyncWithMerge(): Promise { - return this.channel.call('isFirstTimeSyncWithMerge'); + async getLocalSyncResourceHandles(resource: SyncResource): Promise { + const handles = await this.channel.call('getLocalSyncResourceHandles', [resource]); + return handles.map(({ created, uri }) => ({ created, uri: URI.revive(uri) })); + } + + async getRemoteSyncResourceHandles(resource: SyncResource): Promise { + const handles = await this.channel.call('getRemoteSyncResourceHandles', [resource]); + return handles.map(({ created, uri }) => ({ created, uri: URI.revive(uri) })); + } + + async getAssociatedResources(resource: SyncResource, syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> { + const result = await this.channel.call<{ resource: URI, comparableResource?: URI }[]>('getAssociatedResources', [resource, syncResourceHandle]); + return result.map(({ resource, comparableResource }) => ({ resource: URI.revive(resource), comparableResource: URI.revive(comparableResource) })); } private async updateStatus(status: SyncStatus): Promise { diff --git a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncStoreService.ts b/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncStoreService.ts deleted file mode 100644 index 21365024770..00000000000 --- a/src/vs/workbench/services/userDataSync/electron-browser/userDataSyncStoreService.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { SyncResource, IUserDataSyncStoreService, IUserDataSyncStore, getUserDataSyncStore, IUserData, IUserDataManifest, IResourceRefHandle } from 'vs/platform/userDataSync/common/userDataSync'; -import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IProductService } from 'vs/platform/product/common/productService'; - -export class UserDataSyncStoreService implements IUserDataSyncStoreService { - - _serviceBrand: undefined; - private readonly channel: IChannel; - readonly userDataSyncStore: IUserDataSyncStore | undefined; - - constructor( - @ISharedProcessService sharedProcessService: ISharedProcessService, - @IProductService productService: IProductService, - @IConfigurationService configurationService: IConfigurationService - ) { - this.channel = sharedProcessService.getChannel('userDataSyncStoreService'); - this.userDataSyncStore = getUserDataSyncStore(productService, configurationService); - } - - read(key: SyncResource, oldValue: IUserData | null, source?: SyncResource): Promise { - throw new Error('Not Supported'); - } - - write(key: SyncResource, content: string, ref: string | null, source?: SyncResource): Promise { - throw new Error('Not Supported'); - } - - manifest(): Promise { - throw new Error('Not Supported'); - } - - clear(): Promise { - throw new Error('Not Supported'); - } - - getAllRefs(key: SyncResource): Promise { - return this.channel.call('getAllRefs', [key]); - } - - resolveContent(key: SyncResource, ref: string): Promise { - return this.channel.call('resolveContent', [key, ref]); - } - - delete(key: SyncResource): Promise { - return this.channel.call('delete', [key]); - } - -} - -registerSingleton(IUserDataSyncStoreService, UserDataSyncStoreService); diff --git a/src/vs/workbench/services/workingCopy/common/workingCopyService.ts b/src/vs/workbench/services/workingCopy/common/workingCopyService.ts index 628ca136d64..58d76f1b170 100644 --- a/src/vs/workbench/services/workingCopy/common/workingCopyService.ts +++ b/src/vs/workbench/services/workingCopy/common/workingCopyService.ts @@ -27,12 +27,12 @@ export const enum WorkingCopyCapabilities { * `IBackupFileService.resolve(workingCopy.resource)` to * retrieve the backup when loading the working copy. */ -export interface IWorkingCopyBackup { +export interface IWorkingCopyBackup { /** * Any serializable metadata to be associated with the backup. */ - meta?: object; + meta?: MetaType; /** * Use this for larger textual content of the backup. diff --git a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts index 09a1e6a56a9..46e4713ca08 100644 --- a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts @@ -51,7 +51,7 @@ suite('MainThreadDocumentsAndEditors', () => { const dialogService = new TestDialogService(); const notificationService = new TestNotificationService(); const undoRedoService = new UndoRedoService(dialogService, notificationService); - modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), undoRedoService); + modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), undoRedoService, dialogService); codeEditorService = new TestCodeEditorService(); textFileService = new class extends mock() { isDirty() { return false; } diff --git a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts index 2dc9e4ca630..7e8645f2c40 100644 --- a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts @@ -73,7 +73,7 @@ suite('MainThreadEditors', () => { const dialogService = new TestDialogService(); const notificationService = new TestNotificationService(); const undoRedoService = new UndoRedoService(dialogService, notificationService); - modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), undoRedoService); + modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService(), undoRedoService, dialogService); const services = new ServiceCollection(); diff --git a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts index da6aef2e37e..e93eaa8a05d 100644 --- a/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/quickopen.perf.integrationTest.ts @@ -89,7 +89,7 @@ suite.skip('QuickOpen performance (integration)', () => { [IDialogService, dialogService], [INotificationService, notificationService], [IUndoRedoService, undoRedoService], - [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), new NullLogService(), undoRedoService)], + [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), new NullLogService(), undoRedoService, dialogService)], [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IEditorService, new TestEditorService()], [IEditorGroupsService, new TestEditorGroupsService()], diff --git a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts index 91558016763..51a52b7a570 100644 --- a/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/test/electron-browser/textsearch.perf.integrationTest.ts @@ -79,7 +79,7 @@ suite.skip('TextSearch performance (integration)', () => { [IDialogService, dialogService], [INotificationService, notificationService], [IUndoRedoService, undoRedoService], - [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), logService, undoRedoService)], + [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), logService, undoRedoService, dialogService)], [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IEditorService, new TestEditorService()], [IEditorGroupsService, new TestEditorGroupsService()], diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index 8ee0f138984..8390ae4ab86 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -207,6 +207,7 @@ export class TestElectronService implements IElectronService { async relaunch(options?: { addArgs?: string[] | undefined; removeArgs?: string[] | undefined; } | undefined): Promise { } async reload(): Promise { } async closeWindow(): Promise { } + async closeWindowById(): Promise { } async quit(): Promise { } async openDevTools(options?: Electron.OpenDevToolsOptions | undefined): Promise { } async toggleDevTools(): Promise { } diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 19bb3a7db45..7879df84278 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -179,7 +179,6 @@ import 'vs/workbench/contrib/scm/browser/scmViewlet'; // Debug import 'vs/workbench/contrib/debug/browser/debug.contribution'; -import 'vs/workbench/contrib/debug/browser/debugQuickOpen'; import 'vs/workbench/contrib/debug/browser/debugEditorContribution'; import 'vs/workbench/contrib/debug/browser/breakpointEditorContribution'; import 'vs/workbench/contrib/debug/browser/callStackEditorContribution'; @@ -201,7 +200,6 @@ import 'vs/workbench/contrib/customEditor/browser/webviewEditor.contribution'; // Extensions Management import 'vs/workbench/contrib/extensions/browser/extensions.contribution'; -import 'vs/workbench/contrib/extensions/browser/extensionsQuickOpen'; import 'vs/workbench/contrib/extensions/browser/extensionsViewlet'; // Output View @@ -210,7 +208,6 @@ import 'vs/workbench/contrib/output/browser/outputView'; // Terminal import 'vs/workbench/contrib/terminal/browser/terminal.contribution'; -import 'vs/workbench/contrib/terminal/browser/terminalQuickOpen'; import 'vs/workbench/contrib/terminal/browser/terminalView'; // Relauncher diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index dbc3993b172..f2502c08619 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -52,8 +52,6 @@ import 'vs/workbench/services/workspaces/electron-browser/workspaceEditingServic import 'vs/workbench/services/userDataSync/electron-browser/storageKeysSyncRegistryService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataAutoSyncService'; -import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncStoreService'; -import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncBackupStoreService'; import 'vs/workbench/services/authentication/electron-browser/authenticationTokenService'; import 'vs/workbench/services/authentication/browser/authenticationService'; import 'vs/workbench/services/host/electron-browser/desktopHostService'; diff --git a/test/automation/src/quickinput.ts b/test/automation/src/quickinput.ts index 682d14eae7c..70b37ea9e2d 100644 --- a/test/automation/src/quickinput.ts +++ b/test/automation/src/quickinput.ts @@ -9,10 +9,19 @@ export class QuickInput { static QUICK_INPUT = '.quick-input-widget'; static QUICK_INPUT_INPUT = `${QuickInput.QUICK_INPUT} .quick-input-box input`; - static QUICK_INPUT_FOCUSED_ELEMENT = `${QuickInput.QUICK_INPUT} .quick-open-tree .monaco-tree-row.focused .monaco-highlighted-label`; + static QUICK_INPUT_ROW = `${QuickInput.QUICK_INPUT} .quick-input-list .monaco-list-row`; + static QUICK_INPUT_FOCUSED_ELEMENT = `${QuickInput.QUICK_INPUT_ROW}.focused .monaco-highlighted-label`; + static QUICK_INPUT_ENTRY_LABEL = `${QuickInput.QUICK_INPUT_ROW} .label-name`; + static QUICK_INPUT_ENTRY_LABEL_SPAN = `${QuickInput.QUICK_INPUT_ROW} .monaco-highlighted-label span`; constructor(private code: Code) { } + async submit(text: string): Promise { + await this.code.waitForSetValue(QuickInput.QUICK_INPUT_INPUT, text); + await this.code.dispatchKeybinding('enter'); + await this.waitForQuickInputClosed(); + } + async closeQuickInput(): Promise { await this.code.dispatchKeybinding('escape'); await this.waitForQuickInputClosed(); @@ -22,7 +31,11 @@ export class QuickInput { await this.code.waitForActiveElement(QuickInput.QUICK_INPUT_INPUT, retryCount); } - private async waitForQuickInputClosed(): Promise { + async waitForQuickInputElements(accept: (names: string[]) => boolean): Promise { + await this.code.waitForElements(QuickInput.QUICK_INPUT_ENTRY_LABEL, false, els => accept(els.map(e => e.textContent))); + } + + async waitForQuickInputClosed(): Promise { await this.code.waitForElement(QuickInput.QUICK_INPUT, r => !!r && r.attributes.style.indexOf('display: none;') !== -1); } diff --git a/test/automation/src/quickopen.ts b/test/automation/src/quickopen.ts index b40afe76642..cd07572b42a 100644 --- a/test/automation/src/quickopen.ts +++ b/test/automation/src/quickopen.ts @@ -5,17 +5,11 @@ import { Editors } from './editors'; import { Code } from './code'; +import { QuickInput } from './quickinput'; export class QuickOpen { - static QUICK_OPEN = 'div.monaco-quick-open-widget'; - static QUICK_OPEN_HIDDEN = 'div.monaco-quick-open-widget[aria-hidden="true"]'; - static QUICK_OPEN_INPUT = `${QuickOpen.QUICK_OPEN} .quick-open-input input`; - static QUICK_OPEN_FOCUSED_ELEMENT = `${QuickOpen.QUICK_OPEN} .quick-open-tree .monaco-tree-row.focused .monaco-highlighted-label`; - static QUICK_OPEN_ENTRY_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry'; - static QUICK_OPEN_ENTRY_LABEL_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry .label-name'; - - constructor(private code: Code, private editors: Editors) { } + constructor(private code: Code, private editors: Editors, private quickInput: QuickInput) { } async openQuickOpen(value: string): Promise { let retries = 0; @@ -29,7 +23,7 @@ export class QuickOpen { } try { - await this.waitForQuickOpenOpened(10); + await this.quickInput.waitForQuickInputOpened(10); break; } catch (err) { if (++retries > 5) { @@ -41,59 +35,27 @@ export class QuickOpen { } if (value) { - await this.code.waitForSetValue(QuickOpen.QUICK_OPEN_INPUT, value); + await this.code.waitForSetValue(QuickInput.QUICK_INPUT_INPUT, value); } } - async closeQuickOpen(): Promise { - await this.code.dispatchKeybinding('escape'); - await this.waitForQuickOpenClosed(); - } - async openFile(fileName: string): Promise { await this.openQuickOpen(fileName); - await this.waitForQuickOpenElements(names => names[0] === fileName); + await this.quickInput.waitForQuickInputElements(names => names[0] === fileName); await this.code.dispatchKeybinding('enter'); await this.editors.waitForActiveTab(fileName); await this.editors.waitForEditorFocus(fileName); } - async waitForQuickOpenOpened(retryCount?: number): Promise { - await this.code.waitForActiveElement(QuickOpen.QUICK_OPEN_INPUT, retryCount); - } - - private async waitForQuickOpenClosed(): Promise { - await this.code.waitForElement(QuickOpen.QUICK_OPEN_HIDDEN); - } - - async submit(text: string): Promise { - await this.code.waitForSetValue(QuickOpen.QUICK_OPEN_INPUT, text); - await this.code.dispatchKeybinding('enter'); - await this.waitForQuickOpenClosed(); - } - - async selectQuickOpenElement(index: number): Promise { - await this.waitForQuickOpenOpened(); - for (let from = 0; from < index; from++) { - await this.code.dispatchKeybinding('down'); - } - await this.code.dispatchKeybinding('enter'); - await this.waitForQuickOpenClosed(); - } - - async waitForQuickOpenElements(accept: (names: string[]) => boolean): Promise { - await this.code.waitForElements(QuickOpen.QUICK_OPEN_ENTRY_LABEL_SELECTOR, false, els => accept(els.map(e => e.textContent))); - } - - async runCommand(command: string): Promise { - await this.openQuickOpen(`> ${command}`); + async runCommand(commandId: string): Promise { + await this.openQuickOpen(`>${commandId}`); // wait for best choice to be focused - await this.code.waitForTextContent(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT, command); + await this.code.waitForTextContent(QuickInput.QUICK_INPUT_FOCUSED_ELEMENT); // wait and click on best choice - await this.code.waitAndClick(QuickOpen.QUICK_OPEN_FOCUSED_ELEMENT); + await this.quickInput.selectQuickInputElement(0); } async openQuickOutline(): Promise { @@ -106,13 +68,13 @@ export class QuickOpen { await this.code.dispatchKeybinding('ctrl+shift+o'); } - const text = await this.code.waitForTextContent('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span'); + const text = await this.code.waitForTextContent(QuickInput.QUICK_INPUT_ENTRY_LABEL_SPAN); if (text !== 'No symbol information for the file') { return; } - await this.closeQuickOpen(); + await this.quickInput.closeQuickInput(); await new Promise(c => setTimeout(c, 250)); } } diff --git a/test/automation/src/settings.ts b/test/automation/src/settings.ts index 537ec269d2e..de54d4fc6d8 100644 --- a/test/automation/src/settings.ts +++ b/test/automation/src/settings.ts @@ -32,6 +32,6 @@ export class SettingsEditor { } private async openSettings(): Promise { - await this.quickopen.runCommand('Preferences: Open Settings (JSON)'); + await this.quickopen.runCommand('workbench.action.openSettingsJson'); } } diff --git a/test/automation/src/terminal.ts b/test/automation/src/terminal.ts index 82b7d9151e5..0aa4ee46a75 100644 --- a/test/automation/src/terminal.ts +++ b/test/automation/src/terminal.ts @@ -15,7 +15,7 @@ export class Terminal { constructor(private code: Code, private quickopen: QuickOpen) { } async showTerminal(): Promise { - await this.quickopen.runCommand('View: Toggle Integrated Terminal'); + await this.quickopen.runCommand('workbench.action.terminal.toggleTerminal'); await this.code.waitForActiveElement(XTERM_TEXTAREA); await this.code.waitForTerminalBuffer(XTERM_SELECTOR, lines => lines.some(line => line.length > 0)); } diff --git a/test/automation/src/workbench.ts b/test/automation/src/workbench.ts index 212f265ca66..51606062d91 100644 --- a/test/automation/src/workbench.ts +++ b/test/automation/src/workbench.ts @@ -44,8 +44,8 @@ export class Workbench { constructor(code: Code, userDataPath: string) { this.editors = new Editors(code); - this.quickopen = new QuickOpen(code, this.editors); this.quickinput = new QuickInput(code); + this.quickopen = new QuickOpen(code, this.editors, this.quickinput); this.explorer = new Explorer(code, this.editors); this.activitybar = new ActivityBar(code); this.search = new Search(code); diff --git a/test/smoke/src/areas/editor/editor.test.ts b/test/smoke/src/areas/editor/editor.test.ts index 8832f070225..2b5f58bf644 100644 --- a/test/smoke/src/areas/editor/editor.test.ts +++ b/test/smoke/src/areas/editor/editor.test.ts @@ -12,7 +12,7 @@ export function setup() { await app.workbench.quickopen.openFile('www'); await app.workbench.quickopen.openQuickOutline(); - await app.workbench.quickopen.waitForQuickOpenElements(names => names.length >= 6); + await app.workbench.quickinput.waitForQuickInputElements(names => names.length >= 6); }); // it('folds/unfolds the code correctly', async function () { diff --git a/test/smoke/src/areas/languages/languages.test.ts b/test/smoke/src/areas/languages/languages.test.ts index 0985a614a9e..36c9bf446dc 100644 --- a/test/smoke/src/areas/languages/languages.test.ts +++ b/test/smoke/src/areas/languages/languages.test.ts @@ -12,7 +12,7 @@ export function setup() { await app.workbench.quickopen.openFile('style.css'); await app.workbench.quickopen.openQuickOutline(); - await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 2); + await app.workbench.quickinput.waitForQuickInputElements(names => names.length === 2); }); it('verifies problems view', async function () { diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index 0a1090a3ff5..022634a8be5 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -47,8 +47,8 @@ export function setup() { const app = this.app as Application; await app.workbench.quickopen.openQuickOpen('*.*'); - await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 6); - await app.workbench.quickopen.closeQuickOpen(); + await app.workbench.quickinput.waitForQuickInputElements(names => names.length === 6); + await app.workbench.quickinput.closeQuickInput(); }); it('shows workspace name in title', async function () { diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 68c9e5f2854..bdd9ecc39af 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -10,8 +10,8 @@ export function setup() { describe('Search', () => { after(function () { const app = this.app as Application; - cp.execSync('git checkout .', { cwd: app.workspacePathOrFolder }); - cp.execSync('git reset --hard origin/master', { cwd: app.workspacePathOrFolder }); + cp.execSync('git checkout . --quiet', { cwd: app.workspacePathOrFolder }); + cp.execSync('git reset --hard origin/master --quiet', { cwd: app.workspacePathOrFolder }); }); it('searches for body & checks for correct result number', async function () { @@ -71,7 +71,7 @@ export function setup() { ]; await app.workbench.quickopen.openQuickOpen('.js'); - await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); + await app.workbench.quickinput.waitForQuickInputElements(names => expectedNames.every(n => names.some(m => n === m))); await app.code.dispatchKeybinding('escape'); }); @@ -84,7 +84,7 @@ export function setup() { ]; await app.workbench.quickopen.openQuickOpen('a.s'); - await app.workbench.quickopen.waitForQuickOpenElements(names => expectedNames.every(n => names.some(m => n === m))); + await app.workbench.quickinput.waitForQuickInputElements(names => expectedNames.every(n => names.some(m => n === m))); await app.code.dispatchKeybinding('escape'); }); }); diff --git a/test/smoke/src/areas/statusbar/statusbar.test.ts b/test/smoke/src/areas/statusbar/statusbar.test.ts index 34ea9661154..5c5a3700bfb 100644 --- a/test/smoke/src/areas/statusbar/statusbar.test.ts +++ b/test/smoke/src/areas/statusbar/statusbar.test.ts @@ -77,9 +77,9 @@ export function setup(isWeb) { await app.workbench.quickopen.openFile('app.js'); await app.workbench.statusbar.clickOn(StatusBarElement.SELECTION_STATUS); - await app.workbench.quickopen.waitForQuickOpenOpened(); + await app.workbench.quickinput.waitForQuickInputOpened(); - await app.workbench.quickopen.submit(':15'); + await app.workbench.quickinput.submit(':15'); await app.workbench.editor.waitForHighlightingLine('app.js', 15); }); diff --git a/yarn.lock b/yarn.lock index 2fa983546b1..661f528ffc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9638,10 +9638,10 @@ vsce@1.48.0: yauzl "^2.3.1" yazl "^2.2.2" -vscode-debugprotocol@1.39.0: - version "1.39.0" - resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.39.0.tgz#0c639178d0d5ea7de7903b6478b53d2bc0d77461" - integrity sha512-Wkvgtuz90vjtQBcvw9Z+BYa4dA6W+sHwHMpqvJVNmwWSuT3JZdl0XDhZNLqtMXkVF4okxtAe0MmbupPSt+gnAQ== +vscode-debugprotocol@1.40.0-pre.1: + version "1.40.0-pre.1" + resolved "https://registry.yarnpkg.com/vscode-debugprotocol/-/vscode-debugprotocol-1.40.0-pre.1.tgz#62c066c0520cc5e318dfc9873907574018bc8460" + integrity sha512-MLlNUSoJbRPNP/7PpnNLOOubZP/X0ObDEjwC6frrn/GR+bT943S1iIdj9aMjT7i93HSpsIAx8YbwkqId7nxLgw== vscode-minimist@^1.2.2: version "1.2.2"