Merge remote-tracking branch 'upstream/master' into rebornix/notebook

This commit is contained in:
Peng Lyu committed 2019-12-09 11:04:24 -08:00
commit 8d8580260f
257 files changed
+5971 -3106

No files matched your search

+4 -4
View File
@@ -8,7 +8,7 @@ This project incorporates components from the projects listed below. The origina
1. atom/language-clojure version 0.22.7 (https://github.com/atom/language-clojure)
2. atom/language-coffee-script version 0.49.3 (https://github.com/atom/language-coffee-script)
3. atom/language-java version 0.31.3 (https://github.com/atom/language-java)
4. atom/language-sass version 0.61.4 (https://github.com/atom/language-sass)
4. atom/language-sass version 0.62.1 (https://github.com/atom/language-sass)
5. atom/language-shellscript version 0.26.0 (https://github.com/atom/language-shellscript)
6. atom/language-xml version 0.35.2 (https://github.com/atom/language-xml)
7. Colorsublime-Themes version 0.1.0 (https://github.com/Colorsublime/Colorsublime-Themes)
@@ -27,13 +27,13 @@ This project incorporates components from the projects listed below. The origina
20. Ionic documentation version 1.2.4 (https://github.com/ionic-team/ionic-site)
21. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar)
22. jeff-hykin/cpp-textmate-grammar version 1.12.11 (https://github.com/jeff-hykin/cpp-textmate-grammar)
23. jeff-hykin/cpp-textmate-grammar version 1.14.9 (https://github.com/jeff-hykin/cpp-textmate-grammar)
23. jeff-hykin/cpp-textmate-grammar version 1.14.13 (https://github.com/jeff-hykin/cpp-textmate-grammar)
24. js-beautify version 1.6.8 (https://github.com/beautify-web/js-beautify)
25. Jxck/assert version 1.0.0 (https://github.com/Jxck/assert)
26. language-docker (https://github.com/moby/moby)
27. language-go version 0.44.3 (https://github.com/atom/language-go)
28. language-less version 0.34.2 (https://github.com/atom/language-less)
29. language-php version 0.44.2 (https://github.com/atom/language-php)
29. language-php version 0.44.3 (https://github.com/atom/language-php)
30. language-rust version 0.4.12 (https://github.com/zargony/atom-language-rust)
31. MagicStack/MagicPython version 1.1.1 (https://github.com/MagicStack/MagicPython)
32. marked version 0.6.2 (https://github.com/markedjs/marked)
@@ -589,7 +589,7 @@ END OF HTML 5.1 W3C Working Draft NOTICES AND INFORMATION
=========================================
MIT License
Copyright (c) 2017 Yuki Ueda
Copyright (c) 2019 Yuki Ueda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -118,6 +118,32 @@ steps:
displayName: Run integration tests
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- script: |
set -e
yarn gulp "vscode-linux-x64-build-deb"
yarn gulp "vscode-linux-x64-build-rpm"
yarn gulp "vscode-linux-x64-prepare-snap"
displayName: Build packages
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '.build/linux/rpm/x86_64'
Pattern: '*.rpm'
signConfigType: inlineSignParams
inlineOperation: |
[
{
"keyCode": "CP-450779-Pgp",
"operationSetCode": "LinuxSign",
"parameters": [ ],
"toolName": "sign",
"toolVersion": "1.0"
}
]
SessionTimeout: 120
displayName: Codesign rpm
- script: |
set -e
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
-4
View File
@@ -31,7 +31,6 @@ node build/azure-pipelines/common/createAsset.js "server-$PLATFORM_LINUX" archiv
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "x64" "$VSCODE_HOCKEYAPP_ID_LINUX64"
# Publish DEB
yarn gulp "vscode-linux-x64-build-deb"
PLATFORM_DEB="linux-deb-x64"
DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
@@ -40,7 +39,6 @@ DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
node build/azure-pipelines/common/createAsset.js "$PLATFORM_DEB" package "$DEB_FILENAME" "$DEB_PATH"
# Publish RPM
yarn gulp "vscode-linux-x64-build-rpm"
PLATFORM_RPM="linux-rpm-x64"
RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
@@ -49,8 +47,6 @@ RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
node build/azure-pipelines/common/createAsset.js "$PLATFORM_RPM" package "$RPM_FILENAME" "$RPM_PATH"
# Publish Snap
yarn gulp "vscode-linux-x64-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-x64.tar.gz"
+2 -2
View File
@@ -16,7 +16,7 @@
},
{
"name": "ms-vscode.node-debug2",
"version": "1.41.0",
"version": "1.41.3",
"repo": "https://github.com/Microsoft/vscode-node-debug2",
"metadata": {
"id": "36d19e17-7569-4841-a001-947eb18602b2",
@@ -31,7 +31,7 @@
},
{
"name": "ms-vscode.references-view",
"version": "0.0.38",
"version": "0.0.42",
"repo": "https://github.com/Microsoft/vscode-reference-view",
"metadata": {
"id": "dc489f46-520d-4556-ae85-1f9eab3c412d",
-4
View File
@@ -50,10 +50,6 @@
"name": "vs/workbench/contrib/comments",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/testCustomEditors",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/debug",
"project": "vscode-workbench"
+2 -2
View File
@@ -964,10 +964,10 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBas
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBasename}.exe\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\default.ico"
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Applications\{#ExeBasename}.exe\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu, {#ShellNameShort}}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufiles; Flags: uninsdeletekey
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufiles
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\*\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: addcontextmenufiles
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu, {#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "{cm:OpenWithCodeContextMenu,{#ShellNameShort}}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\{#ExeBasename}.exe"; Tasks: addcontextmenufolders
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\shell\{#RegValueName}\command"; ValueType: expandsz; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%V"""; Tasks: addcontextmenufolders
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\directory\background\shell\{#RegValueName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open w&ith {#ShellNameShort}"; Tasks: addcontextmenufolders; Flags: uninsdeletekey
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Configures an attached to container",
"allowComments": true,
"type": "object",
@@ -18,6 +18,10 @@
"type": "integer"
}
},
"settings": {
"$ref": "vscode://schemas/settings/machine",
"description": "Machine specific settings that should be copied into the container."
},
"remoteEnv": {
"type": "object",
"additionalProperties": {
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "Defines a dev container",
"allowComments": true,
"type": "object",
@@ -84,6 +84,13 @@
"type": "boolean",
"description": "Controls whether on Linux the container's user should be updated with the local user's UID and GID. On by default."
},
"mounts": {
"type": "array",
"description": "Mount points to set up when creating the container. See Docker's documentation for the --mount option for the supported syntax.",
"items": {
"type": "string"
}
},
"runArgs": {
"type": "array",
"description": "The arguments required when starting in the container.",
@@ -16,7 +16,13 @@ void Rectangle::set_values (int x, int y) {
height = y;
}
long double operator "" _w(long double);
#define MY_MACRO(a, b)
int main () {
1.2_w; // calls operator "" _w(1.2L)
asm("movl %a %b");
MY_MACRO(1, 2);
Rectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
@@ -36,10 +36,10 @@
"c": "_UCRT",
"t": "source.cpp meta.preprocessor.conditional.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -91,10 +91,10 @@
"c": "_UCRT",
"t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -36,10 +36,10 @@
"c": "_UCRT",
"t": "source.cpp meta.preprocessor.conditional.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -80,10 +80,10 @@
"c": "_UCRT",
"t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -36,10 +36,10 @@
"c": "DOCTEST_IMPLEMENT_FIXTURE",
"t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -36,10 +36,10 @@
"c": "B4G_DEBUG_CHECK",
"t": "source.cpp meta.preprocessor.conditional.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -1807,10 +1807,10 @@
"c": "movw $0x38, %ax; ltr %ax",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp meta.embedded.assembly.cpp",
"r": {
"dark_plus": "meta.embedded: #D4D4D4",
"light_plus": "meta.embedded: #000000",
"dark_vs": "meta.embedded: #D4D4D4",
"light_vs": "meta.embedded: #000000",
"dark_plus": "meta.embedded.assembly: #CE9178",
"light_plus": "meta.embedded.assembly: #A31515",
"dark_vs": "meta.embedded.assembly: #CE9178",
"light_vs": "meta.embedded.assembly: #A31515",
"hc_black": "meta.embedded: #FFFFFF"
}
},
@@ -190,10 +190,10 @@
"c": "EXTERN_C",
"t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
@@ -1011,6 +1011,281 @@
"hc_black": "default: #FFFFFF"
}
},
{
"c": "long",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
"dark_vs": "storage.type: #569CD6",
"light_vs": "storage.type: #0000FF",
"hc_black": "storage.type: #569CD6"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.qualified_type.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "double",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
"dark_vs": "storage.type: #569CD6",
"light_vs": "storage.type: #0000FF",
"hc_black": "storage.type: #569CD6"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "operator",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp keyword.other.operator.overload.cpp",
"r": {
"dark_plus": "keyword.other.operator: #C586C0",
"light_plus": "keyword.other.operator: #AF00DB",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword.other.operator: #C586C0"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "\"\"",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp entity.name.operator.custom-literal.cpp",
"r": {
"dark_plus": "entity.name.operator.custom-literal: #DCDCAA",
"light_plus": "entity.name.operator.custom-literal: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "_w",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp entity.name.operator.custom-literal.cpp",
"r": {
"dark_plus": "entity.name.operator.custom-literal: #DCDCAA",
"light_plus": "entity.name.operator.custom-literal: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "(",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp punctuation.section.parameters.begin.bracket.round.special.operator-overload.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "long",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp meta.function.definition.parameters.special.operator-overload.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
"dark_vs": "storage.type: #569CD6",
"light_vs": "storage.type: #0000FF",
"hc_black": "storage.type: #569CD6"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp meta.function.definition.parameters.special.operator-overload.cpp meta.parameter.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "double",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp meta.function.definition.parameters.special.operator-overload.cpp meta.parameter.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
"dark_vs": "storage.type: #569CD6",
"light_vs": "storage.type: #0000FF",
"hc_black": "storage.type: #569CD6"
}
},
{
"c": ")",
"t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp punctuation.section.parameters.end.bracket.round.special.operator-overload.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": ";",
"t": "source.cpp punctuation.terminator.statement.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "#",
"t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp",
"r": {
"dark_plus": "keyword.control: #C586C0",
"light_plus": "keyword.control: #AF00DB",
"dark_vs": "keyword.control: #569CD6",
"light_vs": "keyword.control: #0000FF",
"hc_black": "keyword.control: #C586C0"
}
},
{
"c": "define",
"t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp",
"r": {
"dark_plus": "keyword.control: #C586C0",
"light_plus": "keyword.control: #AF00DB",
"dark_vs": "keyword.control: #569CD6",
"light_vs": "keyword.control: #0000FF",
"hc_black": "keyword.control: #C586C0"
}
},
{
"c": " ",
"t": "source.cpp meta.preprocessor.macro.cpp",
"r": {
"dark_plus": "meta.preprocessor: #569CD6",
"light_plus": "meta.preprocessor: #0000FF",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "meta.preprocessor: #569CD6"
}
},
{
"c": "MY_MACRO",
"t": "source.cpp meta.preprocessor.macro.cpp entity.name.function.preprocessor.cpp",
"r": {
"dark_plus": "entity.name.function.preprocessor: #569CD6",
"light_plus": "entity.name.function.preprocessor: #0000FF",
"dark_vs": "entity.name.function.preprocessor: #569CD6",
"light_vs": "entity.name.function.preprocessor: #0000FF",
"hc_black": "entity.name.function: #DCDCAA"
}
},
{
"c": "(",
"t": "source.cpp meta.preprocessor.macro.cpp punctuation.definition.parameters.begin.preprocessor.cpp",
"r": {
"dark_plus": "meta.preprocessor: #569CD6",
"light_plus": "meta.preprocessor: #0000FF",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "meta.preprocessor: #569CD6"
}
},
{
"c": "a",
"t": "source.cpp meta.preprocessor.macro.cpp variable.parameter.preprocessor.cpp",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": ",",
"t": "source.cpp meta.preprocessor.macro.cpp punctuation.separator.parameters.cpp",
"r": {
"dark_plus": "meta.preprocessor: #569CD6",
"light_plus": "meta.preprocessor: #0000FF",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "meta.preprocessor: #569CD6"
}
},
{
"c": " ",
"t": "source.cpp meta.preprocessor.macro.cpp",
"r": {
"dark_plus": "meta.preprocessor: #569CD6",
"light_plus": "meta.preprocessor: #0000FF",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "meta.preprocessor: #569CD6"
}
},
{
"c": "b",
"t": "source.cpp meta.preprocessor.macro.cpp variable.parameter.preprocessor.cpp",
"r": {
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": ")",
"t": "source.cpp meta.preprocessor.macro.cpp punctuation.definition.parameters.end.preprocessor.cpp",
"r": {
"dark_plus": "meta.preprocessor: #569CD6",
"light_plus": "meta.preprocessor: #0000FF",
"dark_vs": "meta.preprocessor: #569CD6",
"light_vs": "meta.preprocessor: #0000FF",
"hc_black": "meta.preprocessor: #569CD6"
}
},
{
"c": "int",
"t": "source.cpp meta.function.definition.cpp meta.qualified_type.cpp storage.type.primitive.cpp storage.type.built-in.primitive.cpp",
@@ -1099,6 +1374,292 @@
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "1",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": ".",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.point.cpp",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": "2",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": "_w",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.other.unit.user-defined.cpp",
"r": {
"dark_plus": "keyword.other.unit: #B5CEA8",
"light_plus": "keyword.other.unit: #09885A",
"dark_vs": "keyword.other.unit: #B5CEA8",
"light_vs": "keyword.other.unit: #09885A",
"hc_black": "keyword.other.unit: #B5CEA8"
}
},
{
"c": ";",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp",
"r": {
"dark_plus": "comment: #6A9955",
"light_plus": "comment: #008000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": "//",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp punctuation.definition.comment.cpp",
"r": {
"dark_plus": "comment: #6A9955",
"light_plus": "comment: #008000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": " calls operator \"\" _w(1.2L)",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp comment.line.double-slash.cpp",
"r": {
"dark_plus": "comment: #6A9955",
"light_plus": "comment: #008000",
"dark_vs": "comment: #6A9955",
"light_vs": "comment: #008000",
"hc_black": "comment: #7CA668"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "asm",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp storage.type.asm.cpp",
"r": {
"dark_plus": "storage.type: #569CD6",
"light_plus": "storage.type: #0000FF",
"dark_vs": "storage.type: #569CD6",
"light_vs": "storage.type: #0000FF",
"hc_black": "storage.type: #569CD6"
}
},
{
"c": "(",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp punctuation.section.parens.begin.bracket.round.assembly.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "\"",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp punctuation.definition.string.begin.assembly.cpp",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "movl %a %b",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp meta.embedded.assembly.cpp",
"r": {
"dark_plus": "meta.embedded.assembly: #CE9178",
"light_plus": "meta.embedded.assembly: #A31515",
"dark_vs": "meta.embedded.assembly: #CE9178",
"light_vs": "meta.embedded.assembly: #A31515",
"hc_black": "meta.embedded: #FFFFFF"
}
},
{
"c": "\"",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp string.quoted.double.cpp punctuation.definition.string.end.assembly.cpp",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": ")",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp meta.asm.cpp punctuation.section.parens.end.bracket.round.assembly.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": ";",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "MY_MACRO",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp entity.name.function.call.cpp",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "entity.name.function: #DCDCAA"
}
},
{
"c": "(",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.begin.bracket.round.function.call.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "1",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": ",",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.separator.delimiter.comma.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " ",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": "2",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.numeric.decimal.cpp",
"r": {
"dark_plus": "constant.numeric: #B5CEA8",
"light_plus": "constant.numeric: #09885A",
"dark_vs": "constant.numeric: #B5CEA8",
"light_vs": "constant.numeric: #09885A",
"hc_black": "constant.numeric: #B5CEA8"
}
},
{
"c": ")",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.section.arguments.end.bracket.round.function.call.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": ";",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp punctuation.terminator.statement.cpp",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
"c": " Rectangle rect",
"t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp",
@@ -5,8 +5,8 @@
import * as fs from 'fs';
import * as path from 'path';
import { commands, CompletionItem, CompletionItemKind, ExtensionContext, languages, Position, Range, SnippetString, TextEdit, window, workspace } from 'vscode';
import { Disposable, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
import { commands, CompletionItem, CompletionItemKind, ExtensionContext, languages, Position, Range, SnippetString, TextEdit, window, workspace, TextDocument, CompletionContext, CancellationToken, ProviderResult, CompletionList } from 'vscode';
import { Disposable, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, ProvideCompletionItemsSignature } from 'vscode-languageclient';
import * as nls from 'vscode-nls';
import { getCustomDataPathsFromAllExtensions, getCustomDataPathsInAllWorkspaces } from './customData';
@@ -43,6 +43,31 @@ export function activate(context: ExtensionContext) {
},
initializationOptions: {
dataPaths
},
middleware: {
// testing the replace / insert mode
provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> {
function updateRanges(item: CompletionItem) {
const range = item.range;
if (range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) {
item.range2 = { inserting: new Range(range.start, position), replacing: range };
item.range = undefined;
}
}
function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined {
if (r) {
(Array.isArray(r) ? r : r.items).forEach(updateRanges);
}
return r;
}
const isThenable = <T>(obj: ProviderResult<T>): obj is Thenable<T> => obj && (<any>obj)['then'];
const r = next(document, position, context, token);
if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) {
return r.then(updateProposals);
}
return updateProposals(r);
}
}
};
@@ -783,6 +783,17 @@
}
}
],
"configurationDefaults": {
"[css]": {
"editor.suggest.insertMode": "replace"
},
"[scss]": {
"editor.suggest.insertMode": "replace"
},
"[less]": {
"editor.suggest.insertMode": "replace"
}
},
"jsonValidation": [
{
"fileMatch": "*.css-data.json",
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "CSS contributions to package.json",
"type": "object",
"properties": {
@@ -9,7 +9,7 @@
},
"main": "./out/cssServerMain",
"dependencies": {
"vscode-css-languageservice": "^4.0.3-next.22",
"vscode-css-languageservice": "^4.0.3-next.24",
"vscode-languageserver": "^6.0.0-next.3"
},
"devDependencies": {
@@ -781,10 +781,10 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"
vscode-css-languageservice@^4.0.3-next.22:
version "4.0.3-next.22"
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.22.tgz#ddb23a7086807f0e098f069ad91a8e3b7a696cbb"
integrity sha512-j7+S/0LPn/pTe/CQ8WscDttW5J3aY5Ls6bo/Cz8ZdlBjHl7DbrbZ2rEl5Qd6aKbg0ZdgjWVxGqjjgZFzh+O9/w==
vscode-css-languageservice@^4.0.3-next.24:
version "4.0.3-next.24"
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.24.tgz#6190fb5af4621b7efc1a0772c1a178d996ffb42d"
integrity sha512-7CPBmaQnvkgL7MXZK9vt5R5CwFaQ9TCqWt9aCi9dGm1g0uAgFOwk8+K5+fV2pasI+aoOvb/kLcFjxSSRD03KdA==
dependencies:
vscode-languageserver-textdocument "^1.0.0-next.4"
vscode-languageserver-types "^3.15.0-next.6"
@@ -8,13 +8,13 @@ import * as fs from 'fs';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, Disposable, FormattingOptions, CancellationToken, ProviderResult, TextEdit } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams, DocumentRangeFormattingParams, DocumentRangeFormattingRequest } from 'vscode-languageclient';
import { languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, Disposable, FormattingOptions, CancellationToken, ProviderResult, TextEdit, CompletionContext, CompletionList } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, RequestType, TextDocumentPositionParams, DocumentRangeFormattingParams, DocumentRangeFormattingRequest, ProvideCompletionItemsSignature } from 'vscode-languageclient';
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
import { activateTagClosing } from './tagClosing';
import TelemetryReporter from 'vscode-extension-telemetry';
import { getCustomDataPathsInAllWorkspaces, getCustomDataPathsFromAllExtensions } from './customData';
import { activateMatchingTagPosition as activateMatchingTagSelection } from './matchingTag';
import { activateMirrorCursor } from './mirrorCursor';
namespace TagCloseRequest {
export const type: RequestType<TextDocumentPositionParams, string, any, any> = new RequestType('html/tag');
@@ -72,6 +72,31 @@ export function activate(context: ExtensionContext) {
dataPaths,
provideFormatter: false, // tell the server to not provide formatting capability and ignore the `html.format.enable` setting.
},
middleware: {
// testing the replace / insert mode
provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> {
function updateRanges(item: CompletionItem) {
const range = item.range;
if (range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) {
item.range2 = { inserting: new Range(range.start, position), replacing: range };
item.range = undefined;
}
}
function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined {
if (r) {
(Array.isArray(r) ? r : r.items).forEach(updateRanges);
}
return r;
}
const isThenable = <T>(obj: ProviderResult<T>): obj is Thenable<T> => obj && (<any>obj)['then'];
const r = next(document, position, context, token);
if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) {
return r.then(updateProposals);
}
return updateProposals(r);
}
}
};
// Create the language client and start the client.
@@ -93,7 +118,7 @@ export function activate(context: ExtensionContext) {
return client.sendRequest(MatchingTagPositionRequest.type, param);
};
disposable = activateMatchingTagSelection(matchingTagPositionRequestor, { html: true, handlebars: true }, 'html.autoSelectingMatchingTags');
disposable = activateMirrorCursor(matchingTagPositionRequestor, { html: true, handlebars: true }, 'html.mirrorCursorOnMatchingTag');
toDispose.push(disposable);
disposable = client.onTelemetry(e => {
@@ -1,143 +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 {
window,
workspace,
Disposable,
TextDocument,
Position,
TextEditorSelectionChangeEvent,
Selection,
Range,
WorkspaceEdit
} from 'vscode';
export function activateMatchingTagPosition(
matchingTagPositionProvider: (document: TextDocument, position: Position) => Thenable<Position | null>,
supportedLanguages: { [id: string]: boolean },
configName: string
): Disposable {
let disposables: Disposable[] = [];
window.onDidChangeTextEditorSelection(event => onDidChangeTextEditorSelection(event), null, disposables);
let isEnabled = false;
updateEnabledState();
window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
function updateEnabledState() {
isEnabled = false;
let editor = window.activeTextEditor;
if (!editor) {
return;
}
let document = editor.document;
if (!supportedLanguages[document.languageId]) {
return;
}
if (!workspace.getConfiguration(undefined, document.uri).get<boolean>(configName)) {
return;
}
isEnabled = true;
}
let prevCursorCount = 0;
let cursorCount = 0;
let inMirrorMode = false;
function onDidChangeTextEditorSelection(event: TextEditorSelectionChangeEvent) {
if (!isEnabled) {
return;
}
prevCursorCount = cursorCount;
cursorCount = event.selections.length;
if (cursorCount === 1) {
if (inMirrorMode && prevCursorCount === 2) {
return;
}
if (event.selections[0].isEmpty) {
matchingTagPositionProvider(event.textEditor.document, event.selections[0].active).then(position => {
if (position && window.activeTextEditor) {
inMirrorMode = true;
const newCursor = new Selection(position.line, position.character, position.line, position.character);
window.activeTextEditor.selections = [...window.activeTextEditor.selections, newCursor];
}
});
}
}
if (cursorCount === 2 && inMirrorMode) {
// Check two cases
if (event.selections[0].isEmpty && event.selections[1].isEmpty) {
const charBeforePrimarySelection = getCharBefore(event.textEditor.document, event.selections[0].anchor);
const charAfterPrimarySelection = getCharAfter(event.textEditor.document, event.selections[0].anchor);
const charBeforeSecondarySelection = getCharBefore(event.textEditor.document, event.selections[1].anchor);
const charAfterSecondarySelection = getCharAfter(event.textEditor.document, event.selections[1].anchor);
// Exit mirror mode when cursor position no longer mirror
// Unless it's in the case of `<|></|>`
const charBeforeBothPositionRoughlyEqual =
charBeforePrimarySelection === charBeforeSecondarySelection ||
(charBeforePrimarySelection === '/' && charBeforeSecondarySelection === '<') ||
(charBeforeSecondarySelection === '/' && charBeforePrimarySelection === '<');
const charAfterBothPositionRoughlyEqual =
charAfterPrimarySelection === charAfterSecondarySelection ||
(charAfterPrimarySelection === ' ' && charAfterSecondarySelection === '>') ||
(charAfterSecondarySelection === ' ' && charAfterPrimarySelection === '>');
if (!charBeforeBothPositionRoughlyEqual || !charAfterBothPositionRoughlyEqual) {
inMirrorMode = false;
window.activeTextEditor!.selections = [window.activeTextEditor!.selections[0]];
return;
} else {
// Need to cleanup in the case of <div |></div |>
if (
charBeforePrimarySelection === ' ' &&
charAfterPrimarySelection === '>' &&
charBeforeSecondarySelection === ' ' &&
charAfterSecondarySelection === '>'
) {
const primaryBeforeSecondary =
event.textEditor.document.offsetAt(event.selections[0].anchor) <
event.textEditor.document.offsetAt(event.selections[1].anchor);
if (primaryBeforeSecondary) {
inMirrorMode = false;
const cleanupEdit = new WorkspaceEdit();
const cleanupRange = new Range(event.selections[1].anchor.translate(0, -1), event.selections[1].anchor);
cleanupEdit.replace(event.textEditor.document.uri, cleanupRange, '');
window.activeTextEditor!.selections = [window.activeTextEditor!.selections[0]];
workspace.applyEdit(cleanupEdit);
}
}
}
}
}
}
return Disposable.from(...disposables);
}
function getCharBefore(document: TextDocument, position: Position) {
const offset = document.offsetAt(position);
if (offset === 0) {
return '';
}
return document.getText(new Range(document.positionAt(offset - 1), position));
}
function getCharAfter(document: TextDocument, position: Position) {
const offset = document.offsetAt(position);
if (offset === document.getText().length) {
return '';
}
return document.getText(new Range(position, document.positionAt(offset + 1)));
}
@@ -0,0 +1,233 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import {
window,
workspace,
Disposable,
TextDocument,
Position,
TextEditorSelectionChangeEvent,
Selection,
Range,
WorkspaceEdit
} from 'vscode';
export function activateMirrorCursor(
matchingTagPositionProvider: (document: TextDocument, position: Position) => Thenable<Position | null>,
supportedLanguages: { [id: string]: boolean },
configName: string
): Disposable {
let disposables: Disposable[] = [];
window.onDidChangeTextEditorSelection(event => onDidChangeTextEditorSelection(event), null, disposables);
let isEnabled = false;
updateEnabledState();
window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
function updateEnabledState() {
isEnabled = false;
let editor = window.activeTextEditor;
if (!editor) {
return;
}
let document = editor.document;
if (!supportedLanguages[document.languageId]) {
return;
}
if (!workspace.getConfiguration(undefined, document.uri).get<boolean>(configName)) {
return;
}
isEnabled = true;
}
let prevCursors: readonly Selection[] = [];
let cursors: readonly Selection[] = [];
let inMirrorMode = false;
function onDidChangeTextEditorSelection(event: TextEditorSelectionChangeEvent) {
if (!isEnabled) {
return;
}
prevCursors = cursors;
cursors = event.selections;
if (cursors.length === 1) {
if (inMirrorMode && prevCursors.length === 2) {
if (cursors[0].isEqual(prevCursors[0]) || cursors[0].isEqual(prevCursors[1])) {
return;
}
}
if (event.selections[0].isEmpty) {
matchingTagPositionProvider(event.textEditor.document, event.selections[0].active).then(matchingTagPosition => {
if (matchingTagPosition && window.activeTextEditor) {
const charBeforeAndAfterPositionsRoughtlyEqual = isCharBeforeAndAfterPositionsRoughtlyEqual(
event.textEditor.document,
event.selections[0].anchor,
new Position(matchingTagPosition.line, matchingTagPosition.character)
);
if (charBeforeAndAfterPositionsRoughtlyEqual) {
inMirrorMode = true;
const newCursor = new Selection(
matchingTagPosition.line,
matchingTagPosition.character,
matchingTagPosition.line,
matchingTagPosition.character
);
window.activeTextEditor.selections = [...window.activeTextEditor.selections, newCursor];
}
}
});
}
}
const exitMirrorMode = () => {
inMirrorMode = false;
window.activeTextEditor!.selections = [window.activeTextEditor!.selections[0]];
};
if (cursors.length === 2 && inMirrorMode) {
if (event.selections[0].isEmpty && event.selections[1].isEmpty) {
if (
prevCursors.length === 2 &&
event.selections[0].anchor.line !== prevCursors[0].anchor.line &&
event.selections[1].anchor.line !== prevCursors[0].anchor.line
) {
exitMirrorMode();
return;
}
const charBeforeAndAfterPositionsRoughtlyEqual = isCharBeforeAndAfterPositionsRoughtlyEqual(
event.textEditor.document,
event.selections[0].anchor,
event.selections[1].anchor
);
if (!charBeforeAndAfterPositionsRoughtlyEqual) {
exitMirrorMode();
return;
} else {
// Need to cleanup in the case of <div |></div |>
if (
shouldDoCleanupForHtmlAttributeInput(
event.textEditor.document,
event.selections[0].anchor,
event.selections[1].anchor
)
) {
const cleanupEdit = new WorkspaceEdit();
const cleanupRange = new Range(event.selections[1].anchor.translate(0, -1), event.selections[1].anchor);
cleanupEdit.replace(event.textEditor.document.uri, cleanupRange, '');
exitMirrorMode();
workspace.applyEdit(cleanupEdit);
}
}
}
}
}
return Disposable.from(...disposables);
}
function getCharBefore(document: TextDocument, position: Position) {
const offset = document.offsetAt(position);
if (offset === 0) {
return '';
}
return document.getText(new Range(document.positionAt(offset - 1), position));
}
function getCharAfter(document: TextDocument, position: Position) {
const offset = document.offsetAt(position);
if (offset === document.getText().length) {
return '';
}
return document.getText(new Range(position, document.positionAt(offset + 1)));
}
// Check if chars before and after the two positions are equal
// For the chars before, `<` and `/` are consiered equal to handle the case of `<|></|>`
function isCharBeforeAndAfterPositionsRoughtlyEqual(document: TextDocument, firstPos: Position, secondPos: Position) {
const charBeforePrimarySelection = getCharBefore(document, firstPos);
const charAfterPrimarySelection = getCharAfter(document, firstPos);
const charBeforeSecondarySelection = getCharBefore(document, secondPos);
const charAfterSecondarySelection = getCharAfter(document, secondPos);
/**
* Special case for exiting
* |<div>
* |</div>
*/
if (
charBeforePrimarySelection === ' ' &&
charBeforeSecondarySelection === ' ' &&
charAfterPrimarySelection === '<' &&
charAfterSecondarySelection === '<'
) {
return false;
}
/**
* Special case for exiting
* | <div>
* | </div>
*/
if (charBeforePrimarySelection === '\n' && charBeforeSecondarySelection === '\n') {
return false;
}
/**
* Special case for exiting
* <div>|
* </div>|
*/
if (charAfterPrimarySelection === '\n' && charAfterSecondarySelection === '\n') {
return false;
}
// Exit mirror mode when cursor position no longer mirror
// Unless it's in the case of `<|></|>`
const charBeforeBothPositionRoughlyEqual =
charBeforePrimarySelection === charBeforeSecondarySelection ||
(charBeforePrimarySelection === '/' && charBeforeSecondarySelection === '<') ||
(charBeforeSecondarySelection === '/' && charBeforePrimarySelection === '<');
const charAfterBothPositionRoughlyEqual =
charAfterPrimarySelection === charAfterSecondarySelection ||
(charAfterPrimarySelection === ' ' && charAfterSecondarySelection === '>') ||
(charAfterSecondarySelection === ' ' && charAfterPrimarySelection === '>');
return charBeforeBothPositionRoughlyEqual && charAfterBothPositionRoughlyEqual;
}
function shouldDoCleanupForHtmlAttributeInput(document: TextDocument, firstPos: Position, secondPos: Position) {
// Need to cleanup in the case of <div |></div |>
const charBeforePrimarySelection = getCharBefore(document, firstPos);
const charAfterPrimarySelection = getCharAfter(document, firstPos);
const charBeforeSecondarySelection = getCharBefore(document, secondPos);
const charAfterSecondarySelection = getCharAfter(document, secondPos);
const primaryBeforeSecondary = document.offsetAt(firstPos) < document.offsetAt(secondPos);
/**
* Check two cases
* <div |></div >
* <div | id="a"></div >
* Before 1st cursor: ` `
* After 1st cursor: `>` or ` `
* Before 2nd cursor: ` `
* After 2nd cursor: `>`
*/
return (
primaryBeforeSecondary &&
charBeforePrimarySelection === ' ' &&
(charAfterPrimarySelection === '>' || charAfterPrimarySelection === ' ') &&
charBeforeSecondarySelection === ' ' &&
charAfterSecondarySelection === '>'
);
}
+10 -2
View File
@@ -161,11 +161,11 @@
"default": true,
"description": "%html.autoClosingTags%"
},
"html.autoSelectingMatchingTags": {
"html.mirrorCursorOnMatchingTag": {
"type": "boolean",
"scope": "resource",
"default": true,
"description": "%html.autoSelectingMatchingTags%"
"description": "%html.mirrorCursorOnMatchingTag%"
},
"html.trace.server": {
"type": "string",
@@ -180,6 +180,14 @@
}
}
},
"configurationDefaults": {
"[html]": {
"editor.suggest.insertMode": "replace"
},
"[handlebars]": {
"editor.suggest.insertMode": "replace"
}
},
"jsonValidation": [
{
"fileMatch": "*.html-data.json",
@@ -25,5 +25,5 @@
"html.validate.scripts": "Controls whether the built-in HTML language support validates embedded scripts.",
"html.validate.styles": "Controls whether the built-in HTML language support validates embedded styles.",
"html.autoClosingTags": "Enable/disable autoclosing of HTML tags.",
"html.autoSelectingMatchingTags": "Enable/disable auto selecting matching HTML tags."
"html.mirrorCursorOnMatchingTag": "Enable/disable mirroring cursor on matching HTML tag."
}
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "HTML contributions to package.json",
"type": "object",
"properties": {
@@ -9,7 +9,7 @@
},
"main": "./out/htmlServerMain",
"dependencies": {
"vscode-css-languageservice": "^4.0.3-next.22",
"vscode-css-languageservice": "^4.0.3-next.24",
"vscode-html-languageservice": "^3.0.4-next.11",
"vscode-languageserver": "^6.0.0-next.3",
"vscode-nls": "^4.1.1",
@@ -611,10 +611,10 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"
vscode-css-languageservice@^4.0.3-next.22:
version "4.0.3-next.22"
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.22.tgz#ddb23a7086807f0e098f069ad91a8e3b7a696cbb"
integrity sha512-j7+S/0LPn/pTe/CQ8WscDttW5J3aY5Ls6bo/Cz8ZdlBjHl7DbrbZ2rEl5Qd6aKbg0ZdgjWVxGqjjgZFzh+O9/w==
vscode-css-languageservice@^4.0.3-next.24:
version "4.0.3-next.24"
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.24.tgz#6190fb5af4621b7efc1a0772c1a178d996ffb42d"
integrity sha512-7CPBmaQnvkgL7MXZK9vt5R5CwFaQ9TCqWt9aCi9dGm1g0uAgFOwk8+K5+fV2pasI+aoOvb/kLcFjxSSRD03KdA==
dependencies:
vscode-languageserver-textdocument "^1.0.0-next.4"
vscode-languageserver-types "^3.15.0-next.6"
-1
View File
@@ -13,5 +13,4 @@ Supported image formats:
- `*.bmp`
- `*.gif`
- `*.ico`
- `*.tga`
- `*.webp`
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "image-preview",
"displayName": "%displayName%",
"description": "%description%",
"extensionKind": "ui",
"extensionKind": ["ui", "workspace"],
"version": "1.0.0",
"publisher": "vscode",
"icon": "icon.png",
@@ -10,8 +10,16 @@ import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
const localize = nls.loadMessageBundle();
import { workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken, ProviderResult, TextEdit, Range, Disposable } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams, DocumentRangeFormattingRequest } from 'vscode-languageclient';
import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext
} from 'vscode';
import {
LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType,
DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams,
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature
} from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
import { hash } from './utils/hash';
@@ -36,6 +44,10 @@ namespace SchemaAssociationNotification {
export const type: NotificationType<ISchemaAssociations, any> = new NotificationType('json/schemaAssociations');
}
namespace ResultLimitReachedNotification {
export const type: NotificationType<string, any> = new NotificationType('json/resultLimitReached');
}
interface IPackageInfo {
name: string;
version: string;
@@ -132,6 +144,29 @@ export function activate(context: ExtensionContext) {
}
next(uri, diagnostics);
},
// testing the replace / insert mode
provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> {
function updateRanges(item: CompletionItem) {
const range = item.range;
if (range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) {
item.range2 = { inserting: new Range(range.start, position), replacing: range };
item.range = undefined;
}
}
function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined {
if (r) {
(Array.isArray(r) ? r : r.items).forEach(updateRanges);
}
return r;
}
const isThenable = <T>(obj: ProviderResult<T>): obj is Thenable<T> => obj && (<any>obj)['then'];
const r = next(document, position, context, token);
if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) {
return r.then(updateProposals);
}
return updateProposals(r);
}
}
};
@@ -239,6 +274,12 @@ export function activate(context: ExtensionContext) {
updateFormatterRegistration();
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
toDispose.push(workspace.onDidChangeConfiguration(e => e.affectsConfiguration('html.format.enable') && updateFormatterRegistration()));
client.onNotification(ResultLimitReachedNotification.type, message => {
window.showInformationMessage(`${message}\nUse setting 'json.maxItemsComputed' to configure the limit.`);
});
});
let languageConfiguration: LanguageConfiguration = {
@@ -320,6 +361,8 @@ function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
function getSettings(): Settings {
let httpSettings = workspace.getConfiguration('http');
let resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
let settings: Settings = {
http: {
proxy: httpSettings.get('proxy'),
@@ -327,7 +370,7 @@ function getSettings(): Settings {
},
json: {
schemas: [],
resultLimit: 5000
resultLimit
}
};
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
@@ -422,5 +465,4 @@ function readJSONFile(location: string) {
console.log(`Problems reading ${location}: ${e}`);
return {};
}
}
+120 -108
View File
@@ -1,113 +1,125 @@
{
"name": "json-language-features",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"publisher": "vscode",
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
"vscode": "0.10.x"
},
"icon": "icons/json.png",
"activationEvents": [
"onLanguage:json",
"onLanguage:jsonc"
],
"main": "./client/out/jsonMain",
"enableProposedApi": true,
"scripts": {
"compile": "gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
"watch": "gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",
"postinstall": "cd server && yarn install",
"install-client-next": "yarn add vscode-languageclient@next"
},
"categories": [
"Programming Languages"
],
"contributes": {
"configuration": {
"id": "json",
"order": 20,
"type": "object",
"title": "JSON",
"properties": {
"json.schemas": {
"type": "array",
"scope": "resource",
"description": "%json.schemas.desc%",
"items": {
"type": "object",
"default": {
"fileMatch": [
"/myfile"
],
"url": "schemaURL"
},
"properties": {
"url": {
"type": "string",
"default": "/user.schema.json",
"description": "%json.schemas.url.desc%"
},
"fileMatch": {
"type": "array",
"items": {
"type": "string",
"default": "MyFile.json",
"description": "%json.schemas.fileMatch.item.desc%"
},
"minItems": 1,
"description": "%json.schemas.fileMatch.desc%"
},
"schema": {
"$ref": "http://json-schema.org/draft-07/schema#",
"description": "%json.schemas.schema.desc%"
}
}
}
},
"json.format.enable": {
"type": "boolean",
"scope": "window",
"default": true,
"description": "%json.format.enable.desc%"
},
"json.trace.server": {
"type": "string",
"scope": "window",
"enum": [
"off",
"messages",
"verbose"
],
"default": "off",
"description": "%json.tracing.desc%"
},
"json.colorDecorators.enable": {
"type": "boolean",
"scope": "window",
"default": true,
"description": "%json.colorDecorators.enable.desc%",
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
}
}
"name": "json-language-features",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"publisher": "vscode",
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
"vscode": "0.10.x"
},
"configurationDefaults": {
"[json]": {
"editor.quickSuggestions": {
"strings": true
"icon": "icons/json.png",
"activationEvents": [
"onLanguage:json",
"onLanguage:jsonc"
],
"main": "./client/out/jsonMain",
"enableProposedApi": true,
"scripts": {
"compile": "gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
"watch": "gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",
"postinstall": "cd server && yarn install",
"install-client-next": "yarn add vscode-languageclient@next"
},
"categories": [
"Programming Languages"
],
"contributes": {
"configuration": {
"id": "json",
"order": 20,
"type": "object",
"title": "JSON",
"properties": {
"json.schemas": {
"type": "array",
"scope": "resource",
"description": "%json.schemas.desc%",
"items": {
"type": "object",
"default": {
"fileMatch": [
"/myfile"
],
"url": "schemaURL"
},
"properties": {
"url": {
"type": "string",
"default": "/user.schema.json",
"description": "%json.schemas.url.desc%"
},
"fileMatch": {
"type": "array",
"items": {
"type": "string",
"default": "MyFile.json",
"description": "%json.schemas.fileMatch.item.desc%"
},
"minItems": 1,
"description": "%json.schemas.fileMatch.desc%"
},
"schema": {
"$ref": "http://json-schema.org/draft-07/schema#",
"description": "%json.schemas.schema.desc%"
}
}
}
},
"json.format.enable": {
"type": "boolean",
"scope": "window",
"default": true,
"description": "%json.format.enable.desc%"
},
"json.trace.server": {
"type": "string",
"scope": "window",
"enum": [
"off",
"messages",
"verbose"
],
"default": "off",
"description": "%json.tracing.desc%"
},
"json.colorDecorators.enable": {
"type": "boolean",
"scope": "window",
"default": true,
"description": "%json.colorDecorators.enable.desc%",
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
},
"json.maxItemsComputed": {
"type": "number",
"default": 5000,
"description": "%json.maxItemsComputed.desc%"
}
}
},
"configurationDefaults": {
"[json]": {
"editor.quickSuggestions": {
"strings": true
},
"editor.suggest.insertMode": "replace"
},
"[jsonc]": {
"editor.quickSuggestions": {
"strings": true
},
"editor.suggest.insertMode": "replace"
}
}
}
},
"dependencies": {
"request-light": "^0.2.5",
"vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^6.0.0-next.3",
"vscode-nls": "^4.1.1"
},
"devDependencies": {
"@types/node": "^12.11.7"
}
},
"dependencies": {
"request-light": "^0.2.5",
"vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^6.0.0-next.3",
"vscode-nls": "^4.1.1"
},
"devDependencies": {
"@types/node": "^12.11.7"
}
}
@@ -11,5 +11,6 @@
"json.colorDecorators.enable.desc": "Enables or disables color decorators",
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
"json.schemaResolutionErrorMessage": "Unable to resolve schema.",
"json.clickToRetry": "Click to retry."
"json.clickToRetry": "Click to retry.",
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons)."
}
@@ -63,6 +63,7 @@ The server supports the following settings:
- `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard.
- `url`: The URL of the schema, optional when also a schema is provided.
- `schema`: The schema content.
- `resultLimit`: The max number foldig ranges and otline symbols to be computed (for performance reasons)
```json
{
@@ -153,6 +154,16 @@ Notification:
- method: 'json/schemaContent'
- params: `string` the URL of the schema that has changed.
### Item Limit
If the setting `resultLimit` is set, the JSON language server will limit the number of folding ranges and document symbols computed.
When the limit is reached, a notification `json/resultLimitReached` is sent that can be shown that camn be shown to the user.
Notification:
- method: 'json/resultLimitReached'
- params: a human readable string to show to the user.
## Try
The JSON language server is shipped with [Visual Studio Code](https://code.visualstudio.com/) as part of the built-in VSCode extension `json-language-features`. The server is started when the first JSON file is opened. The [VSCode JSON documentation](https://code.visualstudio.com/docs/languages/json) for detailed information on the user experience and has more information on how to configure the language support.
@@ -14,7 +14,7 @@
"dependencies": {
"jsonc-parser": "^2.2.0",
"request-light": "^0.2.5",
"vscode-json-languageservice": "^3.4.7",
"vscode-json-languageservice": "^3.4.9",
"vscode-languageserver": "^6.0.0-next.3",
"vscode-uri": "^2.1.1"
},
@@ -35,6 +35,10 @@ namespace SchemaContentChangeNotification {
export const type: NotificationType<string, any> = new NotificationType('json/schemaContent');
}
namespace ResultLimitReachedNotification {
export const type: NotificationType<string, any> = new NotificationType('json/resultLimitReached');
}
namespace ForceValidateRequest {
export const type: RequestType<string, Diagnostic[], any, any> = new RequestType('json/validate');
}
@@ -211,7 +215,7 @@ namespace LimitExceededWarnings {
} else {
warning = { features: { [name]: name } };
warning.timeout = setTimeout(() => {
connection.window.showInformationMessage(`${posix.basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
connection.sendNotification(ResultLimitReachedNotification.type, `${posix.basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
warning.timeout = undefined;
}, 2000);
pendingWarnings[uri] = warning;
@@ -80,10 +80,10 @@ request-light@^0.2.5:
https-proxy-agent "^2.2.3"
vscode-nls "^4.1.1"
vscode-json-languageservice@^3.4.7:
version "3.4.7"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.7.tgz#8d85f3c1d46a1e58e9867d747552fb8c83d934fd"
integrity sha512-y3MN2+/yph3yoIHGmHu4ScYpm285L58XVvfGkd49xTQzLja4apxSbwzsYcP9QsqS0W7KuvoyiPhqksiudoMwjg==
vscode-json-languageservice@^3.4.9:
version "3.4.9"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.9.tgz#7ce485bb0f9a07b4d879c988baac9be2222909ad"
integrity sha512-4VCpZ9ooea/Zc/MTnj1ccc9C7rqcoinKVQLhLoi6jw6yueSf4y4tg/YIUiPPVMlEAG7ZCPS+NVmqxisQ+mOsSw==
dependencies:
jsonc-parser "^2.2.0"
vscode-languageserver-textdocument "^1.0.0-next.4"
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Markdown contributions to package.json",
"type": "object",
"properties": {
@@ -29,4 +29,4 @@
}
}
}
}
}
@@ -242,8 +242,11 @@ export class MarkdownEngine {
if (uri.path[0] === '/') {
const root = vscode.workspace.getWorkspaceFolder(this.currentDocument!);
if (root) {
uri = uri.with({
path: path.join(root.uri.fsPath, uri.path),
const fileUri = vscode.Uri.file(path.join(root.uri.fsPath, uri.fsPath));
uri = fileUri.with({
scheme: uri.scheme,
fragment: uri.fragment,
query: uri.query,
});
}
}
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Location, getLocation, createScanner, SyntaxKind, ScanError } from 'jsonc-parser';
import { Location, getLocation, createScanner, SyntaxKind, ScanError, JSONScanner } from 'jsonc-parser';
import { basename } from 'path';
import { BowerJSONContribution } from './bowerJSONContribution';
import { PackageJSONContribution } from './packageJSONContribution';
@@ -111,7 +111,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
add: (suggestion: CompletionItem) => {
if (!proposed[suggestion.label]) {
proposed[suggestion.label] = true;
suggestion.range = overwriteRange;
suggestion.range2 = { replacing: overwriteRange, inserting: new Range(overwriteRange.start, overwriteRange.start) };
items.push(suggestion);
}
},
@@ -123,8 +123,9 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
let collectPromise: Thenable<any> | null = null;
if (location.isAtPropertyKey) {
const addValue = !location.previousNode || !location.previousNode.colonOffset;
const isLast = this.isLast(document, position);
const scanner = createScanner(document.getText(), true);
const addValue = !location.previousNode || !this.hasColonAfter(scanner, location.previousNode.offset + location.previousNode.length);
const isLast = this.isLast(scanner, document.offsetAt(position));
collectPromise = this.jsonContribution.collectPropertySuggestions(fileName, location, currentWord, addValue, isLast, collector);
} else {
if (location.path.length === 0) {
@@ -153,15 +154,19 @@ export class JSONCompletionItemProvider implements CompletionItemProvider {
return text.substring(i + 1, position.character);
}
private isLast(document: TextDocument, position: Position): boolean {
const scanner = createScanner(document.getText(), true);
scanner.setPosition(document.offsetAt(position));
private isLast(scanner: JSONScanner, offset: number): boolean {
scanner.setPosition(offset);
let nextToken = scanner.scan();
if (nextToken === SyntaxKind.StringLiteral && scanner.getTokenError() === ScanError.UnexpectedEndOfString) {
nextToken = scanner.scan();
}
return nextToken === SyntaxKind.CloseBraceToken || nextToken === SyntaxKind.EOF;
}
private hasColonAfter(scanner: JSONScanner, offset: number): boolean {
scanner.setPosition(offset);
return scanner.scan() === SyntaxKind.ColonToken;
}
}
export const xhrDisabled = () => Promise.reject({ responseText: 'Use of online resources is disabled.' });
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "3.7.3-insiders.20191123"
"typescript": "3.7.3"
},
"scripts": {
"postinstall": "node ./postinstall"
+15
View File
@@ -19,6 +19,11 @@
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:search-result ./tsconfig.json"
},
"contributes": {
"configurationDefaults": {
"[search-result]": {
"editor.lineNumbers": "off"
}
},
"commands": [
{
"command": "searchResult.rerunSearch",
@@ -28,6 +33,15 @@
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
},
{
"command": "searchResult.rerunSearchWithContext",
"title": "%searchResult.rerunSearchWithContext.title%",
"category": "Search Result",
"icon": {
"light": "./src/media/refresh-light.svg",
"dark": "./src/media/refresh-dark.svg"
}
}
],
"menus": {
@@ -35,6 +49,7 @@
{
"command": "searchResult.rerunSearch",
"when": "editorLangId == search-result",
"alt": "searchResult.rerunSearchWithContext",
"group": "navigation"
}
]
+2 -1
View File
@@ -1,5 +1,6 @@
{
"displayName": "Search Result",
"description": "Provides syntax highlighting and language features for tabbed search results.",
"searchResult.rerunSearch.title": "Search Again"
"searchResult.rerunSearch.title": "Search Again",
"searchResult.rerunSearchWithContext.title": "Search Again (With Context)"
}
+77 -64
View File
@@ -7,81 +7,93 @@ import * as vscode from 'vscode';
import * as pathUtils from 'path';
const FILE_LINE_REGEX = /^(\S.*):$/;
const RESULT_LINE_REGEX = /^(\s+)(\d+):(\s+)(.*)$/;
const RESULT_LINE_REGEX = /^(\s+)(\d+)(:| )(\s+)(.*)$/;
const SEARCH_RESULT_SELECTOR = { language: 'search-result' };
const DIRECTIVES = ['# Query:', '# Flags:', '# Including:', '# Excluding:', '# ContextLines:'];
const FLAGS = ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch'];
let cachedLastParse: { version: number, parse: ParsedSearchResults } | undefined;
export function activate() {
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch')),
vscode.commands.registerCommand('searchResult.rerunSearchWithContext', () => vscode.commands.executeCommand('search.action.rerunEditorSearchWithContext')),
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch'));
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
const results = parseSearchResults(document, token)
.filter(isFileLine)
.map(line => new vscode.DocumentSymbol(
line.path,
'',
vscode.SymbolKind.File,
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
line.location.originSelectionRange!,
));
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
const results = parseSearchResults(document, token)
.filter(isFileLine)
.map(line => new vscode.DocumentSymbol(
line.path,
'',
vscode.SymbolKind.File,
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
line.location.originSelectionRange!,
));
return results;
}
});
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
const line = document.lineAt(position.line);
if (position.line > 3) { return []; }
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
const header = Array.from({ length: 4 }).map((_, i) => document.lineAt(i).text);
return ['# Query:', '# Flags:', '# Including:', '# Excluding:']
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
return results;
}
}),
if (line.text.indexOf('# Flags:') === -1) { return []; }
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
return ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch']
.filter(flag => line.text.indexOf(flag) === -1)
.map(flag => ({ label: flag, insertText: flag + ' ' }));
}
}, '#');
const line = document.lineAt(position.line);
if (position.line > 3) { return []; }
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
const header = Array.from({ length: DIRECTIVES.length }).map((_, i) => document.lineAt(i).text);
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
const lineResult = parseSearchResults(document, token)[position.line];
if (!lineResult) { return []; }
if (lineResult.type === 'file') {
// TODO: The multi-match peek UX isnt very smooth.
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
return [];
return DIRECTIVES
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
}
if (line.text.indexOf('# Flags:') === -1) { return []; }
return FLAGS
.filter(flag => line.text.indexOf(flag) === -1)
.map(flag => ({ label: flag, insertText: flag + ' ' }));
}
}, '#'),
return [lineResult.location];
}
});
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
const lineResult = parseSearchResults(document, token)[position.line];
if (!lineResult) { return []; }
if (lineResult.type === 'file') {
// TODO: The multi-match peek UX isnt very smooth.
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
return [];
}
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
return parseSearchResults(document, token)
.filter(({ type }) => type === 'file')
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
}
});
const translateRangeSidewaysBy = (r: vscode.Range, n: number) =>
r.with({ start: new vscode.Position(r.start.line, Math.max(0, n - r.start.character)), end: new vscode.Position(r.end.line, Math.max(0, n - r.end.character)) });
vscode.window.onDidChangeActiveTextEditor(e => {
if (e?.document.languageId === 'search-result') {
// Clear the parse whenever we open a new editor.
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
cachedLastParse = undefined;
}
});
return [{
...lineResult.location,
targetSelectionRange: translateRangeSidewaysBy(lineResult.location.targetSelectionRange!, position.character - 1)
}];
}
}),
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
return parseSearchResults(document, token)
.filter(({ type }) => type === 'file')
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
}
}),
vscode.window.onDidChangeActiveTextEditor(e => {
if (e?.document.languageId === 'search-result') {
// Clear the parse whenever we open a new editor.
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
cachedLastParse = undefined;
}
}),
{ dispose() { cachedLastParse = undefined; } }
);
}
@@ -160,13 +172,14 @@ function parseSearchResults(document: vscode.TextDocument, token: vscode.Cancell
const resultLine = RESULT_LINE_REGEX.exec(line);
if (resultLine) {
const [, indentation, _lineNumber, resultIndentation] = resultLine;
const [, indentation, _lineNumber, seperator, resultIndentation] = resultLine;
const lineNumber = +_lineNumber - 1;
const resultStart = (indentation + _lineNumber + ':' + resultIndentation).length;
const resultStart = (indentation + _lineNumber + seperator + resultIndentation).length;
const metadataOffset = (indentation + _lineNumber + seperator).length;
const location: vscode.LocationLink = {
targetRange: new vscode.Range(Math.max(lineNumber - 3, 0), 0, lineNumber + 3, line.length),
targetSelectionRange: new vscode.Range(lineNumber, 0, lineNumber, line.length),
targetSelectionRange: new vscode.Range(lineNumber, metadataOffset, lineNumber, metadataOffset),
targetUri: currentTarget,
originSelectionRange: new vscode.Range(i, resultStart, i, line.length),
};
@@ -3,7 +3,7 @@
"scopeName": "text.searchResult",
"patterns": [
{
"match": "^# (Query|Flags|Including|Excluding): .*$",
"match": "^# (Query|Flags|Including|Excluding|ContextLines): .*$",
"name": "comment"
},
{
@@ -9,7 +9,8 @@
"entity.name.function",
"support.function",
"support.constant.handlebars",
"source.powershell variable.other.member"
"source.powershell variable.other.member",
"entity.name.operator.custom-literal" // See https://en.cppreference.com/w/cpp/language/user_literal
],
"settings": {
"foreground": "#DCDCAA"
@@ -171,7 +171,8 @@
},
{
"scope": [
"meta.preprocessor"
"meta.preprocessor",
"entity.name.function.preprocessor"
],
"settings": {
"foreground": "#569cd6"
@@ -226,6 +227,7 @@
"scope": [
"string",
"entity.name.operator.custom-literal.string",
"meta.embedded.assembly"
],
"settings": {
"foreground": "#ce9178"
@@ -9,7 +9,8 @@
"entity.name.function",
"support.function",
"support.constant.handlebars",
"source.powershell variable.other.member"
"source.powershell variable.other.member",
"entity.name.operator.custom-literal" // See https://en.cppreference.com/w/cpp/language/user_literal
],
"settings": {
"foreground": "#795E26"
@@ -169,7 +169,8 @@
},
{
"scope": [
"meta.preprocessor"
"meta.preprocessor",
"entity.name.function.preprocessor"
],
"settings": {
"foreground": "#0000ff"
@@ -218,6 +219,7 @@
"scope": [
"string",
"entity.name.operator.custom-literal.string",
"meta.embedded.assembly"
],
"settings": {
"foreground": "#a31515"
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TypeScript contributions to package.json",
"type": "object",
"properties": {
@@ -28,4 +28,4 @@
}
}
}
}
}
@@ -60,7 +60,7 @@ export interface ITypeScriptServer {
}
export interface TsServerDelegate {
onFatalError(command: string): void;
onFatalError(command: string, error: Error): void;
}
export interface TsServerProcess {
@@ -222,21 +222,13 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
if (!executeInfo.token || !executeInfo.token.isCancellationRequested) {
/* __GDPR__
"languageServiceErrorResponse" : {
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"stack" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"errortext" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"${include}": [
"${TypeScriptCommonProperties}"
"${TypeScriptCommonProperties}",
"${TypeScriptRequestErrorProperties}"
]
}
*/
this._telemetryReporter.logTelemetry('languageServiceErrorResponse', {
command: err.serverCommand,
message: err.serverMessage || '',
stack: err.serverStack || '',
errortext: err.serverErrorText || '',
});
this._telemetryReporter.logTelemetry('languageServiceErrorResponse', err.telemetry);
}
}
@@ -367,9 +359,8 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
} else if (SyntaxRoutingTsServer.sharedCommands.has(command)) {
// Dispatch to both server but only return from syntax one
const enum RequestState { Unresolved, Resolved, Errored }
let syntaxRequestState = RequestState.Unresolved;
let semanticRequestState = RequestState.Unresolved;
let syntaxRequestState: RequestState.State = RequestState.Unresolved;
let semanticRequestState: RequestState.State = RequestState.Unresolved;
// Also make sure we never cancel requests to just one server
let token: vscode.CancellationToken | undefined = undefined;
@@ -394,16 +385,16 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
semanticRequest
.then(result => {
semanticRequestState = RequestState.Resolved;
if (syntaxRequestState === RequestState.Errored) {
if (syntaxRequestState.type === RequestState.Type.Errored) {
// We've gone out of sync
this._delegate.onFatalError(command);
this._delegate.onFatalError(command, syntaxRequestState.err);
}
return result;
}, err => {
semanticRequestState = RequestState.Errored;
semanticRequestState = new RequestState.Errored(err);
if (syntaxRequestState === RequestState.Resolved) {
// We've gone out of sync
this._delegate.onFatalError(command);
this._delegate.onFatalError(command, err);
}
throw err;
});
@@ -413,16 +404,16 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
syntaxRequest
.then(result => {
syntaxRequestState = RequestState.Resolved;
if (semanticRequestState === RequestState.Errored) {
if (semanticRequestState.type === RequestState.Type.Errored) {
// We've gone out of sync
this._delegate.onFatalError(command);
this._delegate.onFatalError(command, semanticRequestState.err);
}
return result;
}, err => {
syntaxRequestState = RequestState.Errored;
syntaxRequestState = new RequestState.Errored(err);
if (semanticRequestState === RequestState.Resolved) {
// We've gone out of sync
this._delegate.onFatalError(command);
this._delegate.onFatalError(command, err);
}
throw err;
});
@@ -433,3 +424,21 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
}
}
}
namespace RequestState {
export const enum Type { Unresolved, Resolved, Errored }
export const Unresolved = { type: Type.Unresolved } as const;
export const Resolved = { type: Type.Resolved } as const;
export class Errored {
readonly type = Type.Errored;
constructor(
public readonly err: Error
) { }
}
export type State = typeof Unresolved | typeof Resolved | Errored;
}
@@ -7,6 +7,7 @@ import * as Proto from '../protocol';
import { escapeRegExp } from '../utils/regexp';
import { TypeScriptVersion } from '../utils/versionProvider';
export class TypeScriptServerError extends Error {
public static create(
serverId: string,
@@ -31,6 +32,23 @@ export class TypeScriptServerError extends Error {
public get serverCommand() { return this.response.command; }
public get telemetry() {
/* __GDPR__FRAGMENT__
"TypeScriptRequestErrorProperties" : {
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"message" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"stack" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
"errortext" : { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" }
}
*/
return {
command: this.serverCommand,
message: this.serverMessage || '',
stack: this.serverStack || '',
errortext: this.serverErrorText || '',
} as const;
}
/**
* Given a `errorText` from a tsserver request indicating failure in handling a request,
* prepares a payload for telemetry-logging.
@@ -11,7 +11,9 @@ import BufferSyncSupport from './features/bufferSyncSupport';
import { DiagnosticKind, DiagnosticsManager } from './features/diagnostics';
import * as Proto from './protocol';
import { ITypeScriptServer } from './tsServer/server';
import { ITypeScriptServiceClient, ServerResponse, TypeScriptRequests, ExecConfig } from './typescriptService';
import { TypeScriptServerError } from './tsServer/serverError';
import { TypeScriptServerSpawner } from './tsServer/spawner';
import { ExecConfig, ITypeScriptServiceClient, ServerResponse, TypeScriptRequests } from './typescriptService';
import API from './utils/api';
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration';
import { Disposable } from './utils/dispose';
@@ -25,7 +27,6 @@ import Tracer from './utils/tracer';
import { inferredProjectConfig } from './utils/tsconfig';
import { TypeScriptVersionPicker } from './utils/versionPicker';
import { TypeScriptVersion, TypeScriptVersionProvider } from './utils/versionProvider';
import { TypeScriptServerSpawner } from './tsServer/spawner';
const localize = nls.loadMessageBundle();
@@ -314,7 +315,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this.onDidChangeTypeScriptVersion(currentVersion);
let mytoken = ++this.token;
const handle = this.typescriptServerSpawner.spawn(currentVersion, this.configuration, this.pluginManager, {
onFatalError: (command) => this.fatalError(command),
onFatalError: (command, err) => this.fatalError(command, err),
});
this.serverState = new ServerState.Running(handle, apiVersion, undefined, true);
this.lastStart = Date.now();
@@ -670,7 +671,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
}
if (config?.nonRecoverable) {
execution.catch(() => this.fatalError(command));
execution.catch(err => this.fatalError(command, err));
}
return execution;
@@ -704,14 +705,16 @@ export default class TypeScriptServiceClient extends Disposable implements IType
return this.bufferSyncSupport.interuptGetErr(f);
}
private fatalError(command: string): void {
private fatalError(command: string, error: Error): void {
/* __GDPR__
"fatalError" : {
"${include}": [ "${TypeScriptCommonProperties}" ],
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
"${include}": [
"${TypeScriptCommonProperties}",
"${TypeScriptRequestErrorProperties}"
]
}
*/
this.logTelemetry('fatalError', { command });
this.logTelemetry('fatalError', { command, ...(error instanceof TypeScriptServerError ? error.telemetry : {}) });
console.error(`A non-recoverable error occured while executing tsserver command: ${command}`);
if (this.serverState.type === ServerState.Type.Running) {
@@ -101,5 +101,5 @@ export class ResourceMap<T> {
}
export function isWindowsPath(path: string): boolean {
return /^[a-zA-Z]:\\/.test(path);
return /^[a-zA-Z]:[\/\\]/.test(path);
}
+2 -4
View File
@@ -2824,14 +2824,12 @@ export class ProtocolServer implements vscode.DebugAdapter {
private _sequence: number = 1;
private _pendingRequests = new Map<number, (response: DebugProtocol.Response) => void>();
constructor() {
}
public handleMessage(message: DebugProtocol.ProtocolMessage): void {
this.dispatch(message);
}
public stop(): void {
public dispose() {
}
public sendEvent(event: DebugProtocol.Event): void {
@@ -3817,7 +3815,7 @@ export class MockDebugAdapterDescriptorFactory implements vscode.DebugAdapterDes
}
createDebugAdapterDescriptor(_session: vscode.DebugSession, _executable: vscode.DebugAdapterExecutable | undefined): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
return new vscode.DebugAdapterInlineImplementation(new MockDebugSession(this.memfs));
return <any>new vscode.DebugAdapterInlineImplementation(new MockDebugSession(this.memfs));
}
}
@@ -916,4 +916,23 @@ suite('workspace-namespace', () => {
const expected2 = 'import2;import1;';
assert.equal(document.getText(), expected2);
});
test('The api workspace.applyEdit failed for some case of mixing resourceChange and textEdit #80688', async function () {
const file1 = await createRandomFile();
const file2 = await createRandomFile();
let we = new vscode.WorkspaceEdit();
we.insert(file1, new vscode.Position(0, 0), 'import1;');
we.insert(file1, new vscode.Position(0, 0), 'import2;');
const file2Name = basename(file2.fsPath);
const file2NewUri = vscode.Uri.parse(file2.toString().replace(file2Name, `new/${file2Name}`));
we.renameFile(file2, file2NewUri);
await vscode.workspace.applyEdit(we);
const document = await vscode.workspace.openTextDocument(file1);
const expected = 'import1;import2;';
// const expected2 = 'import2;import1;';
assert.equal(document.getText(), expected);
});
});
@@ -13,7 +13,7 @@ suite('workspace-namespace', () => {
teardown(closeAllEditors);
test('rootPath', () => {
assert.ok(pathEquals(vscode.workspace.rootPath!, join(__dirname, '../../testWorkspace')));
assert.equal(vscode.workspace.rootPath, undefined);
});
test('workspaceFile', () => {
@@ -8,53 +8,52 @@ import * as jsoncParser from 'jsonc-parser';
export function activate(context: vscode.ExtensionContext): any {
const tokenModifiers = ['static', 'abstract', 'deprecated'];
const tokenTypes = ['strings', 'types', 'structs', 'classes', 'functions', 'variables'];
const legend = new vscode.SemanticColoringLegend(tokenTypes, tokenModifiers);
const tokenTypes = ['type', 'struct', 'class', 'interface', 'enum', 'parameterType', 'function', 'variable'];
const tokenModifiers = ['static', 'abstract', 'deprecated', 'declaration', 'documentation', 'member', 'async'];
/*
* A certain token (at index `i` is encoded using 5 uint32 integers):
* - at index `5*i` - `deltaLine`: token line number, relative to `SemanticColoringArea.line`
* - at index `5*i+1` - `startCharacter`: token start character offset inside the line (inclusive)
* - at index `5*i+2` - `endCharacter`: token end character offset inside the line (exclusive)
* - at index `5*i+3` - `tokenType`: will be looked up in `SemanticColoringLegend.tokenTypes`
* - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticColoringLegend.tokenModifiers`
*/
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
const semanticHighlightProvider: vscode.SemanticColoringProvider = {
provideSemanticColoring(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticColoring> {
const result: number[] = [];
const semanticHighlightProvider: vscode.SemanticTokensProvider = {
provideSemanticTokens(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticTokens> {
const builder = new vscode.SemanticTokensBuilder();
function addToken(value: string, startLine: number, startCharacter: number, length: number) {
const [type, ...modifiers] = value.split('.');
let tokenType = legend.tokenTypes.indexOf(type);
if (tokenType === -1) {
return;
}
let tokenModifiers = 0;
for (let i = 0; i < modifiers.length; i++) {
const index = legend.tokenModifiers.indexOf(modifiers[i]);
if (index !== -1) {
tokenModifiers = tokenModifiers | 1 << index;
}
}
builder.push(startLine, startCharacter, length, tokenType, tokenModifiers);
}
const visitor: jsoncParser.JSONVisitor = {
onObjectProperty: (property: string, _offset: number, length: number, startLine: number, startCharacter: number) => {
result.push(startLine);
result.push(startCharacter);
result.push(startCharacter + length);
const [type, ...modifiers] = property.split('.');
let tokenType = legend.tokenTypes.indexOf(type);
if (tokenType === -1) {
tokenType = 0;
onObjectProperty: (property: string, _offset: number, _length: number, startLine: number, startCharacter: number) => {
addToken(property, startLine, startCharacter, property.length + 2);
},
onLiteralValue: (value: any, _offset: number, length: number, startLine: number, startCharacter: number) => {
if (typeof value === 'string') {
addToken(value, startLine, startCharacter, length);
}
result.push(tokenType);
let tokenModifiers = 0;
for (let i = 0; i < modifiers.length; i++) {
const index = legend.tokenModifiers.indexOf(modifiers[i]);
if (index !== -1) {
tokenModifiers = tokenModifiers | 1 << index;
}
}
result.push(tokenModifiers);
}
};
jsoncParser.visit(document.getText(), visitor);
return new vscode.SemanticColoring([new vscode.SemanticColoringArea(0, new Uint32Array(result))]);
return new vscode.SemanticTokens(builder.build());
}
};
context.subscriptions.push(vscode.languages.registerSemanticColoringProvider({ pattern: '**/color-test.json' }, semanticHighlightProvider, legend));
context.subscriptions.push(vscode.languages.registerSemanticTokensProvider({ pattern: '**/*semantic-test.json' }, semanticHighlightProvider, legend));
}
+1 -1
View File
@@ -8,7 +8,7 @@
"engines": {
"vscode": "^1.25.0"
},
"extensionKind": "ui",
"extensionKind": [ "ui" ],
"scripts": {
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./",
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-test-resolver ./tsconfig.json"
+4 -4
View File
@@ -2,7 +2,7 @@
# yarn lockfile v1
typescript@3.7.3-insiders.20191123:
version "3.7.3-insiders.20191123"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3-insiders.20191123.tgz#f3bef33a2a3f6e02f11bcc0c20b6f0de526f17fd"
integrity sha512-b+tLx4D0a6SeuaCa7iehdgkRKHsS67FkioQWw+0REjVNOYZ+AqJ0NjlnomK1hEUvSzSNrH9Du+m+Yiv7JlVpSg==
typescript@3.7.3:
version "3.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69"
integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.41.0",
"distro": "30dcc7436405dfa68898d0f3843551c589fc9008",
"version": "1.42.0",
"distro": "17f1b806c349d58f96b4aef97ae59d836e2c5605",
"author": {
"name": "Microsoft Corporation"
},
@@ -53,7 +53,7 @@
"vscode-ripgrep": "^1.5.7",
"vscode-sqlite3": "4.0.9",
"vscode-textmate": "4.4.0",
"xterm": "4.3.0-beta.28",
"xterm": "4.3.0-beta.28.vscode.1",
"xterm-addon-search": "0.4.0-beta4",
"xterm-addon-web-links": "0.2.1",
"xterm-addon-webgl": "0.4.0-beta.11",
+1 -1
View File
@@ -20,7 +20,7 @@
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.7",
"vscode-textmate": "4.4.0",
"xterm": "4.3.0-beta.28",
"xterm": "4.3.0-beta.28.vscode.1",
"xterm-addon-search": "0.4.0-beta4",
"xterm-addon-web-links": "0.2.1",
"xterm-addon-webgl": "0.4.0-beta.11",
+1 -1
View File
@@ -5,7 +5,7 @@
"onigasm-umd": "2.2.5",
"semver-umd": "^5.5.3",
"vscode-textmate": "4.4.0",
"xterm": "4.3.0-beta.28",
"xterm": "4.3.0-beta.28.vscode.1",
"xterm-addon-search": "0.4.0-beta4",
"xterm-addon-web-links": "0.2.1",
"xterm-addon-webgl": "0.4.0-beta.11"
+4 -4
View File
@@ -46,7 +46,7 @@ xterm-addon-webgl@0.4.0-beta.11:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.4.0-beta.11.tgz#0e4a7242e2353cf74aba55e5a5bdc0b4ec87ad10"
integrity sha512-AteDxm1RFy1WnjY9r5iJSETozLebvUkR+jextdZk/ASsK21vsYK0DuVWwRI8afgiN2hUVhxcxuHEJUOV+CJDQA==
xterm@4.3.0-beta.28:
version "4.3.0-beta.28"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.tgz#80f7c4ba8f6ee3c953e6f33f8ce5aef08d5a8354"
integrity sha512-WWZ4XCvce5h+klL6ObwtMauJff/n2KGGOwJJkDbJhrAjVy2a77GKgAedJTDDFGgKJ6ix1d7puHtVSSKflIVaDQ==
xterm@4.3.0-beta.28.vscode.1:
version "4.3.0-beta.28.vscode.1"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.vscode.1.tgz#89b85398b5801708e833d08bf92b2124fa128943"
integrity sha512-JNHNZyDtAWnybJTrenPzD6g/yXpHOvPqmjau91Up4onRbjQYMSNlth17SqaES68DKn/+4kcIl2c/RG5SXJjvGw==
+4 -4
View File
@@ -433,10 +433,10 @@ xterm-addon-webgl@0.4.0-beta.11:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.4.0-beta.11.tgz#0e4a7242e2353cf74aba55e5a5bdc0b4ec87ad10"
integrity sha512-AteDxm1RFy1WnjY9r5iJSETozLebvUkR+jextdZk/ASsK21vsYK0DuVWwRI8afgiN2hUVhxcxuHEJUOV+CJDQA==
xterm@4.3.0-beta.28:
version "4.3.0-beta.28"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.tgz#80f7c4ba8f6ee3c953e6f33f8ce5aef08d5a8354"
integrity sha512-WWZ4XCvce5h+klL6ObwtMauJff/n2KGGOwJJkDbJhrAjVy2a77GKgAedJTDDFGgKJ6ix1d7puHtVSSKflIVaDQ==
xterm@4.3.0-beta.28.vscode.1:
version "4.3.0-beta.28.vscode.1"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.vscode.1.tgz#89b85398b5801708e833d08bf92b2124fa128943"
integrity sha512-JNHNZyDtAWnybJTrenPzD6g/yXpHOvPqmjau91Up4onRbjQYMSNlth17SqaES68DKn/+4kcIl2c/RG5SXJjvGw==
yauzl@^2.9.2:
version "2.10.0"
-3
View File
@@ -1,3 +0,0 @@
declare module 'vscode-ripgrep' {
export const rgPath: string;
}
+23
View File
@@ -972,6 +972,7 @@ export const EventHelper = {
export interface IFocusTracker extends Disposable {
onDidFocus: Event<void>;
onDidBlur: Event<void>;
refreshState?(): void;
}
export function saveParentsScrollTop(node: Element): number[] {
@@ -1000,6 +1001,8 @@ class FocusTracker extends Disposable implements IFocusTracker {
private readonly _onDidBlur = this._register(new Emitter<void>());
public readonly onDidBlur: Event<void> = this._onDidBlur.event;
private _refreshStateHandler: () => void;
constructor(element: HTMLElement | Window) {
super();
let hasFocus = isAncestor(document.activeElement, <HTMLElement>element);
@@ -1026,9 +1029,24 @@ class FocusTracker extends Disposable implements IFocusTracker {
}
};
this._refreshStateHandler = () => {
let currentNodeHasFocus = isAncestor(document.activeElement, <HTMLElement>element);
if (currentNodeHasFocus !== hasFocus) {
if (hasFocus) {
onBlur();
} else {
onFocus();
}
}
};
this._register(domEvent(element, EventType.FOCUS, true)(onFocus));
this._register(domEvent(element, EventType.BLUR, true)(onBlur));
}
refreshState() {
this._refreshStateHandler();
}
}
export function trackFocus(element: HTMLElement | Window): IFocusTracker {
@@ -1079,6 +1097,11 @@ function _$<T extends Element>(namespace: Namespace, description: string, attrs?
Object.keys(attrs).forEach(name => {
const value = attrs![name];
if (typeof value === 'undefined') {
return;
}
if (/^on\w+$/.test(name)) {
(<any>result)[name] = value;
} else if (name === 'selected') {
+2 -7
View File
@@ -15,7 +15,6 @@ import { cloneAndChange } from 'vs/base/common/objects';
import { escape } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { renderCodicons } from 'vs/base/browser/ui/codiconLabel/codiconLabel';
export interface MarkdownRenderOptions extends FormattedTextRenderOptions {
codeBlockRenderer?: (modeId: string, value: string) => Promise<string>;
@@ -63,7 +62,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
if (uri.query) {
uri = uri.with({ query: _uriMassage(uri.query) });
}
return uri.toString();
return uri.toString(true);
};
// signal to code-block render that the
@@ -73,10 +72,6 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
const renderer = new marked.Renderer();
renderer.image = (href: string, title: string, text: string) => {
if (href && href.indexOf('vscode-icon://codicon/') === 0) {
return renderCodicons(`$(${URI.parse(href).path.substr(1)})`);
}
let dimensions: string[] = [];
let attributes: string[] = [];
if (href) {
@@ -178,7 +173,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
renderer
};
const allowedSchemes = [Schemas.http, Schemas.https, Schemas.mailto, Schemas.data, Schemas.file, Schemas.vscodeRemote];
const allowedSchemes = [Schemas.http, Schemas.https, Schemas.mailto, Schemas.data, Schemas.file, Schemas.vscodeRemote, Schemas.vscodeRemoteResource];
if (markdown.isTrusted) {
allowedSchemes.push(Schemas.command);
}
@@ -396,7 +396,6 @@
.codicon-debug-breakpoint-function:before { content: "\eb88" }
.codicon-debug-breakpoint-function-disabled:before { content: "\eb88" }
.codicon-debug-breakpoint-stackframe-active:before { content: "\eb89" }
.codicon-debug-breakpoint-stackframe-dot:before { content: "\eb8a" }
.codicon-debug-breakpoint-stackframe:before { content: "\eb8b" }
.codicon-debug-breakpoint-stackframe-focused:before { content: "\eb8b" }
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
+4 -4
View File
@@ -604,8 +604,8 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
export type GridNodeDescriptor = { size?: number, groups?: GridNodeDescriptor[] };
export type GridDescriptor = { orientation: Orientation, groups?: GridNodeDescriptor[] };
export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor): void {
if (nodeDescriptor.groups && nodeDescriptor.groups.length <= 1) {
export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor, rootNode: boolean): void {
if (!rootNode && nodeDescriptor.groups && nodeDescriptor.groups.length <= 1) {
nodeDescriptor.groups = undefined;
}
@@ -617,7 +617,7 @@ export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor):
let totalDefinedSizeCount = 0;
for (const child of nodeDescriptor.groups) {
sanitizeGridNodeDescriptor(child);
sanitizeGridNodeDescriptor(child, false);
if (child.size) {
totalDefinedSize += child.size;
@@ -665,7 +665,7 @@ function getDimensions(node: ISerializedNode, orientation: Orientation): { width
}
export function createSerializedGrid(gridDescriptor: GridDescriptor): ISerializedGrid {
sanitizeGridNodeDescriptor(gridDescriptor);
sanitizeGridNodeDescriptor(gridDescriptor, true);
const root = createSerializedNode(gridDescriptor);
const { width, height } = getDimensions(root, gridDescriptor.orientation);
+2
View File
@@ -1086,6 +1086,8 @@ export class GridView implements IDisposable {
throw new Error('Invalid JSON: \'width\' property must be a number.');
} else if (typeof json.height !== 'number') {
throw new Error('Invalid JSON: \'height\' property must be a number.');
} else if (json.root?.type !== 'branch') {
throw new Error('Invalid JSON: \'root\' property must have \'type\' value of branch.');
}
const orientation = json.orientation;
+14 -6
View File
@@ -9,6 +9,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte
import { IMatch } from 'vs/base/common/filters';
import { Disposable } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range';
import { equals } from 'vs/base/common/objects';
export interface IIconLabelCreationOptions {
supportHighlights?: boolean;
@@ -26,6 +27,7 @@ export interface IIconLabelValueOptions {
labelEscapeNewLines?: boolean;
descriptionMatches?: IMatch[];
readonly separator?: string;
readonly domId?: string;
}
class FastLabelNode {
@@ -164,21 +166,23 @@ class Label {
private label: string | string[] | undefined = undefined;
private singleLabel: HTMLElement | undefined = undefined;
private options: IIconLabelValueOptions | undefined;
constructor(private container: HTMLElement) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
if (this.label === label && equals(this.options, options)) {
return;
}
this.label = label;
this.options = options;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
dom.removeClass(this.container, 'multiple');
this.singleLabel = dom.append(this.container, dom.$('a.label-name'));
this.singleLabel = dom.append(this.container, dom.$('a.label-name', { id: options?.domId }));
}
this.singleLabel.textContent = label;
@@ -189,8 +193,9 @@ class Label {
for (let i = 0; i < label.length; i++) {
const l = label[i];
const id = options?.domId && `${options?.domId}_${i}`;
dom.append(this.container, dom.$('a.label-name', { 'data-icon-label-count': label.length, 'data-icon-label-index': i }, l));
dom.append(this.container, dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i }, l));
if (i < label.length - 1) {
dom.append(this.container, dom.$('span.label-separator', undefined, options?.separator || '/'));
@@ -224,21 +229,23 @@ class LabelWithHighlights {
private label: string | string[] | undefined = undefined;
private singleLabel: HighlightedLabel | undefined = undefined;
private options: IIconLabelValueOptions | undefined;
constructor(private container: HTMLElement, private supportCodicons: boolean) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
if (this.label === label && equals(this.options, options)) {
return;
}
this.label = label;
this.options = options;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
dom.removeClass(this.container, 'multiple');
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name')), this.supportCodicons);
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), this.supportCodicons);
}
this.singleLabel.set(label, options?.matches, options?.title, options?.labelEscapeNewLines);
@@ -254,8 +261,9 @@ class LabelWithHighlights {
for (let i = 0; i < label.length; i++) {
const l = label[i];
const m = matches ? matches[i] : undefined;
const id = options?.domId && `${options?.domId}_${i}`;
const name = dom.$('a.label-name', { 'data-icon-label-count': label.length, 'data-icon-label-index': i });
const name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i });
const highlightedLabel = new HighlightedLabel(dom.append(this.container, name), this.supportCodicons);
highlightedLabel.set(l, m, options?.title, options?.labelEscapeNewLines);
+25 -5
View File
@@ -702,6 +702,9 @@ export interface IAccessibilityProvider<T> {
* https://www.w3.org/TR/wai-aria/#aria-level
*/
getAriaLevel?(element: T): number | undefined;
onDidChangeActiveDescendant?: Event<void>;
getActiveDescendantId?(element: T): string | undefined;
}
export class DefaultStyleController implements IStyleController {
@@ -1115,6 +1118,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private spliceable: ISpliceable<T>;
private styleController: IStyleController;
private typeLabelController?: TypeLabelController<T>;
private accessibilityProvider?: IAccessibilityProvider<T>;
protected readonly disposables = new DisposableStore();
@@ -1200,8 +1204,14 @@ export class List<T> implements ISpliceable<T>, IDisposable {
const baseRenderers: IListRenderer<T, ITraitTemplateData>[] = [this.focus.renderer, this.selection.renderer];
if (_options.accessibilityProvider) {
baseRenderers.push(new AccessibiltyRenderer<T>(_options.accessibilityProvider));
this.accessibilityProvider = _options.accessibilityProvider;
if (this.accessibilityProvider) {
baseRenderers.push(new AccessibiltyRenderer<T>(this.accessibilityProvider));
if (this.accessibilityProvider.onDidChangeActiveDescendant) {
this.accessibilityProvider.onDidChangeActiveDescendant(this.onDidChangeActiveDescendant, this, this.disposables);
}
}
renderers = renderers.map(r => new PipelineRenderer(r.templateId, [...baseRenderers, r]));
@@ -1623,14 +1633,24 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private _onFocusChange(): void {
const focus = this.focus.get();
DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0);
this.onDidChangeActiveDescendant();
}
private onDidChangeActiveDescendant(): void {
const focus = this.focus.get();
if (focus.length > 0) {
this.view.domNode.setAttribute('aria-activedescendant', this.view.getElementDomId(focus[0]));
let id: string | undefined;
if (this.accessibilityProvider?.getActiveDescendantId) {
id = this.accessibilityProvider.getActiveDescendantId(this.view.element(focus[0]));
}
this.view.domNode.setAttribute('aria-activedescendant', id || this.view.getElementDomId(focus[0]));
} else {
this.view.domNode.removeAttribute('aria-activedescendant');
}
DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0);
}
private _onSelectionChange(): void {
+5 -1
View File
@@ -161,12 +161,16 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
}
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element);
},
getAriaLevel(node) {
return node.depth;
}
},
getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
return options.accessibilityProvider!.getActiveDescendantId!(node.element);
})
},
keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {
...options.keyboardNavigationLabelProvider,
+57 -12
View File
@@ -6,7 +6,7 @@
import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper } from 'vs/base/browser/ui/tree/tree';
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper, ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
@@ -20,6 +20,7 @@ import { values } from 'vs/base/common/map';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { IThemable } from 'vs/base/common/styler';
import { isFilterResult, getVisibleState } from 'vs/base/browser/ui/tree/indexTreeModel';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -229,9 +230,16 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
}
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element as T);
}
},
getAriaLevel: options.accessibilityProvider!.getAriaLevel && (node => {
return options.accessibilityProvider!.getAriaLevel!(node.element as T);
}),
getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
return options.accessibilityProvider!.getActiveDescendantId!(node.element as T);
})
},
filter: options.filter && {
filter(e, parentVisibility) {
@@ -760,12 +768,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
result = createCancelablePromise(async () => {
const children = await this.dataSource.getChildren(node.element!);
if (this.sorter) {
children.sort(this.sorter.compare.bind(this.sorter));
}
return children;
return this.processChildren(children);
});
this.refreshPromises.set(node, result);
@@ -924,6 +927,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
};
}
protected processChildren(children: T[]): T[] {
if (this.sorter) {
children.sort(this.sorter.compare.bind(this.sorter));
}
return children;
}
// view state
getViewState(): IAsyncDataTreeViewState {
@@ -1066,6 +1077,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
protected readonly tree!: CompressibleObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected readonly compressibleNodeMapper: CompressibleAsyncDataTreeNodeMapper<TInput, T, TFilterData> = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));
private filter?: ITreeFilter<T, TFilterData>;
constructor(
user: string,
@@ -1077,6 +1089,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
options: ICompressibleAsyncDataTreeOptions<T, TFilterData> = {}
) {
super(user, container, virtualDelegate, renderers, dataSource, options);
this.filter = options.filter;
}
protected createTree(
@@ -1176,14 +1189,16 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
if (compressedNode) {
for (let i = 0; i < compressedNode.elements.length; i++) {
const id = getId(compressedNode.elements[i].element as T);
const element = compressedNode.elements[compressedNode.elements.length - 1].element as T;
if (oldSelection.has(id)) {
selection.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
// github.com/microsoft/vscode/issues/85938
if (oldSelection.has(id) && selection.indexOf(element) === -1) {
selection.push(element);
didChangeSelection = true;
}
if (oldFocus.has(id)) {
focus.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
if (oldFocus.has(id) && focus.indexOf(element) === -1) {
focus.push(element);
didChangeFocus = true;
}
}
@@ -1202,4 +1217,34 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
this.setFocus(focus);
}
}
// For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work
// and we have to filter everything beforehand
// Related to #85193 and #85835
protected processChildren(children: T[]): T[] {
if (this.filter) {
children = children.filter(e => {
const result = this.filter!.filter(e, TreeVisibility.Visible);
const visibility = getVisibility(result);
if (visibility === TreeVisibility.Recurse) {
throw new Error('Recursive tree visibility not supported in async data compressed trees');
}
return visibility === TreeVisibility.Visible;
});
}
return super.processChildren(children);
}
}
function getVisibility<TFilterData>(filterResult: TreeFilterResult<TFilterData>): TreeVisibility {
if (typeof filterResult === 'boolean') {
return filterResult ? TreeVisibility.Visible : TreeVisibility.Hidden;
} else if (isFilterResult(filterResult)) {
return getVisibleState(filterResult.visibility);
} else {
return getVisibleState(filterResult);
}
}
@@ -11,7 +11,7 @@ import { IObjectTreeModelOptions, ObjectTreeModel, IObjectTreeModel } from 'vs/b
// Exported only for test reasons, do not use directly
export interface ICompressedTreeElement<T> extends ITreeElement<T> {
readonly children?: Iterator<ICompressedTreeElement<T>> | ICompressedTreeElement<T>[];
readonly children?: ISequence<ICompressedTreeElement<T>>;
readonly incompressible?: boolean;
}
+16 -1
View File
@@ -172,13 +172,28 @@ export module Iterator {
}
};
}
export function chain<T>(iterator: Iterator<T>): ChainableIterator<T> {
return new ChainableIterator(iterator);
}
}
export class ChainableIterator<T> implements Iterator<T> {
constructor(private it: Iterator<T>) { }
next(): IteratorResult<T> { return this.it.next(); }
map<R>(fn: (t: T) => R): ChainableIterator<R> { return new ChainableIterator(Iterator.map(this.it, fn)); }
filter(fn: (t: T) => boolean): ChainableIterator<T> { return new ChainableIterator(Iterator.filter(this.it, fn)); }
}
export type ISequence<T> = Iterator<T> | T[];
export function getSequenceIterator<T>(arg: Iterator<T> | T[]): Iterator<T> {
export function getSequenceIterator<T>(arg: ISequence<T> | undefined): Iterator<T> {
if (Array.isArray(arg)) {
return Iterator.fromArray(arg);
} else if (!arg) {
return Iterator.empty();
} else {
return arg;
}
+10 -9
View File
@@ -199,6 +199,13 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null,
return null;
}
// we explicitly ignore a specific set of encodings from auto guessing
// - ASCII: we never want this encoding (most UTF-8 files would happily detect as
// ASCII files and then you could not type non-ASCII characters anymore)
// - UTF-16: we have our own detection logic for UTF-16
// - UTF-32: we do not support this encoding in VSCode
const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32'];
/**
* Guesses the encoding from buffer.
*/
@@ -210,15 +217,9 @@ async function guessEncodingByBuffer(buffer: Buffer): Promise<string | null> {
return null;
}
// Ignore 'ascii' as guessed encoding because that
// is almost never what we want, rather fallback
// to the configured encoding then. Otherwise,
// opening a ascii-only file with auto guessing
// enabled will put the file into 'ascii' mode
// and thus typing any special characters is
// not possible anymore.
if (guessed.encoding.toLowerCase() === 'ascii') {
return null;
const enc = guessed.encoding.toLowerCase();
if (0 <= IGNORE_ENCODINGS.indexOf(enc)) {
return null; // see comment above why we ignore some encodings
}
return toIconvLiteEncoding(guessed.encoding);
@@ -787,7 +787,7 @@ suite('SerializableGrid', function () {
test('sanitizeGridNodeDescriptor', () => {
const nodeDescriptor = { groups: [{ size: 0.2 }, { size: 0.2 }, { size: 0.6, groups: [{}, {}] }] };
const nodeDescriptorCopy = deepClone<GridNodeDescriptor>(nodeDescriptor);
sanitizeGridNodeDescriptor(nodeDescriptorCopy);
sanitizeGridNodeDescriptor(nodeDescriptorCopy, true);
assert.deepEqual(nodeDescriptorCopy, { groups: [{ size: 0.2 }, { size: 0.2 }, { size: 0.6, groups: [{ size: 0.5 }, { size: 0.5 }] }] });
});
@@ -50,8 +50,8 @@ import { IFileService } from 'vs/platform/files/common/files';
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
import { Schemas } from 'vs/base/common/network';
import { IProductService } from 'vs/platform/product/common/productService';
import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncService, UserDataAutoSync } from 'vs/platform/userDataSync/common/userDataSyncService';
import { IUserDataSyncService, IUserDataSyncStoreService, ISettingsMergeService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { SettingsMergeChannelClient } from 'vs/platform/userDataSync/common/settingsSyncIpc';
@@ -63,6 +63,8 @@ import { AuthTokenService } from 'vs/platform/auth/electron-browser/authTokenSer
import { AuthTokenChannel } from 'vs/platform/auth/common/authTokenIpc';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService';
import { UserDataSyncUtilServiceClient } from 'vs/platform/userDataSync/common/keybindingsSyncIpc';
import { UserDataAutoSync } from 'vs/platform/userDataSync/electron-browser/userDataAutoSync';
export interface ISharedProcessConfiguration {
readonly machineId: string;
@@ -186,6 +188,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
const settingsMergeChannel = server.getChannel('settingsMerge', activeWindowRouter);
services.set(ISettingsMergeService, new SettingsMergeChannelClient(settingsMergeChannel));
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', activeWindowRouter)));
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
registerConfiguration();
@@ -9,11 +9,10 @@ import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory } from 'vs/editor/browser/controller/mouseTarget';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
@@ -46,9 +45,9 @@ export interface IPointerHandlerHelper {
focusTextArea(): void;
/**
* Get the last rendered information of the cursors.
* Get the last rendered information for cursors & textarea.
*/
getLastViewCursorsRenderData(): IViewCursorRenderData[];
getLastRenderData(): PointerHandlerLastRenderData;
shouldSuppressMouseDownOnViewZone(viewZoneId: string): boolean;
shouldSuppressMouseDownOnWidget(widgetId: string): boolean;
@@ -158,13 +157,11 @@ export class MouseHandler extends ViewEventHandler {
return null;
}
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, editorPos, pos, null);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, null);
}
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): editorBrowser.IMouseTarget {
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, e.editorPos, e.pos, testEventTarget ? e.target : null);
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, testEventTarget ? e.target : null);
}
private _getMouseColumn(e: EditorMouseEvent): number {
@@ -89,6 +89,13 @@ interface IHitTestResult {
hitTarget: Element | null;
}
export class PointerHandlerLastRenderData {
constructor(
public readonly lastViewCursorsRenderData: IViewCursorRenderData[],
public readonly lastTextareaPosition: Position | null
) { }
}
export class MouseTarget implements IMouseTarget {
public readonly element: Element | null;
@@ -232,19 +239,19 @@ export class HitTestContext {
public readonly viewDomNode: HTMLElement;
public readonly lineHeight: number;
public readonly typicalHalfwidthCharacterWidth: number;
public readonly lastViewCursorsRenderData: IViewCursorRenderData[];
public readonly lastRenderData: PointerHandlerLastRenderData;
private readonly _context: ViewContext;
private readonly _viewHelper: IPointerHandlerHelper;
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastViewCursorsRenderData: IViewCursorRenderData[]) {
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastRenderData: PointerHandlerLastRenderData) {
this.model = context.model;
const options = context.configuration.options;
this.layoutInfo = options.get(EditorOption.layoutInfo);
this.viewDomNode = viewHelper.viewDomNode;
this.lineHeight = options.get(EditorOption.lineHeight);
this.typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;
this.lastViewCursorsRenderData = lastViewCursorsRenderData;
this.lastRenderData = lastRenderData;
this._context = context;
this._viewHelper = viewHelper;
}
@@ -462,8 +469,8 @@ export class MouseTargetFactory {
return false;
}
public createMouseTarget(lastViewCursorsRenderData: IViewCursorRenderData[], editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastViewCursorsRenderData);
public createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastRenderData);
const request = new HitTestRequest(ctx, editorPos, pos, target);
try {
const r = MouseTargetFactory._createMouseTarget(ctx, request, false);
@@ -544,7 +551,7 @@ export class MouseTargetFactory {
if (request.target) {
// Check if we've hit a painted cursor
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
for (const d of lastViewCursorsRenderData) {
@@ -560,7 +567,7 @@ export class MouseTargetFactory {
// first or last rendered view line dom node, therefore help it out
// and first check if we are on top of a cursor
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
const mouseContentHorizontalOffset = request.mouseContentHorizontalOffset;
const mouseVerticalOffset = request.mouseVerticalOffset;
@@ -602,7 +609,10 @@ export class MouseTargetFactory {
private static _hitTestTextArea(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it the textarea?
if (ElementPath.isTextArea(request.targetPath)) {
return request.fulfill(MouseTargetType.TEXTAREA);
if (ctx.lastRenderData.lastTextareaPosition) {
return request.fulfill(MouseTargetType.CONTENT_TEXT, ctx.lastRenderData.lastTextareaPosition);
}
return request.fulfill(MouseTargetType.TEXTAREA, ctx.lastRenderData.lastTextareaPosition);
}
return null;
}
@@ -77,6 +77,12 @@ export class TextAreaHandler extends ViewPart {
private _visibleTextArea: VisibleTextAreaData | null;
private _selections: Selection[];
/**
* The position at which the textarea was rendered.
* This is useful for hit-testing and determining the mouse position.
*/
private _lastRenderPosition: Position | null;
public readonly textArea: FastDomNode<HTMLTextAreaElement>;
public readonly textAreaCover: FastDomNode<HTMLElement>;
private readonly _textAreaInput: TextAreaInput;
@@ -104,6 +110,7 @@ export class TextAreaHandler extends ViewPart {
this._visibleTextArea = null;
this._selections = [new Selection(1, 1, 1, 1)];
this._lastRenderPosition = null;
// Text Area (The focus will always be in the textarea when the cursor is blinking)
this.textArea = createFastDomNode(document.createElement('textarea'));
@@ -413,13 +420,18 @@ export class TextAreaHandler extends ViewPart {
this._textAreaInput.refreshFocusState();
}
public getLastRenderData(): Position | null {
return this._lastRenderPosition;
}
// --- end view API
private _primaryCursorPosition: Position = new Position(1, 1);
private _primaryCursorVisibleRange: HorizontalPosition | null = null;
public prepareRender(ctx: RenderingContext): void {
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
this._primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(this._primaryCursorPosition);
}
public render(ctx: RestrictedRenderingContext): void {
@@ -431,6 +443,7 @@ export class TextAreaHandler extends ViewPart {
if (this._visibleTextArea) {
// The text area is visible for composition reasons
this._renderInsideEditor(
null,
this._visibleTextArea.top - this._scrollTop,
this._contentLeft + this._visibleTextArea.left - this._scrollLeft,
this._visibleTextArea.width,
@@ -465,6 +478,7 @@ export class TextAreaHandler extends ViewPart {
// For the popup emoji input, we will make the text area as high as the line height
// We will also make the fontSize and lineHeight the correct dimensions to help with the placement of these pickers
this._renderInsideEditor(
this._primaryCursorPosition,
top, left,
canUseZeroSizeTextarea ? 0 : 1, this._lineHeight
);
@@ -472,12 +486,14 @@ export class TextAreaHandler extends ViewPart {
}
this._renderInsideEditor(
this._primaryCursorPosition,
top, left,
canUseZeroSizeTextarea ? 0 : 1, canUseZeroSizeTextarea ? 0 : 1
);
}
private _renderInsideEditor(top: number, left: number, width: number, height: number): void {
private _renderInsideEditor(renderedPosition: Position | null, top: number, left: number, width: number, height: number): void {
this._lastRenderPosition = renderedPosition;
const ta = this.textArea;
const tac = this.textAreaCover;
@@ -495,6 +511,7 @@ export class TextAreaHandler extends ViewPart {
}
private _renderAtTopLeft(): void {
this._lastRenderPosition = null;
const ta = this.textArea;
const tac = this.textAreaCover;
@@ -274,7 +274,11 @@ export class TextAreaInput extends Disposable {
this._register(dom.addDisposableListener(textArea.domNode, 'compositionend', (e: CompositionEvent) => {
this._lastTextAreaEvent = TextAreaInputEventType.compositionend;
// https://github.com/microsoft/monaco-editor/issues/1663
// On iOS 13.2, Chinese system IME randomly trigger an additional compositionend event with empty data
if (!this._isDoingComposition) {
return;
}
if (compositionDataInValid(e.locale)) {
// https://github.com/Microsoft/monaco-editor/issues/339
const [newState, typeInput] = deduceInputFromTextAreaValue(/*couldBeEmojiInput*/false, /*couldBeTypingAtOffset0*/false);
+5 -2
View File
@@ -48,6 +48,7 @@ import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IThemeService, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
export interface IContentWidgetData {
@@ -244,8 +245,10 @@ export class View extends ViewEventHandler {
this.focus();
},
getLastViewCursorsRenderData: () => {
return this.viewCursors.getLastRenderData() || [];
getLastRenderData: (): PointerHandlerLastRenderData => {
const lastViewCursorsRenderData = this.viewCursors.getLastRenderData() || [];
const lastTextareaPosition = this._textAreaHandler.getLastRenderData();
return new PointerHandlerLastRenderData(lastViewCursorsRenderData, lastTextareaPosition);
},
shouldSuppressMouseDownOnViewZone: (viewZoneId: string) => {
return this.viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId);
@@ -57,7 +57,7 @@ export abstract class AbstractLineHighlightOverlay extends DynamicViewOverlay {
const renderSelections = isRenderedUsingBorder ? this._selections.slice(0, 1) : this._selections;
const cursorsLineNumbers = renderSelections.map(s => s.positionLineNumber);
cursorsLineNumbers.sort();
cursorsLineNumbers.sort((a, b) => a - b);
if (!arrays.equals(this._cursorLineNumbers, cursorsLineNumbers)) {
this._cursorLineNumbers = cursorsLineNumbers;
hasChanged = true;
@@ -33,6 +33,7 @@ import { Color } from 'vs/base/common/color';
import { GestureEvent, EventType, Gesture } from 'vs/base/browser/touch';
import { MinimapCharRendererFactory } from 'vs/editor/browser/viewParts/minimap/minimapCharRendererFactory';
import { MinimapPosition } from 'vs/editor/common/model';
import { once } from 'vs/base/common/functional';
function getMinimapLineHeight(renderMinimap: RenderMinimap, scale: number): number {
if (renderMinimap === RenderMinimap.Text) {
@@ -73,7 +74,7 @@ class MinimapOptions {
public readonly fontScale: number;
public readonly charRenderer: MinimapCharRenderer;
public readonly charRenderer: () => MinimapCharRenderer;
/**
* container dom node left position (in CSS px)
@@ -117,7 +118,7 @@ class MinimapOptions {
const minimapOpts = options.get(EditorOption.minimap);
this.showSlider = minimapOpts.showSlider;
this.fontScale = Math.round(minimapOpts.scale * pixelRatio);
this.charRenderer = MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily);
this.charRenderer = once(() => MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily));
this.pixelRatio = pixelRatio;
this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;
this.lineHeight = options.get(EditorOption.lineHeight);
@@ -850,6 +851,11 @@ export class Minimap extends ViewPart {
charWidth: number): void {
const y = (lineNumber - layout.startLineNumber) * lineHeight;
// Skip rendering the line if it's vertically outside our viewport
if (y + height < 0 || y > this._options.canvasOuterHeight) {
return;
}
// Cache line offset data so that it is only read once per line
let lineIndexToXOffset = lineOffsetMap.get(lineNumber);
const isFirstDecorationForLine = !lineIndexToXOffset;
@@ -900,6 +906,7 @@ export class Minimap extends ViewPart {
private renderLines(layout: MinimapLayout): RenderData {
const renderMinimap = this._options.renderMinimap;
const charRenderer = this._options.charRenderer();
const startLineNumber = layout.startLineNumber;
const endLineNumber = layout.endLineNumber;
const minimapLineHeight = getMinimapLineHeight(renderMinimap, this._options.fontScale);
@@ -941,7 +948,7 @@ export class Minimap extends ViewPart {
useLighterFont,
renderMinimap,
this._tokensColorTracker,
this._options.charRenderer,
charRenderer,
dy,
tabSize,
lineInfo.data[lineIndex]!,
@@ -874,6 +874,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
public onHide(): void {
this._modelData?.view.refreshFocusState();
this._focusTracker.refreshState();
}
public getContribution<T extends editorCommon.IEditorContribution>(id: string): T {
@@ -1806,6 +1807,12 @@ class CodeEditorWidgetFocusTracker extends Disposable {
public hasFocus(): boolean {
return this._hasFocus;
}
public refreshState(): void {
if (this._domFocusTracker.refreshState) {
this._domFocusTracker.refreshState();
}
}
}
const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' enable-background='new 0 0 6 3' height='3' width='6'><g fill='`);
@@ -128,12 +128,13 @@ class VisualEditorState {
this.inlineDiffMargins = [];
for (let i = 0, length = newDecorations.zones.length; i < length; i++) {
const viewZone = <editorBrowser.IViewZone>newDecorations.zones[i];
viewZone.suppressMouseDown = false;
viewZone.suppressMouseDown = true;
let zoneId = viewChangeAccessor.addZone(viewZone);
this._zones.push(zoneId);
this._zonesMap[String(zoneId)] = true;
if (newDecorations.zones[i].diff && viewZone.marginDomNode && this._clipboardService) {
viewZone.suppressMouseDown = false;
this.inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
}
}
@@ -263,6 +263,13 @@ function migrateOptions(options: IEditorOptions): void {
} else if (<any>autoIndent === false) {
options.autoIndent = 'advanced';
}
const matchBrackets = options.matchBrackets;
if (<any>matchBrackets === true) {
options.matchBrackets = 'always';
} else if (<any>matchBrackets === false) {
options.matchBrackets = 'never';
}
}
function deepCloneAndMigrateOptions(_options: IEditorOptions): IEditorOptions {
+8 -6
View File
@@ -481,9 +481,9 @@ export interface IEditorOptions {
showFoldingControls?: 'always' | 'mouseover';
/**
* Enable highlighting of matching brackets.
* Defaults to true.
* Defaults to 'always'.
*/
matchBrackets?: boolean;
matchBrackets?: 'never' | 'near' | 'always';
/**
* Enable rendering of whitespace.
* Defaults to none.
@@ -2271,7 +2271,7 @@ class EditorRulers extends SimpleEditorOption<EditorOption.rulers, number[]> {
for (let value of input) {
rulers.push(EditorIntOption.clampedInt(value, 0, 0, 10000));
}
rulers.sort();
rulers.sort((a, b) => a - b);
return rulers;
}
return this.defaultValue;
@@ -3356,9 +3356,11 @@ export const EditorOptions = {
EditorOption.links, 'links', true,
{ description: nls.localize('links', "Controls whether the editor should detect links and make them clickable.") }
)),
matchBrackets: register(new EditorBooleanOption(
EditorOption.matchBrackets, 'matchBrackets', true,
{ description: nls.localize('matchBrackets', "Highlight matching brackets when one of them is selected.") }
matchBrackets: register(new EditorStringEnumOption(
EditorOption.matchBrackets, 'matchBrackets',
'always' as 'never' | 'near' | 'always',
['always', 'near', 'never'] as const,
{ description: nls.localize('matchBrackets', "Highlight matching brackets.") }
)),
minimap: register(new EditorMinimap()),
mouseStyle: register(new EditorStringEnumOption(
+1 -1
View File
@@ -898,7 +898,7 @@ export interface ITextModel {
* @param position The position at which to start the search.
* @internal
*/
findEnclosingBrackets(position: IPosition): [Range, Range] | null;
findEnclosingBrackets(position: IPosition, maxDuration?: number): [Range, Range] | null;
/**
* Given a `position`, if the position is on top or near a bracket,
+18 -7
View File
@@ -34,6 +34,7 @@ import { withUndefinedAsNull } from 'vs/base/common/types';
import { VSBufferReadableStream, VSBuffer } from 'vs/base/common/buffer';
import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2 } from 'vs/editor/common/model/tokensStore';
import { Color } from 'vs/base/common/color';
import { Constants } from 'vs/base/common/uint';
function createTextBufferBuilder() {
return new PieceTreeTextBufferBuilder();
@@ -2341,16 +2342,21 @@ export class TextModel extends Disposable implements model.ITextModel {
return null;
}
public findEnclosingBrackets(_position: IPosition): [Range, Range] | null {
public findEnclosingBrackets(_position: IPosition, maxDuration = Constants.MAX_SAFE_SMALL_INTEGER): [Range, Range] | null {
const position = this.validatePosition(_position);
const lineCount = this.getLineCount();
const savedCounts = new Map<number, number[]>();
let counts: number[] = [];
const resetCounts = (modeBrackets: RichEditBrackets | null) => {
counts = [];
for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {
counts[i] = 0;
const resetCounts = (languageId: number, modeBrackets: RichEditBrackets | null) => {
if (!savedCounts.has(languageId)) {
let tmp = [];
for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {
tmp[i] = 0;
}
savedCounts.set(languageId, tmp);
}
counts = savedCounts.get(languageId)!;
};
const searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null => {
while (true) {
@@ -2380,7 +2386,12 @@ export class TextModel extends Disposable implements model.ITextModel {
let languageId: LanguageId = -1;
let modeBrackets: RichEditBrackets | null = null;
const startTime = Date.now();
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
const elapsedTime = Date.now() - startTime;
if (elapsedTime > maxDuration) {
return null;
}
const lineTokens = this._getLineTokens(lineNumber);
const tokenCount = lineTokens.getCount();
const lineText = this._buffer.getLineContent(lineNumber);
@@ -2396,7 +2407,7 @@ export class TextModel extends Disposable implements model.ITextModel {
if (languageId !== tokenLanguageId) {
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
resetCounts(modeBrackets);
resetCounts(languageId, modeBrackets);
}
}
@@ -2415,7 +2426,7 @@ export class TextModel extends Disposable implements model.ITextModel {
}
languageId = tokenLanguageId;
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
resetCounts(modeBrackets);
resetCounts(languageId, modeBrackets);
}
const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
+13 -7
View File
@@ -121,7 +121,7 @@ export interface IEncodedTokens {
getMetadata(tokenIndex: number): number;
clear(): void;
acceptDeleteRange(startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void;
acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void;
acceptInsertText(deltaLine: number, character: number, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void;
}
@@ -173,7 +173,7 @@ export class SparseEncodedTokens implements IEncodedTokens {
this._tokenCount = 0;
}
public acceptDeleteRange(startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {
public acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {
// This is a bit complex, here are the cases I used to think about this:
//
// 1. The token starts before the deletion range
@@ -292,9 +292,13 @@ export class SparseEncodedTokens implements IEncodedTokens {
tokenDeltaLine -= deletedLineCount;
} else if (tokenDeltaLine === endDeltaLine && tokenStartCharacter >= endCharacter) {
// 4. (continued) The token starts after the deletion range, on the last line where a deletion occurs
if (horizontalShiftForFirstLineTokens && tokenDeltaLine === 0) {
tokenStartCharacter += horizontalShiftForFirstLineTokens;
tokenEndCharacter += horizontalShiftForFirstLineTokens;
}
tokenDeltaLine -= deletedLineCount;
tokenStartCharacter -= endCharacter;
tokenEndCharacter -= endCharacter;
tokenStartCharacter -= (endCharacter - startCharacter);
tokenEndCharacter -= (endCharacter - startCharacter);
} else {
throw new Error(`Not possible!`);
}
@@ -373,8 +377,8 @@ export class SparseEncodedTokens implements IEncodedTokens {
}
}
// => the token must move and keep its size constant
tokenDeltaLine += eolCount;
if (tokenDeltaLine === deltaLine) {
tokenDeltaLine += eolCount;
// this token is on the line where the insertion is taking place
if (eolCount === 0) {
tokenStartCharacter += firstLineLength;
@@ -384,6 +388,8 @@ export class SparseEncodedTokens implements IEncodedTokens {
tokenStartCharacter = lastLineLength + (tokenStartCharacter - character);
tokenEndCharacter = tokenStartCharacter + tokenLength;
}
} else {
tokenDeltaLine += eolCount;
}
}
@@ -527,9 +533,9 @@ export class MultilineTokens2 {
const deletedBefore = -firstLineIndex;
this.startLineNumber -= deletedBefore;
this.tokens.acceptDeleteRange(0, 0, lastLineIndex, range.endColumn - 1);
this.tokens.acceptDeleteRange(range.startColumn - 1, 0, 0, lastLineIndex, range.endColumn - 1);
} else {
this.tokens.acceptDeleteRange(firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);
this.tokens.acceptDeleteRange(0, firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);
}
}
+17 -17
View File
@@ -1465,31 +1465,31 @@ export interface CodeLensProvider {
resolveCodeLens?(model: model.ITextModel, codeLens: CodeLens, token: CancellationToken): ProviderResult<CodeLens>;
}
export interface SemanticColoringLegend {
export interface SemanticTokensLegend {
readonly tokenTypes: string[];
readonly tokenModifiers: string[];
}
export interface SemanticColoringArea {
/**
* The zero-based line value where this token block begins.
*/
readonly line: number;
/**
* The actual token block encoded data.
*/
export interface SemanticTokens {
readonly resultId?: string;
readonly data: Uint32Array;
}
export interface SemanticColoring {
readonly areas: SemanticColoringArea[];
dispose(): void;
export interface SemanticTokensEdit {
readonly start: number;
readonly deleteCount: number;
readonly data?: Uint32Array;
}
export interface SemanticColoringProvider {
getLegend(): SemanticColoringLegend;
provideSemanticColoring(model: model.ITextModel, token: CancellationToken): ProviderResult<SemanticColoring>;
export interface SemanticTokensEdits {
readonly resultId?: string;
readonly edits: SemanticTokensEdit[];
}
export interface SemanticTokensProvider {
getLegend(): SemanticTokensLegend;
provideSemanticTokens(model: model.ITextModel, lastResultId: string | null, ranges: Range[] | null, token: CancellationToken): ProviderResult<SemanticTokens | SemanticTokensEdits>;
releaseSemanticTokens(resultId: string | undefined): void;
}
// --- feature registries ------
@@ -1597,7 +1597,7 @@ export const FoldingRangeProviderRegistry = new LanguageFeatureRegistry<FoldingR
/**
* @internal
*/
export const SemanticColoringProviderRegistry = new LanguageFeatureRegistry<SemanticColoringProvider>();
export const SemanticTokensProviderRegistry = new LanguageFeatureRegistry<SemanticTokensProvider>();
/**
* @internal
@@ -17,6 +17,7 @@ import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDeco
import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { withUndefinedAsNull } from 'vs/base/common/types';
import { minimapWarning, minimapError } from 'vs/platform/theme/common/colorRegistry';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -205,7 +206,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
color = themeColorFromId(overviewRulerWarning);
zIndex = 20;
minimap = {
color,
color: themeColorFromId(minimapWarning),
position: MinimapPosition.Inline
};
break;
@@ -220,7 +221,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
color = themeColorFromId(overviewRulerError);
zIndex = 30;
minimap = {
color,
color: themeColorFromId(minimapError),
position: MinimapPosition.Inline
};
break;
+206 -58
View File
@@ -14,7 +14,7 @@ import { Range } from 'vs/editor/common/core/range';
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { LanguageIdentifier, SemanticColoringProviderRegistry, SemanticColoringProvider, SemanticColoring, SemanticColoringLegend } from 'vs/editor/common/modes';
import { LanguageIdentifier, SemanticTokensProviderRegistry, SemanticTokensProvider, SemanticTokensLegend, SemanticTokens, SemanticTokensEdits } from 'vs/editor/common/modes';
import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry';
import { ILanguageSelection } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
@@ -459,22 +459,22 @@ class SemanticColoringFeature extends Disposable {
class SemanticStyling extends Disposable {
private _caches: WeakMap<SemanticColoringProvider, SemanticColoringProviderStyling>;
private _caches: WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>;
constructor(
private readonly _themeService: IThemeService
) {
super();
this._caches = new WeakMap<SemanticColoringProvider, SemanticColoringProviderStyling>();
this._caches = new WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>();
if (this._themeService) {
// workaround for tests which use undefined... :/
this._register(this._themeService.onThemeChange(() => {
this._caches = new WeakMap<SemanticColoringProvider, SemanticColoringProviderStyling>();
this._caches = new WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>();
}));
}
}
public get(provider: SemanticColoringProvider): SemanticColoringProviderStyling {
public get(provider: SemanticTokensProvider): SemanticColoringProviderStyling {
if (!this._caches.has(provider)) {
this._caches.set(provider, new SemanticColoringProviderStyling(provider.getLegend(), this._themeService));
}
@@ -580,7 +580,7 @@ class SemanticColoringProviderStyling {
private readonly _hashTable: HashTable;
constructor(
private readonly _legend: SemanticColoringLegend,
private readonly _legend: SemanticTokensLegend,
private readonly _themeService: IThemeService
) {
this._hashTable = new HashTable();
@@ -611,13 +611,39 @@ class SemanticColoringProviderStyling {
}
}
const enum SemanticColoringConstants {
/**
* Let's aim at having 8KB buffers if possible...
* So that would be 8192 / (5 * 4) = 409.6 tokens per area
*/
DesiredTokensPerArea = 400,
/**
* Try to keep the total number of areas under 1024 if possible,
* simply compensate by having more tokens per area...
*/
DesiredMaxAreas = 1024,
}
class SemanticTokensResponse {
constructor(
private readonly _provider: SemanticTokensProvider,
public readonly resultId: string | undefined,
public readonly data: Uint32Array
) { }
public dispose(): void {
this._provider.releaseSemanticTokens(this.resultId);
}
}
class ModelSemanticColoring extends Disposable {
private _isDisposed: boolean;
private readonly _model: ITextModel;
private readonly _semanticStyling: SemanticStyling;
private readonly _fetchSemanticTokens: RunOnceScheduler;
private _currentResponse: SemanticColoring | null;
private _currentResponse: SemanticTokensResponse | null;
private _currentRequestCancellationTokenSource: CancellationTokenSource | null;
constructor(model: ITextModel, themeService: IThemeService, stylingProvider: SemanticStyling) {
@@ -626,17 +652,21 @@ class ModelSemanticColoring extends Disposable {
this._isDisposed = false;
this._model = model;
this._semanticStyling = stylingProvider;
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 500));
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 300));
this._currentResponse = null;
this._currentRequestCancellationTokenSource = null;
this._register(this._model.onDidChangeContent(e => this._fetchSemanticTokens.schedule()));
this._register(SemanticColoringProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
this._register(this._model.onDidChangeContent(e => {
if (!this._fetchSemanticTokens.isScheduled()) {
this._fetchSemanticTokens.schedule();
}
}));
this._register(SemanticTokensProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
if (themeService) {
// workaround for tests which use undefined... :/
this._register(themeService.onThemeChange(_ => {
// clear out existing tokens
this._setSemanticTokens(null, null, []);
this._setSemanticTokens(null, null, null, []);
this._fetchSemanticTokens.schedule();
}));
}
@@ -673,90 +703,208 @@ class ModelSemanticColoring extends Disposable {
});
const styling = this._semanticStyling.get(provider);
const request = Promise.resolve(provider.provideSemanticColoring(this._model, this._currentRequestCancellationTokenSource.token));
const lastResultId = this._currentResponse ? this._currentResponse.resultId || null : null;
const request = Promise.resolve(provider.provideSemanticTokens(this._model, lastResultId, null, this._currentRequestCancellationTokenSource.token));
request.then((res) => {
this._currentRequestCancellationTokenSource = null;
contentChangeListener.dispose();
this._setSemanticTokens(res || null, styling, pendingChanges);
this._setSemanticTokens(provider, res || null, styling, pendingChanges);
}, (err) => {
errors.onUnexpectedError(err);
this._currentRequestCancellationTokenSource = null;
contentChangeListener.dispose();
this._setSemanticTokens(null, styling, pendingChanges);
this._setSemanticTokens(provider, null, styling, pendingChanges);
});
}
private _setSemanticTokens(tokens: SemanticColoring | null, styling: SemanticColoringProviderStyling | null, pendingChanges: IModelContentChangedEvent[]): void {
private static _isSemanticTokens(v: SemanticTokens | SemanticTokensEdits): v is SemanticTokens {
return v && !!((<SemanticTokens>v).data);
}
private static _isSemanticTokensEdits(v: SemanticTokens | SemanticTokensEdits): v is SemanticTokensEdits {
return v && Array.isArray((<SemanticTokensEdits>v).edits);
}
private static _copy(src: Uint32Array, srcOffset: number, dest: Uint32Array, destOffset: number, length: number): void {
for (let i = 0; i < length; i++) {
dest[destOffset + i] = src[srcOffset + i];
}
}
private _setSemanticTokens(provider: SemanticTokensProvider | null, tokens: SemanticTokens | SemanticTokensEdits | null, styling: SemanticColoringProviderStyling | null, pendingChanges: IModelContentChangedEvent[]): void {
const currentResponse = this._currentResponse;
if (this._currentResponse) {
this._currentResponse.dispose();
this._currentResponse = null;
}
if (this._isDisposed) {
// disposed!
if (tokens) {
tokens.dispose();
if (provider && tokens) {
provider.releaseSemanticTokens(tokens.resultId);
}
return;
}
this._currentResponse = tokens;
if (!this._currentResponse || !styling) {
if (!provider || !tokens || !styling) {
this._model.setSemanticTokens(null);
return;
}
const result: MultilineTokens2[] = [];
for (const area of this._currentResponse.areas) {
const srcTokens = area.data;
const tokenCount = srcTokens.length / 5;
let destTokens = new Uint32Array(4 * tokenCount);
let destOffset = 0;
for (let i = 0; i < tokenCount; i++) {
const srcOffset = 5 * i;
const deltaLine = srcTokens[srcOffset];
const startCharacter = srcTokens[srcOffset + 1];
const endCharacter = srcTokens[srcOffset + 2];
const tokenTypeIndex = srcTokens[srcOffset + 3];
const tokenModifierSet = srcTokens[srcOffset + 4];
const metadata = styling.getMetadata(tokenTypeIndex, tokenModifierSet);
if (metadata !== Constants.NO_STYLING) {
destTokens[destOffset] = deltaLine;
destTokens[destOffset + 1] = startCharacter;
destTokens[destOffset + 2] = endCharacter;
destTokens[destOffset + 3] = metadata;
destOffset += 4;
if (ModelSemanticColoring._isSemanticTokensEdits(tokens)) {
if (!currentResponse) {
// not possible!
this._model.setSemanticTokens(null);
return;
}
if (tokens.edits.length === 0) {
// nothing to do!
tokens = {
resultId: tokens.resultId,
data: currentResponse.data
};
} else {
let deltaLength = 0;
for (const edit of tokens.edits) {
deltaLength += (edit.data ? edit.data.length : 0) - edit.deleteCount;
}
}
if (destOffset !== destTokens.length) {
destTokens = destTokens.subarray(0, destOffset);
const srcData = currentResponse.data;
const destData = new Uint32Array(srcData.length + deltaLength);
let srcLastStart = srcData.length;
let destLastStart = destData.length;
for (let i = tokens.edits.length - 1; i >= 0; i--) {
const edit = tokens.edits[i];
const copyCount = srcLastStart - (edit.start + edit.deleteCount);
if (copyCount > 0) {
ModelSemanticColoring._copy(srcData, srcLastStart - copyCount, destData, destLastStart - copyCount, copyCount);
destLastStart -= copyCount;
}
if (edit.data) {
ModelSemanticColoring._copy(edit.data, 0, destData, destLastStart - edit.data.length, edit.data.length);
destLastStart -= edit.data.length;
}
srcLastStart = edit.start;
}
if (srcLastStart > 0) {
ModelSemanticColoring._copy(srcData, 0, destData, 0, srcLastStart);
}
tokens = {
resultId: tokens.resultId,
data: destData
};
}
const tokens = new MultilineTokens2(area.line, new SparseEncodedTokens(destTokens));
result.push(tokens);
}
// Adjust incoming semantic tokens
if (pendingChanges.length > 0) {
// More changes occurred while the request was running
// We need to:
// 1. Adjust incoming semantic tokens
// 2. Request them again
for (const change of pendingChanges) {
for (const area of result) {
for (const singleChange of change.changes) {
area.applyEdit(singleChange.range, singleChange.text);
if (ModelSemanticColoring._isSemanticTokens(tokens)) {
this._currentResponse = new SemanticTokensResponse(provider, tokens.resultId, tokens.data);
const srcData = tokens.data;
const tokenCount = (tokens.data.length / 5) | 0;
const tokensPerArea = Math.max(Math.ceil(tokenCount / SemanticColoringConstants.DesiredMaxAreas), SemanticColoringConstants.DesiredTokensPerArea);
const result: MultilineTokens2[] = [];
let tokenIndex = 0;
let lastLineNumber = 1;
let lastStartCharacter = 0;
while (tokenIndex < tokenCount) {
const tokenStartIndex = tokenIndex;
let tokenEndIndex = Math.min(tokenStartIndex + tokensPerArea, tokenCount);
// Keep tokens on the same line in the same area...
if (tokenEndIndex < tokenCount) {
let smallTokenEndIndex = tokenEndIndex;
while (smallTokenEndIndex - 1 > tokenStartIndex && srcData[5 * smallTokenEndIndex] === 0) {
smallTokenEndIndex--;
}
if (smallTokenEndIndex - 1 === tokenStartIndex) {
// there are so many tokens on this line that our area would be empty, we must now go right
let bigTokenEndIndex = tokenEndIndex;
while (bigTokenEndIndex + 1 < tokenCount && srcData[5 * bigTokenEndIndex] === 0) {
bigTokenEndIndex++;
}
tokenEndIndex = bigTokenEndIndex;
} else {
tokenEndIndex = smallTokenEndIndex;
}
}
let destData = new Uint32Array((tokenEndIndex - tokenStartIndex) * 4);
let destOffset = 0;
let areaLine = 0;
while (tokenIndex < tokenEndIndex) {
const srcOffset = 5 * tokenIndex;
const deltaLine = srcData[srcOffset];
const deltaCharacter = srcData[srcOffset + 1];
const lineNumber = lastLineNumber + deltaLine;
const startCharacter = (deltaLine === 0 ? lastStartCharacter + deltaCharacter : deltaCharacter);
const length = srcData[srcOffset + 2];
const tokenTypeIndex = srcData[srcOffset + 3];
const tokenModifierSet = srcData[srcOffset + 4];
const metadata = styling.getMetadata(tokenTypeIndex, tokenModifierSet);
if (metadata !== Constants.NO_STYLING) {
if (areaLine === 0) {
areaLine = lineNumber;
}
destData[destOffset] = lineNumber - areaLine;
destData[destOffset + 1] = startCharacter;
destData[destOffset + 2] = startCharacter + length;
destData[destOffset + 3] = metadata;
destOffset += 4;
}
lastLineNumber = lineNumber;
lastStartCharacter = startCharacter;
tokenIndex++;
}
if (destOffset !== destData.length) {
destData = destData.subarray(0, destOffset);
}
const tokens = new MultilineTokens2(areaLine, new SparseEncodedTokens(destData));
result.push(tokens);
}
this._fetchSemanticTokens.schedule();
// Adjust incoming semantic tokens
if (pendingChanges.length > 0) {
// More changes occurred while the request was running
// We need to:
// 1. Adjust incoming semantic tokens
// 2. Request them again
for (const change of pendingChanges) {
for (const area of result) {
for (const singleChange of change.changes) {
area.applyEdit(singleChange.range, singleChange.text);
}
}
}
if (!this._fetchSemanticTokens.isScheduled()) {
this._fetchSemanticTokens.schedule();
}
}
this._model.setSemanticTokens(result);
return;
}
this._model.setSemanticTokens(result);
this._model.setSemanticTokens(null);
}
private _getSemanticColoringProvider(): SemanticColoringProvider | null {
const result = SemanticColoringProviderRegistry.ordered(this._model);
private _getSemanticColoringProvider(): SemanticTokensProvider | null {
const result = SemanticTokensProviderRegistry.ordered(this._model);
return (result.length > 0 ? result[0] : null);
}
}
@@ -5,7 +5,7 @@
import * as nls from 'vs/nls';
import { Color, RGBA } from 'vs/base/common/color';
import { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder, contrastBorder, editorFindMatchHighlight } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
/**
@@ -15,7 +15,7 @@ export const editorLineHighlight = registerColor('editor.lineHighlightBackground
export const editorLineHighlightBorder = registerColor('editor.lineHighlightBorder', { dark: '#282828', light: '#eeeeee', hc: '#f38518' }, nls.localize('lineHighlightBorderBox', 'Background color for the border around the line at the cursor position.'));
export const editorRangeHighlight = registerColor('editor.rangeHighlightBackground', { dark: '#ffffff0b', light: '#fdff0033', hc: null }, nls.localize('rangeHighlight', 'Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.'), true);
export const editorRangeHighlightBorder = registerColor('editor.rangeHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('rangeHighlightBorder', 'Background color of the border around highlighted ranges.'), true);
export const editorSymbolHighlight = registerColor('editor.symbolHighlightBackground', { dark: editorRangeHighlight, light: editorRangeHighlight, hc: null }, nls.localize('symbolHighlight', 'Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.'), true);
export const editorSymbolHighlight = registerColor('editor.symbolHighlightBackground', { dark: editorFindMatchHighlight, light: editorFindMatchHighlight, hc: null }, nls.localize('symbolHighlight', 'Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.'), true);
export const editorSymbolHighlightBorder = registerColor('editor.symbolHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('symbolHighlightBorder', 'Background color of the border around highlighted symbols.'), true);
export const editorCursorForeground = registerColor('editorCursor.foreground', { dark: '#AEAFAD', light: Color.black, hc: Color.white }, nls.localize('caret', 'Color of the editor cursor.'));
@@ -116,7 +116,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
private _lastVersionId: number;
private _decorations: string[];
private readonly _updateBracketsSoon: RunOnceScheduler;
private _matchBrackets: boolean;
private _matchBrackets: 'never' | 'near' | 'always';
constructor(
editor: ICodeEditor
@@ -132,7 +132,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
this._updateBracketsSoon.schedule();
this._register(editor.onDidChangeCursorPosition((e) => {
if (!this._matchBrackets) {
if (this._matchBrackets === 'never') {
// Early exit if nothing needs to be done!
// Leave some form of early exit check here if you wish to continue being a cursor position change listener ;)
return;
@@ -153,12 +153,13 @@ export class BracketMatchingController extends Disposable implements editorCommo
this._updateBracketsSoon.schedule();
}));
this._register(editor.onDidChangeConfiguration((e) => {
this._matchBrackets = this._editor.getOption(EditorOption.matchBrackets);
if (!this._matchBrackets && this._decorations.length > 0) {
// Remove existing decorations if bracket matching is off
if (e.hasChanged(EditorOption.matchBrackets)) {
this._matchBrackets = this._editor.getOption(EditorOption.matchBrackets);
this._decorations = this._editor.deltaDecorations(this._decorations, []);
this._lastBracketsData = [];
this._lastVersionId = 0;
this._updateBracketsSoon.schedule();
}
this._updateBracketsSoon.schedule();
}));
}
@@ -262,7 +263,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
});
private _updateBrackets(): void {
if (!this._matchBrackets) {
if (this._matchBrackets === 'never') {
return;
}
this._recomputeBrackets();
@@ -332,8 +333,8 @@ export class BracketMatchingController extends Disposable implements editorCommo
} else {
let brackets = model.matchBracket(position);
let options = BracketMatchingController._DECORATION_OPTIONS_WITH_OVERVIEW_RULER;
if (!brackets) {
brackets = model.findEnclosingBrackets(position);
if (!brackets && this._matchBrackets === 'always') {
brackets = model.findEnclosingBrackets(position, 20 /* give at most 20ms to compute */);
options = BracketMatchingController._DECORATION_OPTIONS_WITHOUT_OVERVIEW_RULER;
}
newData[newDataLen++] = new BracketsData(position, brackets, options);
@@ -148,19 +148,29 @@ export class ContextMenuController implements IEditorContribution {
// translate them into other actions
for (let group of groups) {
const [, actions] = group;
let addedItems = 0;
for (const action of actions) {
if (action instanceof SubmenuItemAction) {
const subActions = this._getMenuActions(model, action.item.submenu);
if (subActions.length > 0) {
result.push(new ContextSubMenu(action.label, subActions));
addedItems++;
}
} else {
result.push(action);
addedItems++;
}
}
result.push(new Separator());
if (addedItems) {
result.push(new Separator());
}
}
result.pop(); // remove last separator
if (result.length) {
result.pop(); // remove last separator
}
return result;
}
@@ -7,7 +7,7 @@ import * as dom from 'vs/base/browser/dom';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IDataSource, ITreeNode, ITreeRenderer, ITreeSorter, ITreeFilter } from 'vs/base/browser/ui/tree/tree';
import { values, forEach } from 'vs/base/common/collections';
import { values } from 'vs/base/common/collections';
import { createMatches, FuzzyScore } from 'vs/base/common/filters';
import 'vs/css!./media/outlineTree';
import 'vs/css!./media/symbol-icons';
@@ -22,6 +22,8 @@ import { MarkerSeverity } from 'vs/platform/markers/common/markers';
import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { registerColor, listErrorForeground, listWarningForeground, foreground } from 'vs/platform/theme/common/colorRegistry';
import { IdleValue } from 'vs/base/common/async';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { URI } from 'vs/base/common/uri';
export type OutlineItem = OutlineGroup | OutlineElement;
@@ -278,27 +280,26 @@ export class OutlineFilter implements ITreeFilter<OutlineItem> {
[SymbolKind.TypeParameter]: 'showTypeParameters',
});
private readonly _filteredTypes = new Set<SymbolKind>();
constructor(
private readonly _prefix: string,
@IConfigurationService private readonly _configService: IConfigurationService,
) {
this.update();
}
update() {
this._filteredTypes.clear();
forEach(OutlineFilter.configNameToKind, entry => {
const key = `${this._prefix}.${entry.key}`;
if (this._configService.getValue<boolean>(key) === false) {
this._filteredTypes.add(entry.value);
}
});
}
@ITextResourceConfigurationService private readonly _textResourceConfigService: ITextResourceConfigurationService,
) { }
filter(element: OutlineItem): boolean {
return !(element instanceof OutlineElement) || !this._filteredTypes.has(element.symbol.kind);
const outline = OutlineModel.get(element);
let uri: URI | undefined;
if (outline) {
uri = outline.textModel.uri;
}
if (!(element instanceof OutlineElement)) {
return true;
}
const configName = OutlineFilter.kindToConfigName[element.symbol.kind];
const configKey = `${this._prefix}.${configName}`;
return this._textResourceConfigService.getValue(uri, configKey);
}
}
Loaded 100 of 257 files, more files were not shown because too many files have changed in this diff. Show more